최근 스프링부트를 통해 LLM과 채팅을 해야하는 API를 개발중이었는데 응답을 스트리밍으로 받아야 해서 비동기 통신이 필요한 상황이었다. 그래서 webflux의 WebClient를 통해 개발하였다.
WebClient가 비동기와 논블로킹 방식으로 동작한다는 것을 알고는 있었지만 차이가 정확하게 무엇진지 궁금했다.
대충 동기는 함수의 완료를 기다리고 비동기는 함수의 완료를 기다리지 않는다는 것은 알고 있었고
블로킹과 논블로킹 또한 이와 비슷하게 동작하는 정도만 알고 있고 정확하게 어떤 차이가 있는지는 알고 있지 못했다.
그래서 궁금함을 참지 못하고 차이를 찾아보았고 앞으로 헷갈리지 않기 위해 오랜만이지만 글로 남겨야겠다 생각했다.
동기(Synchronous)
동기 방식은 작업이 순차적으로 실행된다. 현재 작업이 완료될 때까지 다음 작업은 대기한다.
특징
- 작업의 순서가 보장된다.
- 구현이 비교적 간단하고 직관적이다.
- 작업 간의 의존성이 높아질 수 있다.
- 긴 작업이 있는 경우 전체 흐름이 지연될 수 있다.
비동기(Asynchronous)
비동기 방식은 작업이 독립적으로 실행된다. 하나의 작업이 시작되면 그 작업이 끝나기를 기다리지 않고 다른 작업을 시작한다. 비동기 방식은 주로 I/O 작업이나 네트워크 요청과 같이 시간이 오래 걸리는 작업에 사용된다.
특징
- 작업의 순서가 보장되지 않습니다.
- 응답 시간을 줄이고 자원을 효율적으로 사용할 수 있습니다.
- 복잡한 동시성 문제를 해결할 필요가 있습니다.
- 더 복잡한 오류 처리와 디버깅이 필요할 수 있습니다.
블로킹(Blocking)
블로킹 방식에서는 작업이 완료될 때까지 현재 스레드가 대기한다. I/O 작업이나 어떤 자원을 기다리는 동안 스레드는 아무 것도 하지 않고 기다린다.
특징
- 단순하고 직관적이다.
- 코드가 이해하기 쉽고 디버깅이 용이하다.
- 자원을 기다리는 동안 다른 작업을 수행하지 못해 비효율적일 수 있다.
- 응답 시간이 길어질 수 있다.
논블로킹(Non-blocking)
논블로킹 방식에서는 작업이 즉시 완료되지 않더라도 현재 스레드는 계속해서 다른 작업을 수행할 수 있다. 작업이 완료되면 나중에 결과를 처리하는 방식이다.
특징
- 자원을 기다리는 동안 다른 작업을 수행할 수 있어 효율적이다.
- 응답성이 높아진다.
- 코드가 복잡해지고 디버깅이 어려울 수 있다.
- 콜백 함수를 통해 작업 완료를 처리해야 한다.
동작의 초점: 비동기는 "완료 시점"에 초점을 맞추며 사건이 언제 일어날지를 다룹니다. 반면, 논블로킹은 "시작 시점"에 초점을 맞추어 호출 시 즉시 반환 여부를 다룬다.
주 사용 상황: 비동기는 보통 프로세스나 스레드 간의 비동기 작업 실행에 사용되며 결과 처리 방법에 대한 명확한 정의가 필요하다. 논블로킹은 주로 멀티스레드 프로그래밍에서 자원 접근에 사용되어 스레드가 블록되지 않도록 한다.
응답성 개선: 둘 다 시스템의 응답성을 개선하지만 비동기적 방식은 작업의 완료를 기다리지 않다. 논블로킹 방식은 접근 하려는 자원이 바로 사용 가능한 상태가 아니면 즉시 다른 작업을 수행한다.
동기와 블로킹의 경우에는 보통 처음 개발을 하는 방식이라 익숙한 내용이었고 개발할때에도 순서대로 만처리하니 편하다는 생각이 들었다. 하지만 비동기와 논블로킹 방식의 프로그래밍을 해보니 직관적이지가 않아 개발하기가 어렵긴 했다.
(동기와 비동기) 그리고 (블로킹과 논블로킹)의 차이는 무었일까? 생각해 보았다.
내가 생각한 결과는 (동기와 비동기)는 실행 순서와 프로세스를 다루고 (블로킹과 논블로킹)는 컴퓨터의 자원을 다루는 내용이라는 생각이 들었다.