✏️ Spring MVC 시작하기

2026. 7. 18. 18:44·Backend/Spring MVC

이 글은 Velog에서 이전한 글입니다. Velog 원문 보기

*스프링이 제공하는 컨트롤러는 애노테이션 기반으로 동작해서, 매우 유연하고 실용적이다. *

@RequestMapping
스프링은 애노테이션을 활용한 매우 유연하고, 실용적인 컨트롤러를 만들었는데 이것이 바로 @RequestMapping 애노테이션을 사용하는 컨트롤러이다.

  • RequestMappingHandlerMapping
  • RequestMappingHandlerAdapter

@ReqeustMapping 기반의 스프링 MVC Controller를 작성하면서 V1부터 V3까지 개선하는 과정을 작성해보려고 한다.

📌 V1 - 개선 전

✔︎ SpringMemberFormControllerV1 - 회원 등록 폼

package hello.servlet.web.springmvc.v1;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class SpringMemberFormControllerV1 {

    @RequestMapping("/springmvc/v1/members/new-form")
    public ModelAndView process() {
        return new ModelAndView("new-form");
    }
}

@Controller

  • 내부에 @Component 애노테이션이 있어서 스프링이 자동으로 스프링 빈으로 등록한다.
  • Spring MVC에서 애노테이션 기반 Controller로 인식한다.

RequestMappingHandlerMapping은 스프링 빈 중에서 @RequestMapping or @Controller가 클래스 레벨에 붙어 있는 경우 매핑 정보로 인식한다.
그러므로 다음 코드도 동일하게 동작한다.

package hello.servlet.web.springmvc.v1;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Component //Component Scan을 통해 스프링 빈으로 등록
@RequestMapping
public class SpringMemberFormControllerV1 {
    @RequestMapping("/springmvc/v1/members/new-form")
    public ModelAndView process() {
        return new ModelAndView("new-form");
    }
}

- - -

