inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술

정리

스프링 프레임워크 동작 구조 정리

해결된 질문

490

경민

작성한 질문수 40

4

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? 예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예
3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예

[질문 내용]

안녕하세요 !!

[1] 요청 시에 @RequestBody와 HttpEntity를 안 쓰는 경우 , 응답 시에 @ResponseBody와 HttpEntity를 안 쓰는 경우

[2] 요청 시에 @RequestBody와 HttpEntity를 쓰는 경우 , 응답 시에 @ResponseBody와 HttpEntity를 쓰는 경우

이 두 가지 케이스로 나누어 스프링 프레임워크의 동작 구조를 정리해보았는데 제가 이해하는 게 맞는지 너무 길지만 한번만 피드백해주시면 감사하겠습니다 !!


[1]

요청 : 파라메터 타입에 @RequestBody X 이거나 HttpEntity X의 경우

응답 : 반환 값에 @ResponseBody X 이거나 HttpEntity X의 경우

 

1. 클라이언트의 요청

 

2. DispatcherServlet를 호출(urlPatterns = /* 경로이기 때문)

 

3. HandlerMapping의 가장 우선순위에 있는 구현체인 RequestMappingHandlerMapping을 통해 @Controller이 붙은 클래스의 객체를 매핑 정보로 활용

 

4. doDispatch()의 getHandler()에서 해당 매핑 정보의 컨트롤러 객체 반환

 

5. doDispatch()의 getHandlerAdapter()을 통해 HandlerAdapter을 호출 후 컨트롤러를 처리할 수 있는 어댑터 있는지 검증(supports()) 후 어댑터 호출(handle())

 

6. 이때 컨트롤러는 @Controller의 @RequestMapping이 붙어있으므로 HandlerAdapter의 가장 우선순위의 RequestMappingHandlerAdapter 어댑터 구현체가 호출되는 것!

 

7. 어댑터는 컨트롤러의 파라메터에 해당되는 객체가 ArgumentResolver의 구현체로 존재하는지 검증(supportsParameter()) 후 존재하면 생성(resolveArgument())

 

8. 어댑터는 생성된 객체를 컨트롤러의 파라메터에 주입하면서 컨트롤러 호출

 

9. 컨트롤러는 로직 수행 후 return 값(객체)을 어댑터에 반환

 

10. 어댑터는 ResultValueHandler 호출하면서 반환값에 해당되는 객체가 존재하는지 검증(supportsReturnType()) 후 존재하면 생성(handleReturnValue())

 

11. 어댑터는 생성된 객체 및 논리적 뷰 이름으로 초기화된 ModelAndView 객체 생성 후 DispatchServlet에 반환

 

12. DispatchServlet에서 ViewResolver에 논리적 뷰 이름을 넘겨주면서 호출

 

13. ViewResolver에선 논리적 뷰 이름을 물리적 뷰 경로로 바꿔주고 그 값으로 초기화된 View 객체 반환

 

14. DispatchServlet에서 View객체 이용해서 render() 호출

 

15. JSP 뷰 템플릿이었으면 render()에서 JSP 코드로 포워드 후 랜더링하고 나머지 타임리프 같은 뷰 템플릿이면 render() 받자마자 바로 화면 랜더링

 


 

[2]

요청 : 파라메터 타입에 @RequestBody O 이거나 HttpEntity O의 경우

응답 : 반환 값에 @ResponseBody O 이거나 HttpEntity O의 경우

 

1. 클라이언트의 요청

 

2. DispatcherServlet를 호출(urlPatterns = /* 경로이기 때문)

 

3. HandlerMapping의 가장 우선순위에 있는 구현체인 RequestMappingHandlerMapping을 통해 @Controller이 붙은 클래스의 객체를 매핑 정보로 활용

 

4. doDispatch()의 getHandler()에서 해당 매핑 정보의 컨트롤러 객체 반환

 

5. doDispatch()의 getHandlerAdapter()을 통해 HandlerAdapter을 호출 후 컨트롤러를 처리할 수 있는 어댑터 있는지 검증(supports()) 후 어댑터 호출(handle())

 

6. 이때 컨트롤러는 @Controller의 @RequestMapping이 붙어있으므로 HandlerAdapter의 가장 우선순위의 RequestMappingHandlerAdapter 어댑터 구현체가 호출되는 것!

 

7. 어댑터는 컨트롤러의 파라메터에 해당되는 타입의 객체가 ArgumentResolver의 구현체로 존재하는지 검증(supportsParameter())

 

8. ArgumentResovler이 검증하던 중 컨트롤러의 파라메터 타입이 @RequestBody 혹은 HttpEntity임을 감지하고 RequestResponseBodyMethodProcessor 구현체가 동작하며 HTTP 메시지 컨버터 호출

 

9. RequestResponseBodyMethodProcessor 구현체는 HTTP 메시지 컨버터의 canRead()를 통하여 파라메터의 클래스 타입과 미디어 타입(Content-Type)을 검증하고 조건 만족하면 read()를 통해 HTTP 메세지 바디에 있는 데이터 변환

 

10. RequestResponseBodyMethodProcessor 구현체는 변환된 객체를 어댑터에 반환

 

11. 어댑터에선 반환된 객체를 컨트롤러의 파라메터에 주입하면서 컨트롤러 호출

 

12. 컨트롤러는 로직 수행 후 return 값(객체)을 어댑터에 반환

 

13. 어댑터는 ResultValueHandler 호출하면서 해당 반환값이 존재하는지 검증(supportsReturnType())

 

14. 이때 ResultValueHandler에선 컨트롤러의 반환값이 @ResponseBody , HttpEntity임을 감지 후 RequestResponseBodyMethodProcessor 구현체가 동작하며 HTTP 메시지 컨버터를 호출

 

15. RequestResponseBodyMethodProcessor구현체는 HTTP 메시지 컨버터의 canWrite()를 통하여 파라메터 클래스 타입과 HTTP 요청 메시지에서의 미디어 타입(Accept)을 검증하고 조건 만족하면 write() 수행

 

16. write()에선 데이터를 변환하여 HTTP 응답 메세지 바디에 삽입 후 응답 메세지 클라이언트에게 반환


감사합니다 !! 그리고 만약 제가 정리한 부분이 맞다면 HTTP API 방식으로 동작하는 경우 맨 마지막 16번에서 write() 이후에 만들어진 응답 메세지를 어디서 클라이언트에게 반환하는 건지 궁금합니다 !

spring mvc

답변 1

2

김영한

안녕하세요. 경민님

생각하신 내용이 맞습니다.

추가로 16번 질문하신 부분은 RequestResponseBodyMethodProcessor 내부에서 더 찾아가보면

AbstractHttpMesageConverter까지 이어지는데, 여기서 write 메서드가 호출되고 그 내부에서 각각의 컨버터에 있는 실제 write가 호출됩니다.

StringHttpMessageConverter의 경우 writeInternal() 메서드 내부에서 실제 write가 발생합니다.

여기서 HttpResponse에 스트림으로 응답 데이터를 전달하게 됩니다.

감사합니다.

2

경민

매번 감사드립니다

선생님께서 잘 가르쳐주신 덕분에 전반적인 스프링 프레임워크 구조를 이해할 수 있었습니다

servlet과 container에 대한 질문입니다

0

20

1

api를 어느 컨트롤러에 작성해야하는지는 어떤 기준으로 해야하나요?

0

62

1

jsp 의존성 수정 요청

0

75

2

요즘 웹 서버가 주로 사용되는 이유는 SPA 구조 때문일까요 ?

0

142

1

save() 메서드 문의

0

65

1

절대 경로로 templates/basic 하위 파일 열면 css 적용 안되는 현상

0

99

1

request-body-json

0

83

2

MVC 패턴의 적용 단위

0

94

1

RequestMapping을 이용한 핸들러, 어댑터

0

118

2

save 후 결과화면

0

86

2

jsp를 이용한 view

0

97

1

application.properties에 debug 추가해도 결과가 똑같습니다.

0

174

1

수업 코드 제공 관련 문의

0

97

2

RequestMappingHandlerAdapter의 Controller 호출 과정

0

98

3

파일 오픈 시

0

68

1

스프링 배치 관련

0

77

1

@RequestParam의 defaultValue가 blank 값도 처리하는 지 여부

0

112

1

postman으로 /request-body-json-v1 호출시 500 error

0

94

1

프론트엔드와 백엔드의 mvc, rest api에 대한 질문

0

77

1

모델의 역할과 계층 분리에 대한 이해 차이 + 추가질문

0

111

1

console log 출력 관련 질문입니다.

0

73

1

애플리케이션이 실행 되지 않습니다 ㅠㅠㅠ

0

137

1

html 변경하는 부분 적용 문제

0

100

1

한글 깨짐

0

76

2