[Spring] 스프링의 구조와 요청 흐름

🔥Log·2022년 11월 30일
2

스프링

목록 보기
1/18

☕ 개요


이번 글에서는 하나의 요청(Request)이 들어왔을 때, 스프링 안에서 어떤 일이 이루어지는 지 알아보도록하겠다.

  • 스프링의 구조
  • Spring MVC에서의 흐름
  • REST API에서의 흐름
  • 에러가 발생했을 때의 흐름

🍃 스프링의 구조


요청 흐름에 대해서 논하기 전에 스프링의 전체적인 구조를 짚고 가자.
(검색을 해봤는데 마음에 드는 다이어그램이 없었다. 그래서 있는 지식 없는 지식을 긁어 모아서 직접 그렸다... 😂
혹시나 잘못된 부분이 있으면 피드백을 주면 감사하겠다.)

  • WAS: Web Application Server의 줄임말이다. 스프링 boot에 내장된 톰캣이 바로 WAS이다. 그래서 모든 요청, 응답은 톰캣을 거친다.
  • Filter: 요청을 가장 먼저 맞이하는 곳이다. 서블릿 필터라고도 부르고, Low레벨의 무언가를 로깅하거나 감지할 때 사용한다.
    필터의 생애주기에 따라서 아래의 메소드들이 호출되는데, 개발자는 이 녀석들로 필요한 기능을 구현할 수 있다.
init()
- 필터 초기화 메서드
- 서블릿 컨테이너가 생성될 때 호출

doFilter()
- 요청이 올 때 마다 해당 메서드가 호출
- 주로 여기에 특정 기능에 대한 로직을 작성

destroy()
- 서블릿 컨테이너가 종료될 때 호출
  • Dispatcher servlet: 프론트 컨트롤러라고도 불리며, 사실상 스프링에서 가장 중심이 되는 역할을 수행한다. 요청을 받아서 필요한 것을 호출하거나, 다른 모듈들에게 값을 전달받아서 응답한다. 중개자 역할이라고 할 수 있다.
  • Handle Interceptor: (사실 저 위치에 그리는 게 맞나 싶긴하다... 🤔) 핸들러 어댑터 앞에서서 알짱되는 애?라고 볼 수 있을 것 같다. 인터셉터의 생애주기에 따라서 아래의 메소드들이 호출되는데, 개발자는 이 녀석들로 필요한 기능을 구현할 수 있다.
preHandle()
- 핸들러 어댑터가 호출되기 전에 실행

postHandle()
- 컨트롤러가 호출된 후에 실행

afterCompletion()
- 뷰가 렌더링된 이후에 실행
  • Handler Mapping: 클라이언트의 요청에 따른 적절한 핸들러를 찾아서 Dispatcher servlet에게 전달한다.

  • Handler Adapter: Handler Mapping을 통해서 찾은 핸들러를 실행할 수 있는 어댑터이다. 요청에 알맞는 핸들러(Controller)를 호출한다.

  • Controller, Service, Repository, DB: 요청을 받아서 비지니스 로직을 돌리고 필요하면 DB작업을 수행한다. 그리고 응답한다.

  • View Resolver: Controller가 데이터와 호출할 뷰를 Dispatcher servlet에게 전달한다. Dispatcher servlet은 전달받은 것을 View resolver에게 넘겨서 뷰를 돌려받고, 그 뷰를 사용자에게 응답하게 된다.


💻 Spring MVC의 흐름


(위에 다이어그램과 함께 보기)

👍 정상 흐름

  1. 사용자 요청
  2. WAS(톰캣)
  3. Filter
  4. Dispatcher Servlet이 요청을 처리할 핸들러와 핸들러 어댑터를 찾아옴.
  5. (Handler Interceptor를 거쳐서) Handler Adapter호출
  6. 로직(컨트롤러-서비스-레포지토리) 수행 후, 호출할 뷰와 데이터를 Dispatcher Servlet에 전달
  7. Dispatcher Servlet이 전달받은 것을 View Resolver에게 전달하고 뷰(html)를 전달받음.
  8. Filter -> 톰캣을 거쳐서 사용자에게 화면 출력

👎 에러 발생 시

잘 돌아가다가 컨트롤러에서 에러가 발생했다고 가정하자. 그러면 그 응답을 WAS까지 올렸다가, WAS에서 다시 에러 페이지를 요청하는 형태로 동작한다.

  1. (컨트롤러에서 에러 발생)
  2. 인터셉터
  3. Dispatcher servlet
  4. Filter
  5. WAS(톰캣에서 에러페이지 다시 요청)
  6. Filter
  7. Dispatcher servlet
  8. 인터셉터
  9. (컨트롤러에서 요청한 에러페이지 호출)

💻 REST API의 흐름


(위에 다이어그램과 함께 보기)

View resolver를 거치지 않고 응답한다는 것만 빼고는 MVC와 비슷하다.

👍 정상 흐름

  1. 사용자 요청
  2. WAS(톰캣)
  3. Filter
  4. Dispatcher Servlet이 요청을 처리할 핸들러와 핸들러 어댑터를 찾아옴.
  5. (Handler Interceptor를 거쳐서) Handler Adapter호출
  6. 로직(컨트롤러-서비스-레포지토리) 수행 후, 응답데이터를 Dispatcher Servlet에게 전달.
  7. Filter, 톰캣을 거쳐서 사용자에게 전달

👎 에러 발생 시

  1. (에러 발생)
  2. HandlerExceptionResolver (ExceptionResolver)에게 에러 정보를 전달하고 처리를 위임
    3-1. 위임받은 ExceptionResolver에서 뷰와 데이터를 Dispatcher Servlet에게 전달 -> Spring MVC처럼 동작
    3-2. 위임받은 EXceptionResolver에서 상태코드, 메세지등등을 Dispatcher Servlet에게 전달 -> (Filet, WAS를 거쳐서 Json으로 응답)

🧾 마무리


흠... 누구든 잘 이해할 수 있게 정리한 것인지 의문이 들지만... 😂 아무튼 스프링의 요청 흐름, 라이프 사이클에 대해서 알아봤다.

개인적으로는 이런 식으로 전체적인 흐름이나 구조를 머리에 그리고 개발을 하는 게 좋아서 이번 글을 작성하게 됐다. ㅎㅎ

혹시나 이해가 안되거나 잘못된 내용이 있으면 댓글로 알려주길 바란다. 🙏

0개의 댓글