
동기 방식에서는 어떤 작업이 순차적으로 실행된다. 즉, 한 작업이 끝나야 다음 작업이 시작할 수 있다. 예를 들어, taskA, taskB, taskC 순으로 작업이 있다면 taskB는 taskA가 끝나야 작업을 시작할 수 있고, taskC는 taksB가 끝나야 작업을 시작할 수 있다. 이는 코드의 흐름을 이해하기 쉽게 하지만, 한 작업이 오래 걸릴 경우 프로그램 전체의 성능이 느려질 수 있다.
전통적인 Spring Freamwork 및 Spring MVC는 주로 동기식 방식으로 작동한다. 클라이언트의 HTTP 요청을 받으면, 서버는 해당 요청을 처리하고 응답을 반환하는 동안 클라이언트는 그 결과를 기다리게 된다. 이러한 처리 방식은 간단하고 직관적이지만, 요청 처리 시간이 길어지거나 대량의 요청이 동시에 발생할 경우 성능에 제한이 있을 수 있다.
그러나 Spring 5 이후로는 Spring WebFlux라는 새로운 프레임워크를 도입하여 리액티브 프로그래밍과 비동기 처리를 지원한다. Spring WebFlux는 비동기적인 요청 처리를 가능하게 하여, 서버의 확장성과 성능을 개선할 수 있따.
따라서 Spring을 사용하는 백엔드 개발이 동기식만을 사용하는 것이 아니다. 예를 들어서 SSE를 통한 실시간 알림 기능와 같은 기능에서는 비동기식으로 동작해야한다. (만약 알림 기능이 동기식이라면 알림을 생성하고 전달하는 동안 사용자의 다른 작업들이 모두 대기 상태가 되어야 하기 때문)

동기 방식과 다르게 비동기 방식에서는 작업이 백그라운드에서 실행된다. 즉, 한 작업이 완료되기를 기다리지 않고 다음 작업을 시작할 수 있다. 위의 예제에서 자신보다 앞에 있는 task를 기다리지 않고 바로 다음 작업을 수행한다. 작업 롼료 시점에 콜백 함수 등을 통해 결과를 처리할 수 있다. 아 방식은 프로그램의 효율성을 높일 수 있지만, 코드의 복잡성이 증가하며, 동시성을 관리해야 하는 문제가 발생할 수 있다.
JavaScript에서는 특히 웹 브라우저에서 실행되는 경우 비동기 처리를 많이 사용합니다. 이는 주로 I/O 작업 (예: 네트워크 요청, 파일 읽기 등)을 처리할 때 유용하며, 이러한 작업들은 종종 시간이 많이 걸릴 수 있고, 동기적으로 처리할 경우 사용자 인터페이스가 차단될 수 있기 때문이다.
JS는 비동기 작업을 처리하기 위해 콜백(callback), 프로미스(promise), async/await와 같은 여러 가지 패턴과 기능을 제공한다.
비동기 방식은 작업이 병렬로 실행될 수 있지만, 그것이 항상 그렇다는 것을 의미하지는 않다. 비동기적으로 시작된 작업들이 병렬로 실행되려면, 이러한 작업들이 서로 독립적이고, 한 작업의 완료가 다른 작업의 시작에 영향을 미치지 않아야 한다.
JS는 싱글 스레드 언어이기 때문에, 하나의 스레드에서 동시에 하나의 작업만 처리할 수 있다. 그러나 JS는 이벤트 루프(event loop)라는 매커니즘을 사용하여 비동기 작업을 관리한다. 이벤트 루프는 실행할 작업이 없으면 비동기 작업이 완료될 때까지 기다리고, 비동기 작업이 완료되면 그에 따른 결과를 처리한다. 이를 통해 JS는 동시에 하나의 작업만 처리하면서도 비동기 작업을 효율적으로 관리할 수 있게 된다.
따라서 "비동기 작업이 병렬적으로 실행된다"고 이해하는 것은 완전히 정확하지는 않다. 더 정확하게는 "비동기 작업이 백그라운드에서 동시에 실행될 수 있고, 이러한 작업들의 완료 순서에 따라 결과를 처리할 수 있다"고 이해하는게 더 적합하다.
백그라운드에서 동시에 실행될 수 있다?
비동기 작업이 "백그라운드에서 실행된다"는 것은 해당 작업이 메인 스레드에서 직접 실행되지 않고, 다른 작업이 메인 스레드에서 실행되는 동안 별도의 공간(예: 웹 API, 워커 스레드 등)에서 실행된다는 것을 의미한다.