반응형

스프링 MVC 전체 구조

1. 직접 만든 MVC 프레임워크 구조와 스프링 MVC 구조 비교

1.1 직접 만든 MVC 프레임워크 구조

1.2 스프링 MVC 구조

※ 직접 만든 프레임워크와 스프링 MVC는 명칭만 조금 다르고 거의 같은 구조와 기능으로 되어있음

 - FrontController → DispatcherServlet

 - handlerMappingMap  HandlerMapping

 - MyHandlerAdapter  HandlerAdapter

 - ModelView  ModelAndView

 - viewResolver  ViewResolver

 - MyView  View

 

2. DispatcherServlet

2.1 DispatcherServlet 개요

FrontController와 마찬가지로 부모 클래스에서 HttpServlet을 상속받아 사용하며, 서블릿으로 동작.
        ◦ DispatcherServelt → FrameworkServlet → HttpServletBean → HttpServlet

 스프링 부트 구동시 DispatcherServlet을 서블릿으로 자동등록하며 모든 경로(urlPatterns="/")에 대해 매핑.

Spring MVC 역시 프론트 컨트롤러 패턴으로 구현되어 있고 DispatcherServlet이 프론트 컨트롤러의 역할

 

※ DispatcherServlet의 다이어그램

 

2.2 DispatcherServlet 요청 흐름 및 핵심 로직 분석

 DispatcherServlet 요청 흐름

 - 서블릿이 호출되면 HttpServlet이 제공하는 service() 메서드가 호출
 - 스프링 MVC는 DispatcherServlet의 부모인 FrameworkServlet에서 service()를 오버라이드 해둠
 - FrameworkServlet.service()를 시작으로 여러 메서드가 호출되며 DispatcherServlet.doDispatch()가 호출 

 

DispacherServlet.doDispatch() 핵심 로직 분석

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	HttpServletRequest processedRequest = request;
	HandlerExecutionChain mappedHandler = null;
	ModelAndView mv = null;

	// 1. 핸들러 조회 (요청에 맞는 적절한 핸들러를 찾아 반환)
	mappedHandler = getHandler(processedRequest);
	if (mappedHandler == null) {
		// 적절한 핸들러를 찾지 못한경우 404 에러코드를 반환
		noHandlerFound(processedRequest, response);
		return;
	}

	// 2.핸들러 어댑터 조회-핸들러를 처리할 수 있는 어댑터 (찾은 핸들러를 처리할 수 있는 핸들러 어댑터를 찾아줌, 만약 찾지 못할경우 ServletException 발생)
	HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
	
	// 3. 핸들러 어댑터 실행 -> 4. 핸들러 어댑터를 통해 핸들러 실행  -> 5. ModelAndView 반환
	mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

	processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}

// 실제 코드는 복잡하게 되있는데 결국 render() 메서드를 호출
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, 
					HandlerExecutionChain mappedHandler, ModelAndView mv, 
					Exception exception) throws Exception {
	// 뷰 렌더링 호출
	render(mv, request, response);
}

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
	View view;
	// 6. 뷰 리졸버를 통해서 뷰 찾기
	// 7. View 반환 
	String viewName = mv.getViewName(); 
	view = resolveViewName(viewName, mv.getModelInternal(), locale, request);
	
	// 8. 뷰 렌더링
	// ModelAndView에서 View를 찾아 뷰 리졸버를 이용해 뷰의 물리적 이름을 완성해서 forward 해줌
	view.render(mv.getModelInternal(), request, response);
}

 

3. 스프링 MVC 동작 순서

① 핸들러 조회 : 핸들러 매핑을 통해 URL에 매핑된 핸들러(컨트롤러) 조회
② 핸들러 어댑터 조회: 핸들러를 실행할 수 있는 핸들러 어댑터 조회
③ 핸들러 어댑터 실행: 핸들러 어댑터 실행
④ 핸들러 실행: 핸들러 어댑터가 실제 핸들러를 실행
⑤ ModelAndView 반환: 핸들러 어댑터는 핸들러가 반환하는 정보를 ModelAndView로 변환해 반환.
⑥ viewResolver 호출: 뷰 리졸버를 찾아 실행
 (JSP: InternalResourceViewResolver가 자등 등록되어 사용됨)
