[Spring MVC 1편] Sec4. Servlet, JSP, MVC 패턴

HAHAING·2025년 11월 27일

Spring Mvc

목록 보기
3/3
post-thumbnail

1. 회원 관리 웹 애플리케이션 요구사항

핵심 기능

  • 회원 저장
  • 회원 목록 조회

회원 정보 (Domain Model)

  • 이름 (username)
  • 나이 (age)
  • 도메인 객체: Member
  • 저장소: MemberRepository (메모리 저장소)

저장소 요구사항

  • 싱글톤 패턴 적용

    • 순수 서블릿 환경에서는 스프링이 없으므로 직접 싱글톤 생성
    • private static final MemberRepository instance = new MemberRepository();
    • public static MemberRepository getInstance()

테스트 코드

  • 저장소는 메모리 기반이므로 테스트 간 영향 제외 필요
  • 테스트 종료 후 store 초기화
@AfterEach
void afterEach() {
    memberRepository.clearStore();
}

2. Servlet 기반 회원 관리 웹 애플리케이션

Servlet으로 직접 HTML을 생성하며 웹 기능 구현.

2-1. 회원 등록 폼 제공 (MemberFormServlet)

  • 사용자에게 <form> 페이지 제공
  • 단순히 JSP 없이 HTML 문자열을 직접 만들어 응답

2-2. 회원 저장 (MemberSaveServlet)

  • HttpServletRequest에서 파라미터 조회
    String username = request.getParameter("username")
  • Member 객체 생성 → memberRepository.save(member)
  • HTML 응답을 직접 문자열로 작성해 동적으로 출력

HTML을 자바 코드로 직접 작성해야 해서 유지보수 매우 어려움

2-3. 회원 목록 조회 (MemberListServlet)

  • List<Member> members = memberRepository.findAll()
  • 반복문(for)을 돌면서 HTML 테이블을 자바 코드로 생성

템플릿 엔진 등장 배경

Servlet은 HTML과 Java 코드가 섞여 복잡하고 유지보수성이 떨어짐.

→ HTML은 HTML대로, 동적 데이터는 템플릿 엔진에서 바꾸도록 개선

  • JSP, Thymeleaf, Freemarker 등 등장
  • 스프링 MVC에서는 JSP보다 Thymeleaf를 더 권장

3. JSP로 회원 관리 웹 애플리케이션 구현

JSP는 HTML 중심이며, 필요한 부분만 Java 코드로 삽입 가능.

기본 문법

  • JSP 파일 선언
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  • import
    <%@ page import="hello.servlet.domain.member.MemberRepository" %>
  • 자바 코드 삽입
    <% ... %>
  • 값 출력
    <%= member.getUsername() %>

JSP를 통해 HTML 중심 코드 작성 + 필요한 곳만 Java 삽입이 가능해짐.

하지만 JSP도 여전히 문제:

  • JSP 안에 비즈니스 로직이 섞임
  • Repository 접근 코드가 그대로 노출
  • 유지보수 어려움

4. Servlet + JSP로 MVC 패턴 도입

비즈니스 로직과 화면 렌더링을 분리하기 위한 구조가 MVC 패턴


4-1. MVC 구조

Model

  • 화면(View)에 전달할 데이터를 담는 역할
  • Servlet에서는 request.setAttribute("key", value) 사용

View

  • JSP
  • HTML 출력에 집중
  • JSP에서는 ${} EL 문법 제공

Controller

  • HttpServletRequest/Response 사용
  • 비즈니스 로직 호출, 결과를 Model에 담아 View로 전달
  • View 호출: request.getRequestDispatcher(viewPath).forward(req, resp)

4-2. MVC에서 redirect와 forward 차이

Forward

  • 서버 내부에서 JSP 또는 다른 Servlet을 호출
  • 브라우저 주소창 URL 변경 없음

Redirect

  • 브라우저에게 다시 요청하라고 응답
  • 주소창 URL 변경됨
  • POST-Redirect-GET 패턴에 자주 사용

5. MVC 패턴 구현 핵심 흐름

5-1. 등록 폼 Controller

  • /WEB-INF/views/new-form.jsp 호출
  • WEB-INF 내부 파일은 외부 URL 직접 접근 불가 → Controller를 반드시 거쳐야 함

5-2. 회원 저장 Controller

  • 폼 데이터 조회
  • Member 저장
  • request.setAttribute()로 View에 데이터 전달
  • 결과 JSP forward

5-3. 회원 목록 Controller

  • List<Member> 조회 후 request에 저장
  • JSP에서 JSTL <c:forEach> 로 반복 렌더링

JSTL 예:

<c:forEach var="item" items="${members}">
    <tr>
        <td>${item.id}</td>
        <td>${item.username}</td>
        <td>${item.age}</td>
    </tr>
</c:forEach>

6. MVC 패턴의 한계

컨트롤러와 뷰는 분리되었지만 여전히 다음 문제가 존재함.

1) View 호출 코드 중복

  • dispatcher.forward() 반복
  • viewPath 반복
    /WEB-INF/views/ + viewName + .jsp

2) HttpServletRequest/Response 의존

  • 컨트롤러가 서블릿 API에 강하게 결합됨
  • 테스트 코드 작성 어려움

3) 공통 로직 처리 어려움

  • 각 컨트롤러마다 중복되는 로직(로그, 인증, 예외 처리 등) 존재
  • 이를 공통 처리하려면 별도 도구 필요

7. Front Controller 패턴 (MVC 프레임워크의 핵심)

위 문제를 해결하기 위해 등장한 패턴.

  • 모든 요청은 FrontController(Servlet) 한 곳으로 들어온다
  • 공통 로직은 FrontController에서 처리
  • 실제 비즈니스 처리는 각 컨트롤러로 위임
  • 스프링 MVC의 DispatcherServlet이 이 패턴 기반

→ 이를 기반으로 하면 우리가 직접 작은 MVC 프레임워크를 만들 수도 있다.


✨ 핵심 요약

  1. Servlet만 사용하면 HTML을 Java 코드로 생성해야 하므로 유지보수 최악
  2. JSP 도입 → HTML 중심 코딩 가능해졌지만 비즈니스 로직 섞이는 문제 존재
  3. MVC 패턴 → Controller, View, Model 분리
  4. 하지만 MVC 구조에서도 forward/viewPath 중복, 공통 기능 처리 어려움
  5. Front Controller(DispatcherServlet)로 모든 문제 해결
    → 스프링 MVC는 이를 기반으로 만든 완성형 구조

출처

profile
따뜻한 시선으로 세상을 변화시키는 데이터사이언티스트

0개의 댓글