동기 (Synchronous)와 비동기 (Asynchronous) 코드 실행 방식에 대해 설명해보세요.
자바스크립트는 동기식 언어이다
기본적으로 단일 쓰레드와 이벤트 루프(event loop)를 이용한 비동기 방식으로 동작
https://ljtaek2.tistory.com/142
1. 한마디 정리
동기는 코드가 순차적으로 실행되는 방식인 반면
비동기는 이벤트 루프의 동작 방식에 따라 코드 실행 순서가 결정됩니다.
따라서 동기 방식의 경우
코드 실행 순서와 결과를 파악하기 좋아 디버깅에 용이한 반면
코드의 실행 대기 시간 때문에 대규모의 I/O 작업(그리고 네트워크 요청) 등의 작업에서 성능이 저하될 수 있습니다.
비동기 방식의 경우
콜백 지옥과 같은 코드 구조가 발생하거나 코드의 복잡도가 증가되는 단점이 있지만
여러 작업을 동시에 수행할 수 있기 때문에 특히 I/O 작업이 많은 웹 어플리케이션 개발에 있어 성능을 최적화할 수 있습니다.
2. 내가 생각한 꼬리질문
1) 각 방식의 단점 보완 방식?
동기
동기 (Synchronous) 코드 실행 방식에서의 단점은 주로 I/O 작업이 많은 경우에 발생합니다. I/O 작업을 수행하는 동안에는 대기하는 시간이 발생하기 때문에, 다른 작업을 수행하지 못하고 대기해야하는 상황이 발생할 수 있습니다.
1) 비동기 (Asynchronous) 코드 실행 방식 적용
비동기 방식으로 코드를 실행하면, I/O 작업을 대기하지 않고 다른 작업을 수행할 수 있기 때문에, 대기 시간이 줄어들어 성능이 향상됩니다.
2) 멀티스레딩 (Multithreading)
멀티스레딩을 사용하면, 여러 작업을 동시에 수행할 수 있기 때문에 I/O 작업 대기 시간을 최소화할 수 있습니다.
3) 캐시 (Cache)
I/O 작업 결과를 캐시에 저장하여, 동일한 요청이 발생하는 경우에는 I/O 작업을 수행하지 않고 캐시에서 결과를 반환함으로써 성능을 향상시킬 수 있습니다.
4) 프로세스 분리 (Process Isolation)
I/O 작업을 수행하는 프로세스를 분리하여, 다른 작업과 독립적으로 실행시키면서 성능 향상을 꾀할 수 있습니다.
5) 더 나은 하드웨어 사용
더 나은 하드웨어를 사용하여 I/O 작업 대기 시간을 최소화하거나, 더 많은 작업을 수행할 수 있도록 확장성을 개선할 수 있습니다.
비동기
1) Promise나 async/await을 사용하여 콜백 지옥을 방지하고 코드 가독성을 높입니다.
2) 적절한 스레드 풀을 사용하여 CPU 바운드 작업이 블로킹 되는 것을 막습니다.
3) 스케일 아웃을 통해 여러 개의 서버를 사용하여 부하 분산을 처리합니다.
4) 캐싱, 인메모리 데이터베이스 등을 사용하여 I/O 작업의 성능을 개선합니다.
5) 이벤트 루프의 동작 방식을 이해하고 최적화합니다.
2) I/O 작업은 무엇인가요?
I/O는 Input/Output의 약자로, 컴퓨터 시스템에서 데이터를 입력받거나 출력하는 작업을 의미합니다. 이 작업은 주로 파일 시스템, 네트워크 등의 외부 자원과의 상호작용을 포함합니다.
I/O 작업은 CPU가 수행하는 계산 작업과는 다르게 매우 느리고 상대적으로 많은 시간이 필요합니다. 따라서 I/O 작업은 CPU 작업과 분리되어 비동기적으로 처리되는 것이 좋습니다.
Node.js에서는 이러한 I/O 작업을 비동기적으로 처리함으로써 다중 작업 처리 및 높은 처리량, 빠른 응답 속도를 제공할 수 있습니다. 이러한 이유로 Node.js는 I/O 작업 처리를 위한 비동기적인 프로그래밍 방식을 권장하고 있습니다.
3) 비동기 코드 실행 방식에서 코드 실행 순서는 어떻게 결정되나요?
비동기 코드 실행 방식에서 코드 실행 순서는 이벤트 루프의 동작 방식에 따라 결정됩니다.
이벤트 루프는 무한 반복하며, 이벤트 큐에 있는 작업들을 순서대로 실행합니다. 이벤트 큐에는 비동기 작업의 콜백 함수나 타이머, 이벤트 등이 들어있으며, 이벤트 루프는 이벤트 큐에서 작업을 꺼내 실행합니다.
따라서, 비동기 코드에서 콜백 함수가 등록된 시간이나 순서와는 상관없이 작업이 완료된 순서에 따라 실행됩니다. 즉, 작업이 완료되면 이벤트 루프에서 순서대로 처리되는 것입니다.
이러한 이벤트 루프의 동작 방식으로 인해 코드 실행 순서가 예측하기 어렵고, 디버깅이 어려울 수 있습니다. 따라서, 비동기 코드 작성시 콜백 지옥을 방지하고 Promise나 async/await 등을 사용하여 가독성을 높이는 것이 좋습니다.
4-1) 동기 방식으로 작업을 처리하면 안정성이 높아지나요?
동기 방식은 코드의 실행 순서가 보장되므로, 작업의 결과를 바로 사용할 수 있어 안정성이 높아집니다. 즉, 작업이 수행되는 동안 다른 작업을 수행하지 않고 기다리면서 작업의 결과를 사용하기 때문에 예측 가능한 코드 실행이 가능합니다.
4-2) 그럼 비동기 방식은 안정성이 높지 못하다고 하나요?
비동기 방식은 작업의 완료를 기다리지 않고 다음 작업을 수행할 수 있으므로, 전체 애플리케이션이 블로킹되는 현상을 방지할 수 있어 안정성이 높아집니다. 또한, 비동기 방식에서는 다수의 작업을 동시에 처리할 수 있기 때문에 대규모 애플리케이션에서 성능이 더욱 향상될 수 있습니다.
5) Java와 같이 동기 방식으로 성능이 저하될 수 있는데 많이 쓰는 이유가 있나요?
Java가 동기 방식으로 실행되어 성능이 저하될 가능성이 있다는 것은 맞습니다. 그러나 Java는 안정성과 생산성이 높은 언어로 알려져 있어서 많은 기업과 개발자들이 사용하고 있습니다. 또한 Java는 다양한 운영체제와 플랫폼에서 동작하기 때문에 이식성이 뛰어나고, 대규모 시스템 개발에 적합한 언어입니다.
Java는 성능을 개선하기 위한 다양한 기술도 제공합니다. 예를 들어, JIT 컴파일러와 가비지 컬렉터를 사용하여 성능을 향상시킬 수 있습니다. 또한, 멀티스레드 지원과 병렬 처리를 위한 다양한 라이브러리를 제공하여 대규모 시스템의 병렬 처리를 용이하게 합니다.
또한, Java의 생태계는 매우 활성화되어 있습니다. 대규모 오픈소스 프로젝트인 Spring Framework를 비롯하여 다양한 라이브러리와 프레임워크들이 있어서 개발자들은 편리하게 개발할 수 있습니다. 또한, Java는 강력한 보안 기능과 안정성을 제공하기 때문에 기업과 정부 기관에서도 많이 사용됩니다. 이러한 이유들로 인해 Java는 여전히 많이 사용되고 있습니다.
3. 스터디원 꼬리질문
어떤 코드 실행 방식을 선택할지는 코드의 용도와 상황에 따라 달라짐
1) 동기적인 방식이 적합
- UI와 같이 빠른 반응성이 필요한 작업을 수행할 때
2) 비동기적인 방식이 적합
- 네트워크 연결과 같이 시간이 오래 걸리는 작업을 수행할 때
동기 (Synchronous) 코드 실행 방식
정의
- 코드가 순차적으로 실행되는 방식 (코드의 한 줄이 실행될 때까지 다음 줄의 실행을 기다림)
=> 즉, 코드가 실행되는 동안 다른 작업을 수행하지 않고 기다리는 방식
장점
- 코드의 실행 순서를 이해하기 쉽고, 코드 실행 결과를 쉽게 파악할 수 있음 (간단함, 직관적)
- 디버깅이 용이함
단점
- 코드 실행 동안 다른 작업을 수행할 수 없기 때문에, 코드가 실행되는 동안 프로그램이 느려질 수 있음
- 시간이 오래 걸리는 작업을 수행할 때, 다른 작업을 수행하지 못하고 대기해야 함
=> 대규모의 I/O 작업이나 네트워크 요청 등의 작업에서는 성능이 저하될 수 있음
적합 작업
순차적으로 실행되어야 하는 작업에 적합
- 작은 크기의 파일을 읽어오는 작업
- 두 개의 숫자를 더하는 작업
- 변수 값을 증가시키는 작업 등
해당 언어
C / Java / Python / Ruby / PHP
비동기 (Asynchronous) 코드 실행 방식
정의
- 코드 실행 순서가 이벤트 루프의 동작 방식에 따라 결정 (코드의 실행 순서가 보장되지 않는 방식)
=> 즉, 코드의 한 부분이 실행되는 동안에도 다른 부분이 실행될 수 있음
* 실행 방식
- 요청을 보내고, 결과가 오기를 기다리지 않고 다음 코드를 실행
- 결과가 도착하면 콜백 함수나 프라미스를 이용해 처리
=> 이러한 방식을 이용하면 여러 개의 작업을 동시에 수행할 수 있으므로, 대규모의 I/O 작업이나 네트워크 요청 등에서 성능 향상을 기대할 수 있음
장점
- 코드가 실행되는 동안 다른 작업을 수행할 수 있기 때문에, 코드의 실행 속도가 빨라집니다.
- 시간이 오래 걸리는 작업을 수행할 때, 다른 작업을 수행하면서 대기할 필요가 없습니다.
단점
- 코드의 실행 순서가 예측하기 어려우며, 디버깅이 어렵습니다.
- 콜백 지옥(callback hell)과 같은 코드 구조가 발생할 수 있습니다.
- 비동기적인 방식이 코드의 복잡도를 증가시킬 수 있습니다.
적합 작업
이러한 언어들이 대부분 웹 어플리케이션 개발을 위해 사용되기 때문입니다.
웹 어플리케이션은 대부분 시간이 오래 걸리는 I/O 작업이 많기 때문에, 비동기 코드 실행 방식을 사용함으로써 성능을 최적화할 수 있습니다.
- 네트워크 요청
- 대용량 파일 처리
- 데이터베이스에서 데이터를 가져오는 작업 등
해당 언어
JavaScript / Node.js / Rust / Go / Kotlin