학습 키워드
- Spring MVC (Blocking)
- Spring WebFlux & WebClient (Non-Blocking)
- Thread Model (Thread per Request vs Event Loop)
학습 한 내용
Spring MVC는 소프트웨어를 Model, View, Controller 세 가지 요소로 나누어 관리하는 패턴을 기반으로 한 서블릿 웹 프레임워크다. 하지만 요즘은 이 전통적인 방식 외에 WebFlux라는 방식도 많이 쓰이는데, 둘의 가장 큰 차이는 '요청을 처리할 때 스레드가 멈추냐 아니냐'의 차이다.
Spring MVC: "순서대로 줄 서서 기다리기"
우리가 흔히 쓰는 방식이다. 요청 하나당 스레드 하나가 딱 붙어서 끝까지 책임진다.
- 모든 요청은 DispatcherServlet이라는 프런트 컨트롤러를 거치는데, 여기서 스레드 풀(Thread Pool)에 미리 만들어둔 스레드를 하나씩 꺼내준다.
- 코드가 위에서 아래로 순서대로 실행되니까 짜기 편하고 직관적이다.
- 하지만 DB에서 데이터를 가져오거나 외부 API 응답을 기다려야 하면, 그 스레드는 응답이 올 때까지 아무것도 못 하고 멍하니 서 있어야 한다(Blocking). 만약 요청이 폭주해서 스레드 풀이 바닥나면 서버는 그대로 먹통이 된다.
Spring WebFlux(WebClient): "진동벨 주고 딴 일 하기"
Go에서 고루틴 돌리듯 자원을 극한으로 아껴 쓰는 방식이다. 톰캣 대신 Netty 같은 비동기 엔진 위에서 Event Loop가 뱅뱅 돌며 일을 처리한다.
- 응답을 기다려야 하는 작업이 생기면 스레드가 거기서 멈추지 않는다. "결과 나오면 알려줘"라고 던져놓고 바로 다음 요청을 받으러 간다(Non-Blocking).
- 적은 숫자의 스레드만 가지고도 수만 명의 요청을 쳐낼 수 있다. 특히 WebClient를 쓰면 외부 서버에 데이터를 물어볼 때 내 서버가 멈추지 않고 계속 돌아가니까 효율이 압도적이다.
- 단, 주의할 점은 DB 드라이버부터 모든 라이브러리가 비동기를 지원해야 하고, 코드 자체도 Mono/Flux 같은 리액티브 스타일로 짜야 해서 디버깅이 어렵고 팀 전체가 익숙해져야 한다는 진입장벽이 있다. 또한 중간에 하나라도 Blocking 이 섞이면 Event Loop가 멈춰 병목이 생기므로, 전체를 Non-blocking으로 구성하는 것이 중요하다.
그래서 뭘 써야 하나?
- MVC: 대부분의 일반적인 서비스. 복잡한 비즈니스 로직이 많고 코드가 읽기 편해야 할 때 쓴다.
- WebFlux: API 게이트웨이나 채팅처럼 동시 접속자가 엄청나게 많거나, 외부 API 호출이 잦아서 '대기 시간'이 긴 서비스에 필수다.