⑦ View 반환: 뷰 리졸버는 뷰의 논리 이름을 물이 이름으로 바꾸고 렌더링 역할을 담당하는 뷰 객체 반환.
(JSP: InternalResourceView(JstlView)를 반환하는데, 내부에는 forward() 가 있음)
⑧ 뷰 렌더링: 뷰를 통해서 뷰를 렌더링

 

4. 스프링 MVC 인터페이스
 SpringMVC는 DispatcherServlet 코드 변경을 하지않고도 원하는 기능을 변경하거나 확장을 할 수 있음. 

그리고 이런 인터페이스들을 구현해 DispatcherServlet에 등록하면 커스텀 컨트롤러를 만들 수도 있음
 주요 인터페이스 목록
 - 핸들러 매핑: org.springframework.web.servlet.HandlerMapping
 - 핸들러 어댑터: org.springframework.web.servlet.HandlerAdapter
 - 뷰 리졸버: org.springframework.web.servlet.ViewResolver
 - 뷰: org.springframework.web.servlet.View

 

 

핸들러 매핑과 핸들러 어댑터

※ 직접 만든 MVC 프레임워크에서는 핸들러 매핑과 핸들러 어댑터를 단순하게 Map, List 콜렉션을 이용해서 등록한 뒤 검색해서 사용함.
 springMVC에서는 어떻게 핸들러 매핑과 핸들러 어댑터를 사용하는지 확인 해보기.

 

1. 과거 버전의 스프링 컨트롤러(Controller인터페이스를 구현)

1.1 예제 1

package hello.servlet.web.springmvc.old;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;


// @Controller 애노테이션과는 다른 Controller 인터페이스임
// /springmvc/old-controller 라는 이름의 스프링 빈으로 등록되었고, 스프링 빈의 이름으로 URL 매핑함.  
// 스프링에서 name을 urlpatterns랑 맞춤
@Component("/springmvc/old-controller")
public class OldController implements Controller{
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		System.out.println("OldController.handleRequest");
		return null;
	}
}

 

1.2 스프링 MVC가 URL을 통해 컨트롤러를 찾는 방법

이 컨트롤러가 호출되기 위해 HandlerMapping과 HandlerAdapter가 필요
        ◦ HandlerMapping
          - 핸들러 매핑에서 이 컨트롤러를 찾을 수 있어야 함.
          - 스프링 빈의 이름으로 핸드러를 찾을 수 있는 핸들러 매핑이 필요.

          - 직접 만든 MVC 프레임워크의 관련 소스

	private final Map<String, Object> handlerMappingMap = new HashMap<>();
    
	private void initHandlerMappingMap() {
		handlerMappingMap.put("/front-controller/v5/v3/members/new-form", new MemberFormControllerV3());
		handlerMappingMap.put("/front-controller/v5/v3/members/save", new MemberSaveControllerV3());
		handlerMappingMap.put("/front-controller/v5/v3/members", new MemberListControllerV3());
		

		handlerMappingMap.put("/front-controller/v5/v4/members/new-form", new MemberFormControllerV4());
		handlerMappingMap.put("/front-controller/v5/v4/members/save", new MemberSaveControllerV4());
		handlerMappingMap.put("/front-controller/v5/v4/members", new MemberListControllerV4());
	}

        ◦ HandlerAdapter
          - 핸들러 매핑을 통해 찾은 핸들러를 실행할 수있는 핸들러 어댑터가 필요  
          - Controller 인터페이스를 실행할 수 있는 핸들러 어댑터를 찾아야 함.

          - 직접 만든 MVC 프레임워크의 관련 소스

	private final List<MyHandlerAdapter> handlerAdapters = new ArrayList<>();

	// 사용할 어댑터를 리스트 콜렉션에 추가하는 작업을 하는 메서드
	private void initHandlerAdapters() {
		handlerAdapters.add(new ControllerV3HandlerAdapter());
		handlerAdapters.add(new ControllerV4HandlerAdapter());
	}

※ 스프링 부트에서는 직접 만든 MVC프레임워크처럼 Map이나 List 같은 객체로 저장하는것이 아니라

인터페이스로 구현된 핸들러 매핑과 핸들러 어댑터 객체를 자동으로 등록해줌

 

 스프링 부트가 자동 등록하는 핸들러 매핑 구현체와 핸들러 어댑터 구현체

 - HandlerMapping을 찾는 우선순위

