이번 수업의 핵심은 “Spring MVC에서 요청이 들어오고 응답이 나가기까지 흐름이 어떻게 구성되는가”였다.
Servlet / JSP 시절에는 FrontController와 Action을 직접 구현했지만 Spring MVC에서는 이 구조가 표준화된 흐름으로 정리되어 있다.
1. Spring MVC는 FrontController 패턴을 프레임워크가 제공한다
Spring MVC에서 DispatcherServlet은 FrontController 역할을 한다.
사용자의 요청이 컨트롤러로 바로 들어가는 게 아니라 DispatcherServlet이 먼저 요청을 받아서 처리 흐름을 통제한다.
정리하면 아래와 같다.
- Servlet / JSP 시절: 개발자가 FrontController를 직접 구현
- Spring MVC: DispatcherServlet이 FrontController 역할을 이미 수행
이 구조의 핵심은 요청 흐름의 “진입점”을 하나로 통일한다는 것이다.
2. 요청 처리 흐름을 3단계로 보면 이해가 쉽다
수업에서 정리한 흐름은 아래처럼 3단계로 볼 수 있다.
(1) [A] DispatcherServlet이 요청을 받는다
DispatcherServlet은 사용자의 모든 요청이 들어오는 첫 번째 관문이다.
그래서 수업에서 “유일한 서블릿”이라고 표현한 이유는 요청을 한 곳에서 통제하는 구조이기 때문이다.
(2) [B] HandlerMapping이 “누가 처리할지”를 찾아준다
DispatcherServlet은 요청을 받으면 바로 컨트롤러를 실행하는 게 아니라 먼저 HandlerMapping에게 물어본다.
- “이 URL 요청을 처리할 컨트롤러가 누구야?”
- “GET 요청인지 POST 요청인지도 확인해야 해”
HandlerMapping은 요청 URL과 HTTP Method를 보고 그 요청을 처리할 컨트롤러를 찾아서 연결해준다.
여기서 수업에서 말한 ActionFactory와 연결되는 포인트가 있다.
- 예전 ActionFactory: 개발자가 if/switch로 직접 분기 (수동 라우팅)
- Spring HandlerMapping: 매핑 정보 기반으로 자동 분기 (자동 라우팅)
ActionFactory 역할이 스프링에서는 HandlerMapping 구조로 정리된다고 이해하면 된다.
(3) [C] Controller가 요청을 처리하고, 어디로 갈지 결정한다
Controller는 예전 MVC 구조에서 Action 역할과 유사하다.
컨트롤러가 하는 일은 크게 두 가지다.
- 요청 정보 (파라미터)를 추출해서 필요한 로직 수행
- 처리 결과를 바탕으로 “어디로 갈지”를 결정해서 반환
Servlet / JSP 구조에서는 ActionForward 같은 객체로 이동 정보를 넘겼다면 Spring MVC에서는 컨트롤러가 뷰 이름 (String) 또는 ModelAndView를 반환하는 방식으로 흐름이 정리된다.
3. @RequestMapping → @GetMapping으로 바뀐 이유
수업에서 다룬 매핑 방식은 크게 두 가지였다.
기존 형태
@RequestMapping(value="/index.do", method=RequestMethod.GET)
축약 형태
@GetMapping("/index")
@GetMapping은 GET 요청 전용 매핑 방식이다.
기존의 RequestMapping을 더 짧고 명확하게 쓴 표현이다.
이 흐름에서는 .do 패턴을 제거하면서 URL을 더 깔끔하게 가져가는 방향도 같이 연결됐다.
4. 요청 정보 추출이 “가벼워지는 이유” = 커맨드 객체 (VO / DTO)
Spring MVC에서는 요청 파라미터를 하나씩 꺼내는 방식이 아니라 DTO 형태로 한 번에 받을 수 있는 구조가 가능하다.
수업에서는 이를 다음처럼 정리했다.
- VO (Value Object)
- DTO (Data Transfer Object)
- 커맨드 객체 (Command Object)
이 용어들은 수업 맥락에서 “요청 데이터를 담는 객체”라는 의미로 연결된다.
여기서 중요한 조건은 하나다.
DTO의 setter 이름과 요청 파라미터 이름이 맞아야 자동으로 바인딩된다.
예를 들어
- name="mid" → setMid()
- name="mpw" → setMpw()
이 구조 덕분에 컨트롤러는 request.getParameter()를 반복하지 않아도 입력을 받을 수 있고 전체 코드가 더 단순해진다.
5. 커맨드 객체에 DAO를 넣으면 안 되는 이유
수업에서 강조한 핵심은 “경량화”였다.
커맨드 객체는 원래 요청 데이터를 담는 역할이다.
그런데 커맨드 객체 안에 DAO 같은 의존 객체를 넣어버리면 문제가 생긴다.
대표적인 문제는 아래 두 가지다.
- DAO가 여러 개 생성될 가능성이 커진다 (new가 늘어남)
- AOP 같은 구조를 적용할 때 설계가 불편해진다
DTO는 DTO 역할만 하고 DAO / Service는 DI로 분리해서 관리하는 구조가 더 안전하다.
6. DI 관점에서 핵심: new를 없애고 “주입받는 구조”로 만든다
이번 수업에서 가장 중요한 메시지는 결국 이것이다.
new를 직접 쓰는 구조를 줄이고 DI로 객체를 주입받는 구조로 만든다.
이렇게 하면
- 객체 생성 책임이 한 곳 (컨테이너)로 모이고
- 중복 생성이 줄고
- 구조 변경이 쉬워진다
특히 멤버 변수가 생겼다면
- 생성자에서 초기화하거나
- DI로 주입받는 구조로 만드는 것이 기본 원칙이다.
7. “어디로 갈지”만 결정하고 “어떻게 갈지”는 구조로 고정된다
Servlet / JSP에서 ActionForward로 “forward / redirect”까지 직접 다뤘다면 Spring MVC에서는 이동 방식이 더 단순하게 정리된다.
수업에서 말한 핵심은
- 컨트롤러는 “어디로 갈지”를 중심으로 반환하고
- 이동 방식은 일정한 규칙으로 처리된다
컨트롤러는 더 가벼워지고 전체 흐름은 프레임워크가 통제하는 구조가 된다.
8. 2-Layered 아키텍처 관점
수업에서 말한 Layer 구조는 다음처럼 정리된다.
- Presentation Layer: Controller (요청 / 응답 담당)
- Business Layer: Service (핵심 로직 담당)
그리고 보통 실제 구현에서는 DAO까지 포함되면서
- Data Access Layer: DAO / Repository
형태로 확장된다.
이 구조를 가져가는 이유는 역할을 분리해서 유지보수성과 확장성을 확보하기 위함이다.
9. 루트 컨테이너 (Root Container)가 먼저 준비되는 이유
“루트 컨테이너”의 핵심은 이거였다.
서비스 / DAO처럼 DB 연결이 필요한 객체는 요청이 들어오기 전에 미리 준비돼야 한다.
그래서 스프링에서는
- 비즈니스 레이어 (Service)
- DB 접근 레이어 (DAO)
쪽이 루트 컨테이너에 잡히는 경우가 많다.
Spring MVC는 요청 흐름을 DispatcherServlet 중심으로 통제하고 Controller는 커맨드 객체로 가볍게 입력을 받고
Service / DAO는 DI로 주입받아 역할을 분리한다.
'수업 복습' 카테고리의 다른 글
| Spring MVC / JSP Q&A 정리 (0) | 2026.01.22 |
|---|---|
| Spring Boot + JSP 로그인부터 게시판 조회 (0) | 2026.01.20 |
| FC 구조를 Spring MVC (DS)로 갈아끼우기 (0) | 2026.01.16 |
| FrontController에서 DispatcherServlet까지 (0) | 2026.01.16 |
| 콘솔 회원·게시판 프로그램 (0) | 2026.01.15 |