
@Controller
요청을 받아, 그에 대한 처리 뒤, 응답을 반환
Front Controller (Servlet)
요청을 받아, Spring에게 처리를 위임 한뒤, 응답을 반환
DispathcerServlet 구현체
HandlerMapping: 요청에 해당하는 처리메서드가 존재하는지 검색 (전화번호부)
HandlerAdapter: Spring 에게 처리를 위임? (이 구현체가 요청에 맞는 컨트롤러를 호출한다)
HandlerMapping 은 아래 HandlerAdapters 모두 순회하며 적합한 HandlerAdapter 검색
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
Iterator var2 = this.handlerAdapters.iterator();
while(var2.hasNext()) {
HandlerAdapter adapter = (HandlerAdapter)var2.next();
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
- HttpRequestHandlerAdapter
- SimpleControllerHandlerAdapter
- RequestMappingHandlerAdapter
- HandlerFunctionAdapter
일반적으로 handlerMapping 에 의해 RequestMappingHandlerAdapter 가 선택되어 실행
@RequesetMpping 정의 시, HandlerMapping을 통해 요청이 controller로 연결
- Controller에서 처리한 모든 응답은 Front Controller(DispatcherServlet)에게 반환한다.
💡`new`를 사용해서 객체를 만들지 않았는데 @Controller 클래스 객체가 만들어진 이유
Spring에서 관리하는 객체를 Bean이라고 부르며 싱글톤으로 관리(주의: Java Beans와 다른 용어)
스프링 빈은 2가지만 기억하면 된다.
1. Bean 등록: Spring Container 내 싱글톤 객체로 등록 (이미 `new` 로 인스턴스화 되어있음)
2. Bean 사용: Spring Container 에 등록되어 있는 싱글톤 객체를 가져와 주입하여 사용
Spring Container는 ApplicationContext 라 불리기도하고 이는 위에 보았듯 2개로 분리
- Servlet WebApplicationContext: @Controller 등
- Root WebApplicationContext: @Service, @Repository
💡Bean 등록 방법
Spring Container 내 싱글톤 객체로 등록
- @ComoponentScan + @Component를 통한 등록(Package 지정 가능)
- @Controller, @Service, @Repository 등을 통한 등록
💡Bean 사용 방법
Spring Container에 등록되어 있는 싱글톤 객체를 가져와 주입하여 사용
- 구체 클래스를 지정하여 Bean 객체 사용 <- 구체 클래스로 Beann 등록
- 부모 클래스를 지정하여 Bean 객체 사용 <- 부모 클래스의 자식 클래스로 Bean등록
- 인터페이스를 지정하여 Bean 객체 사용 <- 인터페이스의 구체 클래스로 Bean 등록
- 다수 자식 클래스 혹은 다수 인터페이스의 구체 클래스를 Collection 자료구조로 Bean 사용
Controller 반환 값
Spring 에 위임되어 Controller에서 처리한 모든 응답은 Front Controller 에게 반환 타입을 고려해 반환
- Front Controller인 DispathcerServlet은 Controller가 반환한 타입에 따라 View 생성
DispatchServlet 은 HandlerAdapter의 응답으로 String, ModelAndView, Object 중 하나를 받음
- DispathchServlet은 @ResponseBody 여부에 따라 ViewResolver 혹은 MessageConverter 실행
- 웹 페이지 반환 = View 반환 = ViewTemplate + Model : ViewResolver 사용
- 웹 데이터(JSON)를 반환 = Model 반환 (@ResponseBody 명시) : MessageConverter 사용
1. 웹 페이지 반환 = View 반환: ViewResolver
- Controller 가 String 반환 = 정적 페이지(ViewTemplate)
- 어떤 웹 페이지(HTML)를 반환할지 ViewTemplate 명칭을 반환
- ViewResolver: ViewTemplate 명칭의 HTML 혹은 JSP 파일을 찾아 렌더링하고, 미존재 시 404
- Controller가 ModelAndView 반환 = 동적 페이지 (ViewTemplate + Model)
- 어떤 웹 페이지(HTML)를 반환할지 ViewTemplate 명칭과 Model 함께 반환
💡ModelAndView VS. ModelMap VS. Model
1. ModelAndView(구현 클래스): ViewTemplate + Model의 역할
- `new ModelAndView` : 개발자가 직접 만드는 ModelAndView 객체
- `ModelAndView Bean`: Spring이 대신 만들어주는 ModelAndView 객체
2. ModelMap(구현 클래스): ViewTemplate 과 Model의 역할 분리
3. Model(인터페이스): 다양한 구현 클래스 적용 가능
2. 데이터(JSON) 반환 = Model 반환: MessageConverter
Controller 가 객체 반환 = @ResponseBody 적용 Controller메서드가 반환한 객체를 JSON으로 변환
- MessageConverter: 객체에 따라 JSON 혹은 XML 같은 것들로 변환(Convert) 하여 데이터 반환
- 메서드에 `@ResponseBody` 추가해서 ViewTemplate으로 반환하지 않고 "값 그 자체"로 반환되도록
@RestController = @Controller + @ResponseBody
만약 UserController 클래스 내부에 모든 메서드들이 JSON 데이터를 반환하는 것인 경우
- @RestController를 클래스 레벨에 붙여준다.
@RestController
public class UserController {
@RequestMapping(method = RequestMethod.GET, value = "/")
public String index() {
return "index.html";
}
}
직렬화: @Getter
public class User {
private Integer id;
private String name;
private Integer age;
private String job;
private String specialty;
}

- 반환 객체 클래스에 @Getter 붙여서 직렬화 문제 해결
@Getter
public class User {
private Integer id;
private String name;
private Integer age;
private String job;
private String specialty;
}

Model 데이터(JSON) View 반환 위한 HttpMessageConverter 구현체
앞서서 MessageConverter 이라고 언급했는데 정확히는 HttpMessageConverter
HttpMessageConverter 는 객체를 JSON 으로 변환하는것뿐만 아니라 JSON 을 객체로도 변환
응답: Java 객체 -> JSON 변환(Java 객체 -> HTTP Response Body): Serialization 직렬화
요청: JSON -> Java 객체 변환 (HTTP Request Body -> Java 객체) : Deserialization 역직렬화

Spring 은 타입 혹은 개발자 설정에 따라 Converter 적용
Spring이 어떻게 타입이 다른지 인지할까?
- 요청의 Content-Type에 따라 Spring이 알아서 결정
어떤 Content-type(MediaType)에 따라 Converter 구현체를 사용할지 세부 설정 가능
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
final MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
final List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add( MediaType.APPLICATION_JSON_UTF8 );
mediaTypes.add( MediaType.APPLICATION_OCTET_STREAM );
mediaTypes.add( MediaType.TEXT_HTML );
mediaTypes.add( MediaType.TEXT_PLAIN );
jacksonConverter.setSupportedMediaTypes( mediaTypes );
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule( new AfterburnerModule() );
objectMapper.setSerializationInclusion( JsonInclude.Include.NON_NULL );
jacksonConverter.setObjectMapper( objectMapper );
return jacksonConverter;
}
- ByteArrayHttpMessageConverter (Order 0): 파일 전송 시 - `application/octet-stream`
- StringHttpMessageConverter (Order. 1): 문자열 전송 시 = `text/html`
- FormHttpMessageConverter: `application/x-www-form-urlencoded`
- MappingJackson2HttpMessageConverter(Order2): JSON 전송 시 - `application/json`
- ResourceHttpMessageConverter(Order3): 파일 전송 시 (`ResponseEntity<Resource> 반환 시)
Java 객체 <-> JSON 변환을 위한 커스텀 XmlHttpMessageConverter 개발 시 XML 변환 가능
- Spring Boot 사용 시, 구현체를 @Bean로 추가만 해주면 Spring 이 알아서 Converter 추가
'ASAC 웹 풀스택 > Spring Boot' 카테고리의 다른 글
Spring Boot 특장점 및 동작(1) - Spring과 Spring Boot의 차이점 (0) | 2024.10.08 |
---|---|
Spring Bean 원리(1) - 싱글톤, IoC, Bean 등록/사용 (3) | 2024.10.08 |
Spring MVC 원리(2) - Tomcat + Spring 상세구조 (0) | 2024.10.07 |
Spring MVC 원리(1) - 동작 과정 (0) | 2024.10.07 |
[Spring Boot] 기본 MVC 개발을 위한 Annotations 과 그 이해(1) - 컨트롤러로 정적/동적 페이지 반환, 타임리프 설정 변경 (1) | 2024.10.06 |

@Controller
요청을 받아, 그에 대한 처리 뒤, 응답을 반환
Front Controller (Servlet)
요청을 받아, Spring에게 처리를 위임 한뒤, 응답을 반환
DispathcerServlet 구현체
HandlerMapping: 요청에 해당하는 처리메서드가 존재하는지 검색 (전화번호부)
HandlerAdapter: Spring 에게 처리를 위임? (이 구현체가 요청에 맞는 컨트롤러를 호출한다)
HandlerMapping 은 아래 HandlerAdapters 모두 순회하며 적합한 HandlerAdapter 검색
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { Iterator var2 = this.handlerAdapters.iterator(); while(var2.hasNext()) { HandlerAdapter adapter = (HandlerAdapter)var2.next(); if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); }
- HttpRequestHandlerAdapter
- SimpleControllerHandlerAdapter
- RequestMappingHandlerAdapter
- HandlerFunctionAdapter
일반적으로 handlerMapping 에 의해 RequestMappingHandlerAdapter 가 선택되어 실행
@RequesetMpping 정의 시, HandlerMapping을 통해 요청이 controller로 연결
- Controller에서 처리한 모든 응답은 Front Controller(DispatcherServlet)에게 반환한다.
💡new
를 사용해서 객체를 만들지 않았는데 @Controller 클래스 객체가 만들어진 이유
Spring에서 관리하는 객체를 Bean이라고 부르며 싱글톤으로 관리(주의: Java Beans와 다른 용어)
스프링 빈은 2가지만 기억하면 된다.
1. Bean 등록: Spring Container 내 싱글톤 객체로 등록 (이미new
로 인스턴스화 되어있음)
2. Bean 사용: Spring Container 에 등록되어 있는 싱글톤 객체를 가져와 주입하여 사용
Spring Container는 ApplicationContext 라 불리기도하고 이는 위에 보았듯 2개로 분리
- Servlet WebApplicationContext: @Controller 등
- Root WebApplicationContext: @Service, @Repository
💡Bean 등록 방법
Spring Container 내 싱글톤 객체로 등록
- @ComoponentScan + @Component를 통한 등록(Package 지정 가능)
- @Controller, @Service, @Repository 등을 통한 등록
💡Bean 사용 방법
Spring Container에 등록되어 있는 싱글톤 객체를 가져와 주입하여 사용
- 구체 클래스를 지정하여 Bean 객체 사용 <- 구체 클래스로 Beann 등록
- 부모 클래스를 지정하여 Bean 객체 사용 <- 부모 클래스의 자식 클래스로 Bean등록
- 인터페이스를 지정하여 Bean 객체 사용 <- 인터페이스의 구체 클래스로 Bean 등록
- 다수 자식 클래스 혹은 다수 인터페이스의 구체 클래스를 Collection 자료구조로 Bean 사용
Controller 반환 값
Spring 에 위임되어 Controller에서 처리한 모든 응답은 Front Controller 에게 반환 타입을 고려해 반환
- Front Controller인 DispathcerServlet은 Controller가 반환한 타입에 따라 View 생성
DispatchServlet 은 HandlerAdapter의 응답으로 String, ModelAndView, Object 중 하나를 받음
- DispathchServlet은 @ResponseBody 여부에 따라 ViewResolver 혹은 MessageConverter 실행
- 웹 페이지 반환 = View 반환 = ViewTemplate + Model : ViewResolver 사용
- 웹 데이터(JSON)를 반환 = Model 반환 (@ResponseBody 명시) : MessageConverter 사용
1. 웹 페이지 반환 = View 반환: ViewResolver
- Controller 가 String 반환 = 정적 페이지(ViewTemplate)
- 어떤 웹 페이지(HTML)를 반환할지 ViewTemplate 명칭을 반환
- ViewResolver: ViewTemplate 명칭의 HTML 혹은 JSP 파일을 찾아 렌더링하고, 미존재 시 404
- Controller가 ModelAndView 반환 = 동적 페이지 (ViewTemplate + Model)
- 어떤 웹 페이지(HTML)를 반환할지 ViewTemplate 명칭과 Model 함께 반환
💡ModelAndView VS. ModelMap VS. Model
1. ModelAndView(구현 클래스): ViewTemplate + Model의 역할
-new ModelAndView
: 개발자가 직접 만드는 ModelAndView 객체
-ModelAndView Bean
: Spring이 대신 만들어주는 ModelAndView 객체
2. ModelMap(구현 클래스): ViewTemplate 과 Model의 역할 분리
3. Model(인터페이스): 다양한 구현 클래스 적용 가능
2. 데이터(JSON) 반환 = Model 반환: MessageConverter
Controller 가 객체 반환 = @ResponseBody 적용 Controller메서드가 반환한 객체를 JSON으로 변환
- MessageConverter: 객체에 따라 JSON 혹은 XML 같은 것들로 변환(Convert) 하여 데이터 반환
- 메서드에
@ResponseBody
추가해서 ViewTemplate으로 반환하지 않고 "값 그 자체"로 반환되도록
@RestController = @Controller + @ResponseBody
만약 UserController 클래스 내부에 모든 메서드들이 JSON 데이터를 반환하는 것인 경우
- @RestController를 클래스 레벨에 붙여준다.
@RestController public class UserController { @RequestMapping(method = RequestMethod.GET, value = "/") public String index() { return "index.html"; } }
직렬화: @Getter
public class User { private Integer id; private String name; private Integer age; private String job; private String specialty; }

- 반환 객체 클래스에 @Getter 붙여서 직렬화 문제 해결
@Getter public class User { private Integer id; private String name; private Integer age; private String job; private String specialty; }

Model 데이터(JSON) View 반환 위한 HttpMessageConverter 구현체
앞서서 MessageConverter 이라고 언급했는데 정확히는 HttpMessageConverter
HttpMessageConverter 는 객체를 JSON 으로 변환하는것뿐만 아니라 JSON 을 객체로도 변환
응답: Java 객체 -> JSON 변환(Java 객체 -> HTTP Response Body): Serialization 직렬화
요청: JSON -> Java 객체 변환 (HTTP Request Body -> Java 객체) : Deserialization 역직렬화

Spring 은 타입 혹은 개발자 설정에 따라 Converter 적용
Spring이 어떻게 타입이 다른지 인지할까?
- 요청의 Content-Type에 따라 Spring이 알아서 결정
어떤 Content-type(MediaType)에 따라 Converter 구현체를 사용할지 세부 설정 가능
@Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { final MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(); final List<MediaType> mediaTypes = new ArrayList<>(); mediaTypes.add( MediaType.APPLICATION_JSON_UTF8 ); mediaTypes.add( MediaType.APPLICATION_OCTET_STREAM ); mediaTypes.add( MediaType.TEXT_HTML ); mediaTypes.add( MediaType.TEXT_PLAIN ); jacksonConverter.setSupportedMediaTypes( mediaTypes ); final ObjectMapper objectMapper = new ObjectMapper(); objectMapper.registerModule( new AfterburnerModule() ); objectMapper.setSerializationInclusion( JsonInclude.Include.NON_NULL ); jacksonConverter.setObjectMapper( objectMapper ); return jacksonConverter; }
- ByteArrayHttpMessageConverter (Order 0): 파일 전송 시 -
application/octet-stream
- StringHttpMessageConverter (Order. 1): 문자열 전송 시 =
text/html
- FormHttpMessageConverter:
application/x-www-form-urlencoded
- MappingJackson2HttpMessageConverter(Order2): JSON 전송 시 -
application/json
- ResourceHttpMessageConverter(Order3): 파일 전송 시 (`ResponseEntity<Resource> 반환 시)
Java 객체 <-> JSON 변환을 위한 커스텀 XmlHttpMessageConverter 개발 시 XML 변환 가능
- Spring Boot 사용 시, 구현체를 @Bean로 추가만 해주면 Spring 이 알아서 Converter 추가
'ASAC 웹 풀스택 > Spring Boot' 카테고리의 다른 글
Spring Boot 특장점 및 동작(1) - Spring과 Spring Boot의 차이점 (0) | 2024.10.08 |
---|---|
Spring Bean 원리(1) - 싱글톤, IoC, Bean 등록/사용 (3) | 2024.10.08 |
Spring MVC 원리(2) - Tomcat + Spring 상세구조 (0) | 2024.10.07 |
Spring MVC 원리(1) - 동작 과정 (0) | 2024.10.07 |
[Spring Boot] 기본 MVC 개발을 위한 Annotations 과 그 이해(1) - 컨트롤러로 정적/동적 페이지 반환, 타임리프 설정 변경 (1) | 2024.10.06 |