0 = RequestMappingHandlerMapping : 애노테이션 기반의 컨트롤러인 @Requestmapping에서 핸들러를 찾음. 
1 = BeanNameUrlHandlerMapping : 스프링 빈의 이름으로 핸들러를 찾음.
...

 - HandlerAdapter을 찾는 우선순위

0 = RequestmappingHandlerAdapter : 애노테이션 기반의 컨트롤러인 @Requestmapping를 사용한 핸들러를 처리
1 = HttpRequestHandlerAdapter : HttpRequesthandler 처리
2 = SimpleControllerHandlerAdapter : Controller 인터페이스(애노테이션 X) 처리
...

• 예제1의 OldController의 핸들러 매핑과 핸들러 어댑터 찾고 실행하는 순서

 ※ 핸들러 매핑, 핸들러 어댑터 모두 순서대로 찾고 만약 없을 경우 다음 순서로 넘어간다. 
 - 핸들러 매핑으로 핸들러 조회
: HandlerMapping에서 순서대로 수행하는데 1 = BeanNameUrlHandlerMapping에서 검색이 되기에 해당 URL을 빈 이름으로 등록한 핸들러(OldController)가 매핑되어 반환됨.


  - 핸들러 어댑터 조회
: 어댑터를 순서대로 호출하며 이전에 찾은 핸들러(OldController)가 실행가능한 어댑터를 찾음.  
이 중에서 SimpleControllerHandlerAdapter가 Controller 인터페이스를 실행 가능하기에 반환.


 - 핸들러 어댑터 실행
: 반환된 어댑터(SimpleControllerHandlerAdapter)는 핸들러인 OldController를 내부에서 실행하면서 핸들러 정보를 넘겨주고 그 결과를 반환. 

 

 

2. 과거 버전의 스프링 컨트롤러(HttpRequestHandler인터페이스를 구현)

2.1 예제 2

package hello.servlet.web.springmvc.old;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestHandler;

@Component("/springmvc/request-handler")
public class MyHttpRequestHandler implements HttpRequestHandler{
	@Override
	public void handleRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
		System.out.println("MyHttpRequestHandler.handleRequest");
	}
}

2.2 스프링 MVC가 예제2의 HttpRequestHandler 핸들러 매핑과 핸들러 어댑터 찾고 실행하는 순서
 - 핸들러 매핑으로 핸들러 조회
: HandlerMapping에서 순서대로 수행하는데 1 = BeanNameUrlHandlerMapping에서 검색이 되기에 해당 URL을 빈 이름으로 등록한 핸들러(MyHttpRequestHandler)가 매핑되어 반환됨.


  - 핸들러 어댑터 조회
: 어댑터를 순서대로 호출하며 이전에 찾은 핸들러(MyHttpRequestHandler)가 실행가능한 어댑터를 찾음.  
이 중에서 HttpRequestHandlerAdapter가 HttpRequestHandler 인터페이스를 실행 가능하기에 반환.


 - 핸들러 어댑터 실행
: 반환된 어댑터(HttpRequestHandlerAdapter)는 핸들러인 MyHttpRequestHandler를 내부에서 실행하면서 핸들러 정보를 넘겨주고 그 결과를 반환. 

 

※ @RequestMapping

 - 가장 우선순위가 높은 핸들러 매핑과 핸들러 어댑터는 RequestMappingHandlerMapping, RequestMappingHandlerAdapter임.

 - @RequestMapping 의 앞글자를 따서 만든 이름인데, 이것이 바로 지금 스프링에서 주로 사용하는 애노테이션 기반의 컨트롤러를 지원하는 매핑과 어댑터이다.

 - 실무에서는 99.9% 이 방식의 컨트롤러를 사용.

 - 추후에 다룰 예정

 

뷰리졸버

1. 뷰리졸버 적용 예시(OldController를 통해)

 소스 코드

 - OldController

@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
    System.out.println("OldController.handleRequest");
    return new ModelAndView("new-form");
}

※ 컨트롤러는 정상 실행 되지만 view 페이지 인 new-form이 호출이 안되고 404에러 발생

 - 원하는 viewPath "/WEB-INF/views/new-form.jsp"를 물리이름으로 완성하지 못했기 때문에 페이지를 못찾음

 - 어떤 경로인지 상위 경로 prefix와 이게 html인지 jsp인지 확장자를 저장한 suffix를 등록 해줘야함
 - application.properties라는 속성 파일에 다음 코드를 추가

spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

 

2. 뷰 리졸버 동작 방식

