UMC/study

[UMC_study] 서블릿 vs Spring MVC 비교

sunm2n 2025. 9. 28. 13:30

1. 핵심 비교: 저수준 Servlet vs. 프레임워크 Spring MVC

 

구분 전통적인 서블릿 (Servlet) Spring MVC 프레임워크
기반 Servlet API를 직접 사용하는 저수준(Low-level) 기술   
 

Servlet API 기반의 요청 중심(Request-driven) 프레임워크   
 
 

개발 난이도 HTTP 요청 처리 및 고급 기능을 직접 구현해야 하므로 복잡함   
 

프레임워크가 복잡성을 추상화하여 개발자가 비즈니스 로직에 집중 가능   
 

Front Controller 없음 (서블릿 컨테이너가 요청을 특정 서블릿으로 직접 매핑) DispatcherServlet이 중앙 집중식 Front Controller 역할을 수행   
 

설정 web.xml 파일을 사용하여 서블릿 매핑을 명시적으로 설정해야 함   
 

어노테이션 기반 설정으로 web.xml 설정이 불필요하거나 최소화됨   
 

 

2. 개발 패러다임 비교: API 및 구조

 

Spring MVC는 서블릿의 저수준 API를 대체하고 추상화하여 개발 편의성을 높입니다.

항목 서블릿 방식 Spring MVC 방식
클래스 정의 HttpServlet 클래스를 상속받아 구현   
 

@Controller 어노테이션을 사용하여 POJO 클래스를 정의   
 

메서드 레벨 처리 특정 HTTP 메서드에 맞춰 doGet(), doPost() 등을 오버라이드   
 

@RequestMapping 어노테이션을 사용하여 URL과 HTTP 메서드를 매핑   
 

요청/응답 객체 HttpServletRequest, HttpServletResponse 객체를 메서드 파라미터로 직접 처리 @RequestParam, @PathVariable, @RequestBody 등 추상화된 객체 처리 메커니즘 사용

 

3. Spring MVC가 서블릿보다 편리한 이유 (프레임워크의 역할)

 

Spring MVC는 단순히 서블릿을 추상화하는 것을 넘어, Spring 프레임워크의 핵심 기능(IoC, AOP)을 통합하여 개발 생산성, 유지보수성, 테스트 용이성을 극대화합니다.

가. 제어의 역전(IoC) 및 의존성 주입(DI)

  • 프레임워크의 역할: Spring의 IoC(Inversion of Control) 컨테이너는 객체의 생성, 구성, 생명주기 관리를 담당합니다. DI(Dependency Injection)를 통해 컨트롤러가 필요한 객체(Service, Repository 등)를 직접 생성하지 않고 주입받아 사용합니다.   
  •  
  •  
  • 이점: 서블릿이 서블릿 컨테이너에 의존하여 객체 생명주기가 제한적인 것에 비해 , Spring은 유연한 의존성 관리를 통해   코드의 결합도를 낮추고 모듈성을 높입니다.
  •  

나. 편리한 단위 테스트

서블릿 환경은 객체 생성이 컨테이너에 종속되어 Mocking이 어렵고 단위 테스트가 복잡합니다. 반면, Spring의 DI 기능은 테스트 코드가 실제 의존성 대신 Mock 객체를 쉽게 주입할 수 있게 하여 단위 테스트 과정을 매우 용이하게 만듭니다.   

 

다. 구조화된 REST API 처리

Spring MVC는 @RequestMapping, @RestController 등의 어노테이션을 제공하여 URL, HTTP 메서드, 요청 파라미터 매핑을 명확하고 구조화된 방식으로 처리할 수 있게 합니다. 이는 서블릿에서 복잡하게 처리해야 했던 RESTful API 개발을 단순화합니다.   

 

라. 관점 지향 프로그래밍(AOP) 지원

Spring 프레임워크는 AOP(Aspect-Oriented Programming)를 지원하여 로깅, 보안, 트랜잭션 관리와 같은 횡단 관심사(Cross-cutting concerns)를 핵심 비즈니스 로직으로부터 분리합니다. 이는 코드의   

 

