Share
Sign In
Lighthouse Dev
[1] - Sync 와 Async 그리고 Blocking과 NonBlocking
김원준
👍
4
❤️
3
😀
1
😘
1
0. 개요
아무것도 모르는 대학생 시절에, 학부 인턴을한 적이 있다.
그때 팀장님이 신입 면접을 보고 오신 뒤, 나에게 질문을 하신 적이 있다.
“oo아 동기와 비동기 차이를 설명해 봐”
동기 - “하나하나 순차적으로 실행하는 것 !”
비동기 - 동시에 실행되는 것 !”
이라고 대답한 기억이 있다.
아마 이렇게 대답한 나는 그 당시에 동기 / 비동기를 아래 사진과 같이 이해하고 있었던 것 같다.
내가 이해한 "동기"
내가 이해한 "비동기"
얼핏 보기엔 맞는 대답이기도 하다.
하지만 지금 와서 생각해 보면
“하나하나 순차적으로 실행하는 것 !”의 대답은, Blocking Sync에 대한 설명일 수도 있고, Blocking Async에 대한 설명일 수도 있다.
또,
“동시에 실행되는 것 !” 의 대답은, NonBlocking Sync일 수도 있고 NonBlocking Async일 수도 있다.
물론, 이론적으론 그렇다.
해당 개념을 잘 모르는 사람에게는, Sync와 Async의 단어 자체는 익숙할 수 있어도, Blocking과 NonBlocking이 앞에 붙는 순간 머리가 아파올 수 있다.
이번 시간에 Blocking / NonBlocking과 Sync / Async에 대해서 간단하게 살펴보자.
들어가기에 앞서 !
💡
제어권
• 제어권은 자신(함수)의 코드를 실행할 권리 같은 것이다. 제어권을 가진 함수는 자신의 코드를 끝까지 실행한 후, 자신을 호출한 함수에게 돌려준다.
💡
종료 호출
• A 함수에서 B 함수를 호출했을 때, A 함수가 B 함수의 결과 값을 기다리느냐의 여부를 의미한다.
용어를 숙지하자 !
1. Blocking? Sync? 그게 뭐야 ?? 🤔
💬
Sync 와 Async. 또 Blocking과 NonBlocking은 “관점”에 차이에 있다.
✅ Blocking / NonBlocking은 호출한 함수가 호출된 함수에게 제어권을 주느냐의 관점
✅ Sync / Async는 호출된 함수의 종료 호출을 호출한 함수가 처리하는지, 호출된 함수가 처리하는지의 관점
이렇게만 봐서는, 이해가 안 될 것 같다. 나라도 그럴 것이다.
2. Blocking과 NonBlocking
2-1. Blocking
→ A함수가 B함수를 호출할 때, B함수가 자신의 작업이 종료되기 전까지 A함수에게 제어권을 돌려주지 않는 것
1.
A함수가 B 함수를 호출하면, 제어권을 B에게 넘긴다.
2.
호출된 B함수는 제어권을 갖고 있기에 함수를 실행한다.
a.
이때! A 함수는 제어권이 없기때문에 (B에게 넘겨주었기 때문에) 함수 실행을 멈춘다.
3.
B함수가 완료되면, A함수에게 제어권을 돌려준다.
a.
잠시 중단되었던 A함수는 다시 함수를 이어나간다.
2-2. NonBlocking
→ A함수가 B함수를 호출할 때, B함수가 제어권을 바로 A함수에게 넘겨주면서, A함수가 다른 일을 할 수 있도록 하는 것
1.
A함수가 B함수를 호출하여 실행시킨다.
a.
이때! 제어권은 계속 A가 가지고 있기 때문에, 호출한 이후에도 A는 자신의 코드를 계속 실행시킨다.
3. Sync와 Async
3-1. Sync
플로우가 순차적으로 이뤄져야 함.
A함수가 B함수를 호출 할 때, B함수의 결과값이 나왔는지 A함수가 계속해서 관여하는 것.
B함수의 종료 여부를 계속해서 신경 쓴다.
✔️ 결과값 & 제어권의 반환이 동시에 이뤄짐
3-2. Async
플로우가 순서에 영향을 받지 않음.
A함수가 B함수를 호출 할 때, B함수의 결과를 B함수가 처리하는 것. (Callback 이용)
B함수의 종료 여부를 신경 쓰지 않는다.
✔️ 결과값 & 제어권의 반환이 동시에 이뤄지지 않음
4. 크로스오버 조합
4-1. Blocking - Sync
💡
한 줄 요약 : 가장 보편적으로 이해하고 있는 동기 - 기다릴 가치가 있네 !
A 함수가 B 함수를 호출했을 때, A 함수는 작업을 중단한다. (제어권을 넘겨줬기에 !!) - Blocking
호출된 함수B의 리턴 값을 A함수가 필요로 한다. (함수의 종료와 결과 값 반환을 신경 쓴다.) + 제어권의 반환과 결과 값의 반환이 일치한다. - Sync
🤔언제 쓸까?
→ 다른 작업의 결과가 자신의 작업에 영향을 주는. 즉, 순차적인 의존성이 있는 작업을 처리할 때.
4-2. NonBlocking - Sync
💡
한 줄 요약 : 동기이지만, 동시에 실행이 가능하다 !! (feat. 컨텍스트 스위칭)
A 함수가 B 함수를 호출해도, A 함수는 작업을 계속 이어나간다. - NonBlocking
호출된 함수 B의 종료를 A가 관리한다. + 결과값의 반환과 제어권의 반환이 일치한다. - Sync
결과값의 반환과 제어권의 반환이 일치한다.
“응 아직 안 끝남” 역시 결과값 !!! (안끝났다는 결과값)
🤔언제 쓸까?
→ 브라우저에서 프로그램을 다운로드 할 때 !!
1.
브라우저에서 다운로드 버튼을 누르면 백그라운드에서 다운로드 진행
2.
다운로드 중에 브라우저에서 다른 작업 가능 ! (NonBlocking)
3.
다른작업 중에도, 브라우저는 계속해서 다운로드 상태 확인 (로딩%라든지.. 완료 되었는지.. 실패했는지 .. 등등)
4.
다운로드가 완료 되어야만 바로 다음 작업이 수행됨!
(3&4 Sync)
4-3. NonBlocking - Async
💡
한 줄 요약 : 가장 보편적으로 이해하고 있는 비동기 !! - 각개전투 !
A 함수가 B 함수를 호출해도, A 함수는 작업을 계속 이어나간다. - NonBlocking
B함수의 종료를 A함수가 신경 쓰지 않음(A프로세스에 B의 리턴값이 중요하지 않다.) + 결과값의 반환과 제어권의 반환이 일치하지 않는다. - Async
🤔언제 쓸까?
→ 호출하는 함수에 종료 여부 / 결과 값에 연연하지 않는 & 파일/네트워크 I/O 등 동시 작업을 필요로 하는 프로세스에서 !
4-4. Blocking - Async
💡
한 줄 요약 : 비효율의 끝판왕 !! - 전설의 포켓몬
A 함수가 B 함수를 호출했을 때, A 함수는 작업을 중단한다. - Blocking
B함수의 종료를 A함수가 신경 쓰지 않음(A프로세스에 B의 리턴 값이 중요하지 않다.) . + 결과값의 반환과 제어권의 반환이 일치하지 않는다. - Async
✔️B함수가 끝나기를 기껏 기다려 놓고, 결과값 역시 사용하지 않아버리는 ?!!?!
🤔언제쓸까?
왜 쓸까?
사용하는 경우는 대부분 개발자의 실수인 anti-pattern인 경우라고 한다.
node & mysql 간의 통신에서 사용된다고 하니, 관심이 있다면 한번 찾아보는 걸 권한다.
5. NonBlocking Sync vs NonBlocking Async
가만 살펴보니, NonBlocking Sync와 NonBlocking Async는 다른 작업이 진행 중이더라도(함수가 호출 중 이더라도) 중단하지 않고 프로세스를 이어나갈 수 있다.
그렇다면 여기서 한 가지 의문이 든다.
“우리의 목표는 다른 함수를 호출해도 중단 없이 플로우를 이어나가는 것 아닌가? 복잡하게 Async로 코딩할 필요 없는 거 아니야? ”
사실 이번 발표를 준비하면서 끊임없이 들었던 의문이기도 하다.
그렇다면 NonBlocking Sync와 NonBlocking Async의 결정적인 차이.
다시 말해 무엇을 위해서 Sync / Async를 구분지어 사용&개발 할까?
쉬운 이해를 위해 예를 들어 설명해보겠다.
1️⃣
NonBlocking - Sync
1️⃣프로젝트를 맡고있는 1️⃣팀은 팀장이 업무 A, B, C를 사원 a, b, c에게 시키려고 한다.
이때 해당 업무는 업무 특성상 A업무가 완료되어야 그 다음 업무인 B로 순차적으로 이어나갈 수 있는 상황이다.
👨🏻 팀장 : 사원 a님, A업무 처리해주세요.
(👨🏻 팀장님은 다른 업무 중 …)
👦🏻 사원a : 네, 알겠습니다 ! (A 처리 중..)
👨🏻 팀장 : a님 완료했나요?
👦🏻 사원a : 아직 완료 못했습니다 !
👨🏻 팀장 : a님 완료했나요?
👦🏻 사원a : 완료했습니다 !!
👨🏻 팀장 : 감사합니다. 곧 바로 b님, B업무 처리 부탁드릴게요.
(👨🏻 팀장님은 다른 업무 중 …)
👨🏻‍🦰 사원b : 네, 알겠습니다 !! (B 처리 중..)
👨🏻 팀장 : b님 B업무 완료했나요?
이후 생략...
2️⃣
NonBlocking - Async
2️⃣프로젝트를 맡고 있는 2️⃣팀은 팀장이 업무 A, B, C를 사원 a, b, c에게 시키려고 한다.
이때 해당 업무A, B, C는 업무 간의 영향이 없다.
👨🏻 팀장 : 사원 a님, A업무 처리해주세요.
👨🏻 팀장 : 사원 b님, B업무 처리해주세요.
👨🏻 팀장 : 사원 c님, C업무 처리해주세요.
(👨🏻 팀장님은 다른 업무 중 …)
👩🏻‍🦰 사원c : 팀장님, C업무 완료했습니다.
👦🏻 사원a : 팀장님, A업무 완료했습니다.
👨🏻‍🦰 사원b : 팀장님, B업무 완료했습니다.
1번 케이스를 먼저 살펴보자. 팀장님 (제어권을 가진 main 함수)이 사원들에게 업무를 지시하는 상황이다. 팀장님은 업무를 지시하고 다른 업무를 처리하고 있다(NonBlocking). 하지만 업무 특성상 A업무가 완료되어야 B 업무가 수행될 수 있는 순차적인 경향을 보이고 있다(Sync).
2번 케이스 역시 팀장님은 업무를 지시하고 다른 업무를 처리하고 있다(NonBlocking). 업무 특성상 동시에 진행되어도 무방한 상황이다. 그래서인지 업무가 완료되는 시기도 모두 다르다.
정리하자면
1번 케이스에서 팀장님은 업무를 지시함과 동시에 다른 업무를 진행하고 있다. 하지만 전체 프로젝트 플로우에서 A업무가 완료되어야 B업무를 수행할 수 있는 등 프로젝트가 순차적으로 진행되어야 한다.
2번 케이스 역시 팀장님은 업무를 지시함과 동시에 다른 업무를 진행하고 있다. 하지만 프로젝트 내부 업무 간의 영향이 없는 탓에, 모든 사원들이 각자 맡은 업무를 동시에 진행하고 있다.
마무리
사실 Blocking과 NonBlocking. Sync와 Async의 개념은 지독하게 추상적이라고 생각한다.
어느 레벨에서 바라보느냐의 관점 차이도 있겠고, 여러 포스팅을 찾아보면서 느낀 점이지만 전부 예시를 들어서 설명하고 있고 설명하는 방식이 모두 다르다. 특히 Sync와 Async에서. 그래서 더 헷갈렸던 것 같다.
해당 조합들을 대용량 트래픽 환경에서의 File I/O, Network I/O 등 꼭 필요한 케이스에서는 성능과 부하 분산에 효율적이기 때문에, 꼭 필요하다고 생각한다. 하지만 그렇지 상황에 맞지 않은 경우를 사용하였다가 오히려 역효과를 낼 수도 있다고 생각한다.(실제로 FastAPI 공식문서에서도, 잘 모르겠으면 그냥 def를 쓰라고 권하고있다.)
⭐어떤 조합이든 상황에 맞게 사용하는게 제일 효율적일 것 같다 !⭐
다음 시간에는
1.
파이썬에서의 Sync, Async 처리
2.
FastAPI에서 비동기 처리가 가능한 이유
3.
Sync / Async, FastAPI에서의 코드 예제
4.
(feat. 비동기가 아닐때에, def를 권장하는 이유)
까지 다뤄볼 예정이다.
출처
Kp
Subscribe to 'kpmg-lighthouse'
Welcome to 'kpmg-lighthouse'!
By subscribing to my site, you'll be the first to receive notifications and emails about the latest updates, including new posts.
Join SlashPage and subscribe to 'kpmg-lighthouse'!
Subscribe
👍
4
❤️
3
😀
1
😘
1
Lighthouse
TDD(Test-Driven Development)
안녕하세요, 오늘은 TDD(Test-Driven Development)에 대해 이야기하려 합니다. TDD 소프트웨어 개발 방법론 중 하나로, 개발 과정에서 테스트를 우선하여 작성하고 이를 통과시키는 것에 초점을 두는 방법론입니다. 코드를 작성하기 이전에 테스트 케이스를 작성하고, 이를 통과하기 위한 그에 맞는 기능을 작성하는 작업을 반복하여 개발합니다. TDD의 장점과 한계 TDD의 장점: 품질 향상: 개발자는 코드의 동작을 확실히 이해하고 테스트 케이스를 통해 코드의 정확성을 검증할 수 있어, 더 견고하고 안정적인 코드를 작성할 수 있습니다. 리팩토링 지원: 코드를 작은 단위로 분리하고 테스트 가능한 형태로 작성하여 코드의 구조와 설계를 개선하기 쉽게 합니다. 빠른 피드백: 작은 단위의 테스트를 빠르게 실행하고 결과를 확인하여 버그를 빠르게 발견하고 수정할 수 있으며, 코드 변경에 대한 피드백을 신속하게 받을 수 있습니다. 협업 강화: 테스트 코드가 개발 프로세스의 일부로 문서화되어 있어 다른 개발자들과의 협업을 용이하게 하며, 코드의 동작을 이해하고 검증하는 데 도움이 됩니다. TDD의 한계: 시간과 노력: 테스트 코드를 작성하기 위해 추가적인 시간과 노력이 필요하며, 개발 시간이 늘어날 수 있습니다. 설계에 대한 이해: 테스트 케이스를 작성하기 위해 개발자는 코드의 설계에 대한 깊은 이해가 필요하며, 이를 갖추지 않으면 테스트 케이스가 미흡해질 수 있습니다. 복잡한 시나리오의 테스트: 복잡한 시나리오나 UI, 성능 테스트 등은 TDD로 테스트하기 어려울 수 있습니다. 변동이 많은 요구사항: 요구사항이 자주 변경되는 경우, 테스트 케이스를 계속 수정해야 하는 상황이 발생할 수 있습니다. 출처: https://semaphoreci.com/wp-content/uploads/2022/02/tdd-vs-waterfall.webp 이러한 장점과 한계로 인해 TDD는 초기에는 추가 비용이 들 수 있지만, 시간이 지남에 따라 비용을 절감할 수 있는 특징을 지녔습니다. TDD의 사이클 Lifecycle of the Test-Driven Development method 출처: https://ko.wikipedia.org/wiki/테스트_주도_개발 Write Test: 기능을 검증할 테스트 케이스를 작성
Lighthouse
파이썬의 동시성 관리 : 코루틴(Corutine) 上
0. 들어가기 앞서 지난 시간에는 파이썬의 GIL 제약과 그 제약으로 인해 “찐”효율을 내지 못하는 멀티 스레드 프로그래밍에 대해서 알아보았다. 이번 시간에는 파이썬 비동기의 핵심 키워드 네이티브 코루틴인 Asyncio, async, await를 이해하기 전 이것들의 근간이라 불리는 코루틴(Corutine)에 대해서 알아보자. 들어가기 앞서, 복습 차원에서 지난 시간 내용을 간략하게 정리하자 1. 제네레이터 1.1. 제네레이터 제네레이터는 쉽게 말해서, 여러개의 데이터를 미리 만들어 놓지 않고 필요한 때마다 즉석에서 하나씩 만들어낼 수 있는 객체를 의미한다. 일반적인 함수와 달리 상태를 유지할 수 있다. 즉, 제네레이터는 yield 표현식을 사용하여 값을 반환하고, 다음 호출 시 마지막으로 실행된 yield 표현식 이후부터 실행을 재개한다. 일반함수는 return을 만나면 실행이 끝나버린다. 하지만 제네레이터는 yield 구문에서 “일시정지”의 상태로 값을 외부로 내보낸다. 그 이후에 필요할 때 다시 실행 흐름을 이어나갈 수 있다. 함수 내부에서 사용된 지역 변수등이 메모리에 그대로 유지되어 있기 때문이다. 아래 코드를 살펴보자. 함수 return_abc()는, 알파벳을 1초마다 하나하나 리스트에 적재하는 코드이다. print를 찍어본다면 어떻게 될까? 너무 당연한 결과이다. 그렇다면 해당 함수를 for loop에 돌려보면 어떻게 될까? 이 결과 역시 너무나도 쉽게 예상할 수 있다. 여기서 3초라는 시간을 잘 기억해주길 바란다. 위에서 제네레이터는 데이터를 미리 만들어두지 않고, 필요할 때마다 하나씩 만들어내는 객체를 뜻한다 했다. 이것도 코드를 통해 알아보자. 뭔가 위의 코드랑 별로 달라진게 없어보인다. print를 찍어보자. !! 예상했던 것과는 달리 제네레이터가 출력 되었다 !! 위에서 언급했던 것처럼 제네레이터는 “필요할 때마다” “하나씩” 만들어 낸다고 했으니, 한번 for문을 통해서 “하나씩” 값을 받아와 보자.
😍
1
donggyun_woo
FastAPI 특징 with Pydantic
이번 글에서는 python FastAPI의 특징과 FastAPI내에서 Pydantic을 사용한 코드를 확인해 보겠습니다. Fast API Fast API란? FastAPI는 Python 프레임워크 중 하나입니다. Python 프레임워크들 중 django, flask 와 같이 비교를 많이 하며, 빠른 속도로 인해 인기가 많아진 프레임워크입니다. FastAPI에서 제공하는 기능들을 간략히 보면 아래와 같습니다. API 문서 자동 생성 (Swagger와 ReDoc 스타일 동일) 의존성 주입 위주의 설계를 통한 DB 등에 대한 관리 편리 비동기 동작으로 빠른 성능 보장 (Starlette) Pydantic을 사용한 Validation 체크 뛰어난 공식문서 가이드 Python Framework 깃허브 스타 github star history 그래프를 보면 FastAPI(노란색)의 스타가 급격히 증가하는 것을 확인 할 수 있습니다. 그래프를 통해 FastAPI를 많이 사용한다는 의미는 될 수 없겠지만, 개발자들 사이에서 관심을 많이 갖고 있는것은 확인 할 수 있을것 같습니다. FastAPI의 특징 특징들을 Fast API 공식문서를 통해 자세하게 확인해 보겠습니다. 파이썬 3.8+ 버전의 Type hint를 사용하는 트랜디하고 높은 성능을 가진 파이썬 프레임워크 빠름: NodeJS 및 Go와 동등한 매우 높은 성능을 제공 실제 파이썬 기반의 프레임워크들을 비교한 내용을 확인해 보면 성능이 상위에 존재하는 것을 확인 할 수 있습니다. 빠른 코딩: 기능 개발 속도를 약 200%~300% 향상 버그 감소: 인간(개발자)이 유발한 오류의 약 40% 감소 직관적: 뛰어난 편집기 지원. 디버깅 시간이 줄어듭니다.
👍🟩😘😀👍🏻
6