1. 프로그래밍의 관점에서 비동기
🔗 https://velog.io/@pexe99/JavaScript-커피와-함께하는-동기와-비동기
🔗 https://www.youtube.com/watch?v=EJNBLD3X2yg&t=76s
🔗 https://www.youtube.com/watch?v=EJNBLD3X2yg&list=PLcXyemr8ZeoT-_8yBc_p_lVwRRqUaN8ET&index=21
이 글은 쉬운코드님 유투브 강의 듣기 + 따로 공부해서 정리한 글입니다.
🍌 동기[sysncronous | 동시에 일어나는]
- 순차적으로 실행
- 코드 한줄, 한줄 실행이 끝난 뒤 다음 코드로 넘어가는 처리 방식
- 동시에 일어난다는 뜻을 가진다.
- 어떤 것을 요청하면 이에 대한 결과가 동시에 일어난다는 뜻입
- 요청을 한다면 얼마나 시간이 걸려도 그 자리에서 결과가 주어져야 한다.
- 즉, 여러 작업(task)들을 순차적으로 실행하도록 개발
🍌 비동기[asyncronous | 동시에 일어나지 않음]
- 동시에 일어나지 않음을 의미
- 어떤 것에 대한 요청에 의한 결과가 동시에 일어나지 않음을 의미
- 요청해도 이를 즉시 처리하지 않아 결과가 이후에 나오게 된다.
- 즉, 여러 개의 요청을 동시에, 독립적으로 처리할 수 있다는 의미입니다.
- 실행이 오래걸리는 코드라면, 효율성 측면에서 비동기로 실행하는 것이 더 좋다.
- 코드 실행 후, 완료 여부와 관계없이 다음 코드로 넘어가는 처리 방식[다른 작업을 동시에 수행]
🍌 예시를 들어보자
네 가지 음식 준비하는 방법이 있다. 김치썰기, 스팸 굽기, 국 끓이기, 햇반 데우기…
먼저, synchronous
하게 음식을 준비해 볼까?
- 차근 차근 준비하는 것을 말함
- 너무 오래 걸림
두 번째로, asynchronous
하게 음식 준비해볼까? ver1
- 두 명이서 음식 준비하기 각자 역할 분담
- 시간 단축
그럼 더 빠르게 asynchronous
하게 음식 준비해볼까? ver2
- 사람을 더 데리고 오기
- 사람 4명을 데리고 옴
하지만, 사람이 너무 많이 필요해… 혼자 할 햇반은 전자레인지가 데우는 거니까 나는 다른 걸 같이 할 수 있지 않을까? asynchronous
하게 음식 준비해볼까? ver3
저 위에가 최선일까? 아니? 친구 한명만 더 데려오자 asynchronous
하게 음식 준비해볼까? ver4
- 각 사람이
thread
를 의미
- 햇반을 데울 때 쓰는 전자레인지나, 국 끓일 때 쓰는 가스레인지를
I/O
- 즉 아래와 같은 방식을
non-block I/O
라고 할 수 있다.
🍌 그렇다면.. 비동기가 좋기만 할까?
동기 방식
- 매우 직관적. 어떤 작업을 실행하면 끝날때까지, 그리고 순차적으로 진행하기 때문
- 하지만, 결과가 주어질 때까지 아무것도 못하고 대기해야 한다.
비동기 방식
- 결과가 주어지기 전까지 다른 작업을 할 수 있기 때문에 효율적
- 하지만 동기 방식에 비해 직관적이지 못하고 복잡하다는 단점
그렇다면… 비동기 동작 예시를 봐보자
setTimeout(callback, ms)
console.log('1등!');
setTimeout(function(){
console.log('2등!')
}. 2000);
setTimeout(function(){
console.log('3등');
})
2. 비동기 프로그래밍 ≠ 멀티스레딩
🍌 asynchronous programming
🍌 multithreading
- asynchronous programming의 한 종류
🍌 asynchronous programming을 가능하게 하는 것은
- multi-threads
- 장점 : 멀티코어 활용 가능
- 단점 : 스레드를 많이 만들게 되면.. 컨텍스트 스위칭 시 비용이 많아질 수 있음
레이스 컨디션
발생 가능
- 두 개이상의 프로세스가 공통 자원을 병행적으로 읽거나 쓸 때, 공용 데이터에 대한 접근이 어떤 순서에 따라 이루어졌는지에 따라 그 실행 결과가 달라지는 것
- non-block I/O
- 장점 : 싱글스레드여도 여러 가지 일을 하게 해줌
- 두 가지를 잘 버무리면, 적은 스레드로도 좋은 성능을 낼 수 있다.
🍌 자바스크립트는 싱글스레드
💡 파란색과 녹색은 스레드들이 속한 메모리 영역
싱글 스레드
- 싱글 스레드를 가지는 프로세스
- 스레드가 나오기 전에 프로세스만의 메모리 구조
- 한 번에 하나의 작업만 수행 할 수 있다.(이전 작업이 완료되어야지만 다음 작업을 수행)
왜 자바스크립트는 싱글 스레드일까?
- JavaScript는 call stack이 하나이기 때문에 싱글 스레드인 것
백엔드 프로그래밍의 추세는 스레드를 적게 쓰면서도 non-block I/O를 통해 전체 처리량을 늘리는 방향으로 발전
3. I/O 관점에서 비동기
🍌 non-blocking, blocking이 뭘까?
🔗 https://adrianmejia.com/asynchronous-vs-synchronous-handling-concurrency-in-javascript/
🔗 https://adrianmejia.com/asynchronous-vs-synchronous-handling-concurrency-in-javascript/
동기모델
- 직렬적[↔ 비동기 : 병렬적]
Blocking
을 확인 가능
- 앞에서 스팸 굽기가 끝날 때까지 아무것도 하지 못하는 상황
- 즉, 동기적인 작업에 따라 이후 작업이 막히게 된 것
- 반대로 작업이 막히지 않으면 Non-Blocking
그렇다면.. 동기는 Blocking이고 비동기는 Non-Blocking일까? 비슷하면서도 다른 개념이다.
쉬운 코드님의 생각으로 I/O multiplexing(select/poll)
의 경우, noti를 받는 것이 아니라 요청자가 결과나 완료를 챙겨야 하기에 Asynchronous
이 더 맞는 것 같으며 어떻게 사용하지는에 따라 blocking이 될 수 도 non-blocking이 될 수도 있다. 또한 read/write의 non-blocking으로 돼서 Non-blocking
이 좀 더 맞는 것 같다고 하심
🔗 https://developer.ibm.com/articles/l-async/
제어
에서의 차이
[Blocking ]
- 직접 제어할 수 없는 대상의 작업이 끝날 때까지 제어권을 넘겨주지 않는 것입니다.
- 사전적인 정의로는 막혀버린, 제한된, 대기하는 상태를 의미합니다.
- 호출된 함수가 자신이 할 일을 모두 마칠 때까지 제어권을 계속 가지고서 호출한 함수에게 바로 돌려주지 않는 경우에 해당합니다.
[ Non-Blocking ]
- 직접 제어할 수 없는 대상의 작업 처리 여부와 상관이 없습니다.
- Blocking과는 반대되는 개념입니다.
- 호출된 함수가 자신이 할 일을 마치지 않았더라도 바로 제어권을 건내주는 경우에 해당합니다.
asynchronous I/O
- 정의하자면, 요청자가 따로 챙길 필요 없이 os로부터 noti를 받거나 작업을 시작할 때 callback으로 os에서 알아서 callback 실행하는 경우
문맥에 따라서.. CASE 1
- synchronous I/O = block I/O
- asynchronous I/O = non-block I/O
문맥에 따라서.. CASE 2
- synchronous I/O : 요청자가 I/O 완료까지[결과까지] 챙겨야 할 때
- asynchronous I/O : 완료를 noti 주거나 callback으로 처리
문맥에 따라서.. CASE 3
- asynchronous I/O : block I/O를 다른 thread에서 실행
- block 받는 게 싫어서 스레드에 block I/O 처리 후 최종 결과를 합쳐서 처리
4. 백엔드 아키텍처 관점
하나의 서비스는 기능과 역할에 따라 여러 개의 마이크로 서비스로 구성
되고 이들 사이에는 빈번하게 커뮤니케이션이 발생 ⇒ 커뮤니케이션 방법에 따라 부르는 것이 달라짐
🍌 Synchronous communication
- 하나의 응답이 올 때까지 대기했다가 처리 처리
- API를 전달해서 커뮤니케이션
- C가 응답 불능에 빠지면 B, A 또한 영향을 받아 비정상적인 상태로 가서 전체 응답 불능 상태로 전체 서비스 장애까지 올 수 있음
🍌 Asynchronous communication
- Synchronous communication의 문제를 해결하기 위함
- Message Q라는 버퍼를 이용 ⇒ 처리가 느림(한쪽으로 전달만 해야 하는 상황에서 사용)
- C가 장애에 빠져도 영향을 받지 않음, 일부 서비스는 문제가 생기나 전체 서비스 장애까지 가지는 않게 됨
그렇다면… 모든 걸 Message Q로? 언제 API를 써야 할까?
- A에서 B에서 제공하는 데이터를 필요로 하다면 그것은 API로 구현해야 함