모듈성, 재사용성 및 유지보수성을 획기적으로 향상시킵니다. Spring AOP는 순수 Java로 구현되어 서블릿 컨테이너 환경에 적합합니다.   

 

4. DispatcherServlet의 요청 처리 단계별 분석 (HandlerMapping, HandlerAdapter, Interceptor)

 

DispatcherServlet은 Spring MVC의 핵심으로, 모든 요청을 단일 진입점에서 받아 내부 구성 요소들을 사용하여 적절한 Handler(Controller 메서드)로 분배하고 응답을 생성합니다.   

 

1) 요청 처리 흐름 다이어그램 (단계별)

요청이 DispatcherServlet에 도달하면, 다음과 같은 과정을 거쳐 처리됩니다 :   

 
단계 주체 역할 및 주요 키워드
1. Request 수신 Client → DispatcherServlet 클라이언트 요청을 DispatcherServlet이 수신합니다.   
 

2. Handler Mapping HandlerMapping 요청(URL, 메서드 등)을 분석하여 해당 요청을 처리할 **Handler(Controller 메서드)**를 찾습니다. 이때 Handler와 Interceptor 목록을 포함하는 **HandlerExecutionChain**을 반환합니다.   
 
 
 

3. Interceptor (preHandle) HandlerInterceptor 요청이 Handler로 가기 전에 사전 처리(preHandle()) 로직을 실행합니다. 인증이나 로깅 등의 작업을 수행하며, 여기서 false를 반환하면 처리가 중단됩니다.   
 
 

4. Handler Adapter 호출 HandlerAdapter DispatcherServlet은 HandlerAdapter를 사용하여 Handler(Controller 메서드)를 실제로 호출합니다. 이는 DispatcherServlet과 다양한 형태의 Handler 간의 느슨한 결합을 가능하게 합니다.   
 
 

5. Handler(Controller) 실행 Controller 비즈니스 로직을 실행하고, 처리 결과를 담은 ModelAndView 객체(또는 View 이름, Model 데이터)를 반환합니다.   
 

6. Interceptor (postHandle) HandlerInterceptor Handler 실행 후, View 렌더링 전에 사후 처리(postHandle()) 로직을 실행합니다. Model 데이터 수정이나 응답 헤더 추가 등이 가능합니다.   
 
 

7. View Resolution ViewResolver Controller가 반환한 논리적 View 이름을 사용하여 실제 View 리소스(예: /WEB-INF/views/index.jsp)에 대한 View 객체를 찾습니다.   
 
 

8. View 렌더링 및 응답 View View 객체가 Model 데이터를 사용하여 응답을 렌더링하고, 이 최종 응답이 클라이언트에게 전달됩니다. 요청 완료 후에는   
 

afterCompletion()Interceptor가 최종 정리 작업을 수행합니다.   
 

2) 핵심 구성 요소 역할 상세

  • HandlerMapping: 요청을 분석하고 해당 요청을 처리할 수 있는 **Handler(Controller)**와 Interceptors 목록을 HandlerExecutionChain 형태로 반환하는 역할을 합니다. 가장 일반적으로 사용되는 구현체는   @RequestMapping 어노테이션을 처리하는 RequestMappingHandlerMapping입니다.
  •  
  • HandlerAdapter: DispatcherServlet과 다양한 종류의 Handler(Controller) 사이의 중개자 역할을 수행하여 Handler의 실행을 담당합니다.   DispatcherServlet은 모든 Handler를 이 Adapter를 통해 통일된 방식으로 호출합니다.
  •  
  • HandlerInterceptor: Handler(Controller)가 실행되기 (preHandle), Handler 실행 (postHandle), 요청 처리 완료 후(afterCompletion)에 특정 로직을 삽입할 수 있도록 합니다. 이는 전역적인 인증, 로깅, 권한 확인 등의   횡단 관심사를 Controller 로직과 분리하는 데 사용됩니다.