### ✔︎ SpringMemberSaveControllerV1 - 회원 저장
```java
package hello.servlet.web.springmvc.v1;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import hello.servlet.web.frontcontroller.ModelView;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;
import java.util.Map;

@Controller
public class SpringMemberListControllerV1 {
    private MemberRepository memberRepository = MemberRepository.getInstance();

    @RequestMapping("/springmvc/v1/members")
    public ModelAndView process() {
        List<Member> members = memberRepository.findAll();

        ModelAndView mv = new ModelAndView("members");
        mv.addObject("members", members);
        return mv;
    }
}

mv.addObject("member", member)

  • 스프링이 제공하는 ModelAndView를 통해 Model 데이터를 추가할 때는 addObject()를 사용하면 된다. 이 데이터는 이후 View를 렌더링 할 때 사용된다.

✔︎ SpringMemberListControllerV1 - 회원 목록

package hello.servlet.web.springmvc.v1;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import hello.servlet.web.frontcontroller.ModelView;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@Controller
public class SpringMemberSaveControllerV1 {

    private MemberRepository memberRepository = MemberRepository.getInstance();


    @RequestMapping("/springmvc/v1/members/save")
    public ModelAndView process(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        int age = Integer.parseInt(request.getParameter("age"));

        Member member = new Member(username, age);
        memberRepository.save(member);

        ModelAndView mv = new ModelAndView("save-result");
        mv.addObject("member", member);
        return mv;

    }
}

V1은 각 Controller가 따로 분리되어 있어 한 눈에 파악하기가 어렵다. V2에서는 이 부분을 개선해보겠다.

📌 V2 - 컨트롤러 통합

V1의 각 Controller의 @RequestMapping를 보면 클래스 단위가 아닌 메서드 단위에 적용되어 있다. 그러므로 Controller Class를 유연하게 하나로 통합할 수 있다.

package hello.servlet.web.springmvc.v2;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

@Controller
@RequestMapping("/springmvc/v2/members")
public class SpringMemberControllerV2 {
    private MemberRepository memberRepository = MemberRepository.getInstance();

    @RequestMapping("/new-form")
    public ModelAndView newForm() {
        return new ModelAndView("new-form");
    }

    @RequestMapping("/save")
    public ModelAndView save(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        int age = Integer.parseInt(request.getParameter("age"));

        Member member = new Member(username, age);
        memberRepository.save(member);

        ModelAndView mv = new ModelAndView("save-result");
        mv.addObject("member", member);
        return mv;
    }

    @RequestMapping
    public ModelAndView members() {
        List<Member> members = memberRepository.findAll();

        ModelAndView mv = new ModelAndView("members");
        mv.addObject("members", members);
        return mv;
    }
}

클래스 단위에 @RequestMapping("/springmvc/v2/members")를 작성함으로서 중복되는 부분도 제거하였다. 그런데 여전히 개발자가 ModelView를 직접 생성해서 반환해야 한다는 불편한 부분이 존재한다. 개선할 방법이 없을까?

📌 V3 - 실용적인 방식

package hello.servlet.web.springmvc.v3;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

@Controller
@RequestMapping("/springmvc/v3/members")
public class SpringMemberControllerV3 {

    private MemberRepository memberRepository = MemberRepository.getInstance();

    @GetMapping("/new-form")
    public String newForm() {
        return "new-form";
    }

    @PostMapping("/save")
    public String save(
            @RequestParam("username") String username,
            @RequestParam("age") int age,
            Model model) {
        Member member = new Member(username, age);
        memberRepository.save(member);

        model.addAttribute("member", member);
        return "save-result";
    }

    @GetMapping
    public String members(Model model) {
        List<Member> members = memberRepository.findAll();
        model.addAttribute("members", members);
        return "members";
    }
}

V3에서는 V2의 불편한 부분을 개선하기 위해 다음과 같은 기능을 추가했다.

  • Model 도입
  • 각 메소드가 ModelAndView 객체가 아닌 ViewName를 직접 반환
  • @GetMapping, PostMapping 사용

Model 파라미터

  • save(), members()를 보면 Model을 파라미터로 받는 것을 확인할 수 있다. Spring MVC도 이런 편의 기능을 제공한다.

ViewName 직접 반환

  • View의 논리 이름을 반환할 수 있다.

@GetMapping, @PostMapping

  • @GetMapping과 @PostMapping은 다음 코드의 간략화 버전이다.
    @RequestMapping(value="/...", method = RequestMethod.Get)
    @RequestMapping(value="/...", method = RequestMethod.Post)
    //@RequestMapping은 URL만 매칭하는 것이 아니라, HTTP Method도 함께 구분할 수 있다. 

출처
김영한님의 Spring MVC 강의

'Backend > Spring MVC' 카테고리의 다른 글

✏️ 요청 매핑  (0) 2026.07.18
✏️ Logging  (0) 2026.07.18
✏️ Front Controller 패턴, Adapter 패턴  (0) 2026.07.18
✏️ MVC 패턴  (0) 2026.07.18
✏️ HttpServlet 요청과 응답  (0) 2026.07.18
'Backend/Spring MVC' 카테고리의 다른 글
  • ✏️ 요청 매핑
  • ✏️ Logging
  • ✏️ Front Controller 패턴, Adapter 패턴
  • ✏️ MVC 패턴
pp8817
pp8817
공부한 내용, 개발 관련 지식, 트러블 슈팅 등을 기록합니다. 이전 블로그: https://velog.io/@pp8817/posts
  • pp8817
    끄적이는 개발 log
    pp8817
  • 전체
    오늘
    어제
    • 분류 전체보기 (273)
      • Project (71)
        • 척척학사 (29)
        • Book (23)
        • Saynow (3)
        • YAPP 27기 (4)
        • 나의 작은 프로젝트 (10)
        • Landit (2)
      • Backend (88)
        • Spring (13)
        • Spring MVC (13)
        • Spring Security (4)
        • JPA (26)
        • Database (19)
        • HTTP·Web (13)
        • Architecture (0)
      • Language·CS (59)
        • Java·Kotlin (5)
        • CS Interview (17)
        • Backend Interview (5)
        • Concepts (32)
      • Algorithm (25)
        • Algorithm (24)
        • 소마 알고리즘 스터디 (1)
      • Infra (8)
      • Troubleshooting (11)
      • Retrospective (6)
      • Etc (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Algorithm
    interview
    object
    Project
    Spring MVC
    척척학사
    jpa
    나의 작은 프로젝트
    http
    BOJ
    java
    Spring
    OS
    개념 정리!
    HTTP WEB 기본 지식
    Book
    게시판
    Python
    CS Interview
    트러블슈팅
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
pp8817
✏️ Spring MVC 시작하기
상단으로

티스토리툴바