※ 스프링 부트는 InternalResourceViewResolver 라는 뷰 리졸버를 자동으로 등록하는데,

이때 application.properties 에 등록한 spring.mvc.view.prefix , spring.mvc.view.suffix 설정 정보를 사용해서 등록함.

2.1 구성도

※ 위 springMVC 구조에서 6번, 7번 과정에서 뷰 리졸버가 동작.
※ 스프링 부트는 구동시 자동 등록하는 뷰 리졸버가 많은데, 이중 몇가지를 말하면 다음과 같음.

1 = BeanNameViewResolver : 빈 이름으로 뷰를 찾아서 반환한다. (예: 엑셀 파일 생성 기능에 사용)
2 = InternalResourceViewResolver : JSP를 처리할 수 있는 뷰를 반환한다.

 

2.2 예제 OldController의 뷰리졸버 동작 순서
 핸들러 어댑터 호출
 - 핸들러 어댑터를 통해 new-form 이라는 논리 뷰 이름을 획득
 ViewResolver 호출
 - new-form 이라는 뷰 이름으로 viewResolver를 순서대로 호출.
 - BeanNameViewResolver 는 new-form 이라는 이름의 스프링 빈으로 등록된 뷰를 찾아야 하는데 없음.
 - 스프링부트에 자동으로 등록된 InternalResourceViewResolver가 호출.
 InternalResourceViewResolver
 - 이 뷰 리졸버는 InternalResourceView 를 반환
뷰 - InternalResourceView
 - InternalResourceView 는 JSP처럼 포워드 forward() 를 호출해서 처리할 수 있는 경우에 사용
 view.render()
 - view.render() 가 호출되고 InternalResourceView 는 forward() 를 사용해서 JSP를 실행


※  InternalResourceViewResolver는 만약 JSTL 라이브러리가 있으면 InternalResourceView를
상속받은 JstlView를 반환.

JstlView 는 JSTL 태그 사용시 약간의 부가 기능이 추가.


※  다른 뷰는 실제 뷰를 렌더링하지만, JSP의 경우 forward() 통해서 해당 JSP로 이동(실행)해야 렌더링이
됨.

JSP를 제외한 나머지 뷰 템플릿들은 forward() 과정 없이 바로 렌더링.


※  Thymeleaf 뷰 템플릿을 사용하면 ThymeleafViewResolver 를 등록해야 함.

최근에는 라이브러리만 추가하면 스프링 부트가 이런 작업도 모두 자동화해줌

 

 

스프링 MVC 적용하기(version 1)

1. @RequestMapping

 기존에 @WebServlet에서 urlPattern을 사용해주고, Component에 빈 이름으로 URL을 작성해서 사용해지만,

스프링 MVC가 @RequestMapping 애노테이션을 사용해서 유연하고 편리하게 컨트롤러 구현이 가능해짐.

 

@RequestMapping이 사용하는 HandlerMapping과 HandlerAdapter

        ◦ RequestMappingHandlerMapping

        ◦ RequestMappingHandlerAdapter

※ 가장 우선순위가 높은 핸들러 매핑과 핸들러 어댑터

 

2. 코드

2.1 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와 같음
// 스프링 빈으로 등록
@Component
// 핸들러로 인식
@RequestMapping
*/

// 스프링이 자동으로 스프링 빈으로 등록한다. (내부에 @Component 애노테이션이 있어서 컴포넌트 스캔의 대상이 됨)
// 스프링 MVC에서 애노테이션 기반 컨트롤러(핸들러)로 인식
// RequestMapnpingHandlerMapping에서 매핑시켜줄수 있는(사용할 수 있는) 핸들러로 인식된다는 의미.
@Controller
public class SpringMemberFormControllerV1 {
	// 해당 URL이 호출되면 이 메서드가 호출. 애노테이션을 기반으로 동작하기 때문에, 메서드의 이름은 임의로 지으면 됨
	@RequestMapping("/springmvc/v1/members/new-form")
    // 모델과 뷰 정보를 담아 반환하면 됨
	public ModelAndView process() {
		return new ModelAndView("new-form");
	}
}

2.2 SpringMemberSaveControllerV1 - 회원 저장 컨트롤러

package hello.servlet.web.springmvc.v1;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;

@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.getModel().put("member", member);
		// 스프링이 제공하는 ModelAndView를 통해 Model 데이터를 추가할 때는 addObject()를 사용하면 됨
		mv.addObject("member", member);
		
		return mv;
	}	
}

2.3 SpringMemberListControllerV1- 회원 목록 컨트롤러

package hello.servlet.web.springmvc.v1;

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;

@Controller
public class SpringMemberListControllerV1 {
	private MemberRepository memberRepository = MemberRepository.getInstance();
	
	@RequestMapping("/springmvc/v1/members")
	public ModelAndView process(HttpServletRequest request, HttpServletResponse response) {
		List<Member> members = memberRepository.findAll();
		ModelAndView mv = new ModelAndView("members");
		mv.addObject("members", members);
		return mv;
	}
}

※ @Controller 애노테이션이 없어도 직접 설정영역에서 빈으로 등록해줘도 되고, 
클래스영역에 @RequestMapping과 @Component 애노테이션을 사용하면 정상적으로 등록되어 사용할 수 있음.

대체적으로 그냥 @Controller를 사용함.

 

 

스프링 MVC 컨트롤러 통합(version 2)

애노테이션 기반 컨트롤러 구축시 URL 매핑이 클래스 단위가 아니라 메서드 단위로 되는 것을 확인할 수 있었는데,

이러한 메서드들을 하나의 컨트롤러로 통합할수도 있음.

1. 코드

package hello.servlet.web.springmvc.v2;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;

@Controller
// 기존 V1의 매핑 URL을 보면 /springmvc/v1/members 까지는 중복되는데 이런 중복되는 경로를 클래스단위의 @RequestMapping에 작성해서 경로 조합이 가능함.
@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(HttpServletRequest request, HttpServletResponse response) {
		List<Member> members = memberRepository.findAll();
		ModelAndView mv = new ModelAndView("members");
		mv.addObject("members", members);
		return mv;
	}
}

 

 

스프링 MVC 실용적인 방식(version 3)

1. 코드

package hello.servlet.web.springmvc.v3;

import java.util.List;
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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import hello.servlet.domain.member.Member;
import hello.servlet.domain.member.MemberRepository;

/**
 * v3
 * Model 도입
 * ViewName 직접 반환
 * @RequestParam 사용
 * @RequestMapping -> @GetMapping, @PostMapping
 */
@Controller
@RequestMapping("/springmvc/v3/members")
public class SpringMemberControllerV3 {
	private MemberRepository memberRepository = MemberRepository.getInstance();
	
	//@RequestMapping(value = "/new-form", method = RequestMethod.GET)
	@GetMapping("/new-form")
	public String newForm() {
		return "new-form";
	}
	
	//@RequestMapping(value = "/save", method = RequestMethod.POST)
	@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";
	}

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

 Model model
 - save(), members()에서 Model을 파라미터로 받음.
 - 추가할 데이터는 이 Model에 추가해주면 되며, 기존처럼 ModelAndView 객체를 만든 뒤 여기에 데이터를 넣어줄 필요가 없어짐.


 viewName 직접 반환
 - 애노테이션 기반의 컨트롤러는 ModelAndView 뿐 아니라 ViewName을 직접 반환해도 동작함.


 @RequestParam 사용
 - 스프링은 HTTP 요청 파라미터를 @RequestParam으로 받을 수 있음.

 - 코드에서 사용 된 @RequestParam("username")은 request.getParameter("username")과 거의 같음.
 - 그래서 GET, POST Form 방식의 데이터 가져오는것을 모두 지원한다. 


@RequestMapping → @GetMapping, @PostMapping

 - @RequestMapping 애노테이션은 URL만 매칭하는게 아니라 HTTP Method도 구분할 수 있음.

 - 예를들어 회원 등록 폼 요청은 GET 으로 올 때만 매핑시키려면 method 속성에 GET을 작성하면 됨.

@RequestMapping(value = "/new-form", method = RequestMethod.GET)

 - @GetMapping, @PostMapping는 이런 method를 미리 지정해둔 애노테이션으로 가독성과 편의성이 좋아 쓰기 편함.

※ Put, Delete, Patch 모두 존재


  참고
 @GetMapping, @PostMapping  내부 코드를 보면

결국 @RequestMapping 애노테이션의 메소드를 미리 지정해둔 애노테이션임

이런 애노테이션의 유연함이 스프링 사용을 편리하게 해줌.

 - @GetMapping 에노테이션 소스

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {
	...
}
반응형

+ Recent posts