GitHub

https://github.com/Choidongjun0830

Spring

[원티드 백엔드 챌린지 11월] Spring의 기능 자세히 살펴보기

gogi masidda 2024. 11. 22. 15:36

Servlet 

  • Web Page 또는 결과 값을 동적으로 생성하는 역할을 하는 자바 프로그램
  • Controller와 Service 레이어가 함께 묶여져 있는 것

 

Spring Boot = Tomcat + Spring

  • Tomcat (WAS (Web Application Server))
    • Web server + Servlet Container의 결합으로 다양한 기능을 컨테이너에 구현하여 다양한 역할을 수행할 수 있는 서버
      • Web Server
        • 네트워크 처리(HTTP 및 Socket): Client의 요청부터 응답까지 전반적인 네트워크 처리 역할
        • 정적 리소스 처리: HTML, CSS, JS와 같은 리소스만 처리
      • Servlet Container
        • Servlet 관리 및 처리: 동적 페이지 생성 및 처리
        • Web Server와 네트워크 처리
          • Web Server와 Servlet Container 간의 통신 
        • Thread pool 관리 
    • 톰캣 안에 멀티 쓰레드로 동작할 수 있게끔 Thread pool을 갖고 있다. 
    • 클라이언트가 요청을 보내면, Web server를 통해 커넥션이 맺어진다.
    • 요청이 정적인 리소스를 사용하는 경우에는 Web server가 응답 
    • 요청이 동적인 리소스를 사용해서 동적으로 페이지를 생성해야 한다면
      • Task Queue에 요청이 할당된다. 
      • Thread Pool에서 요청을 가져와서 해당 하는 Thread가 작업을 처리 
      • => 같은 시간에 여러개의 요청을 보내도 MultiThread 방식으로 모두 처리하여 응답 가능 
    • 멀티 스레드 환경에서 문제
      • Race Condition 해결
        • ThreadLocalRandom 
          • Random을 상속받는 클래스 
          • 동시성 문제를 해결하기 위해, 각 Thread마다 생성된 인스턴스에서 각각의 난수를 리턴 
          • 난수를 생성할 때, 유니크하게 하기 위해 Random 대신 ThreadLocalRandom을 쓰는게 좋다. 
        • Mutex도 있는데 ThreadLocal 방식이 더 좋다
          • 스레드별 독립적인 자원을 제공 
      • Deadlock 상태
        • 무한 대기

Request 처리 프로세스

  • Filter와 Dispatcher Servlet은 Tomcat 영역에 있다. 
    • Spring Security는 Filter에서 동작하는데, Authentication과 Authorization을 둘다 Filter에서 할 필요는 없다. 
      • Authentication은 Filter에서 확인하고, Authorization은 Interceptor에서 확인 
  • request가 들어와서 dispatch해서 handler mapping에 갔다가, Handler Interceptor를 거쳐 Handler Adaptor로 간다.
    • 이 과정을 거쳐야 Controller로 가게 된다. 
  • Controller의 응답을 받아 Handler Adaptor는 View Resolver를 통해 화면을 보여줄 수 있게 한다. 

 

  • 가장 먼저 요청 메시지를 Dispatcher Servlet이 받음
  • Handler Mapping
    • Request message의 Header에 저장된 부가적인 정보를 이용해서 요청처리를 위임할 Controller를 찾음
  • Request를 위임할 HandlerAdaptor를 찾아서 전달
    • 직접 Controller를 위임하지 않는 이유는 Controller 구현 방식이 다양하기 때문에 이것들을 모두 수용하기 위해서
  • HandlerAdaptor가 Handler(Controller)로 요청을 위임
    • HandlerAdaptor가 Handler로 요청을 위임하는 과정에서 Controller의 Method 인자에 선언된 객체(@RequestBody, @RequestParam)를 인스턴스화 
      • JSON 문자를 파싱해서 RequestDto로 만듦 
    • ArgumentResolver가 HttpMessageConverter를 사용해서 Request Message의 데이터를 적절한 데이터 타입으로 변환 및 생성 

 

ArgumentResolver 상세 프로세스

  • Handler를 호출하여 파라미터 타입 정보를 전달 받음
  • ArgumentResolver를 호출하여 Controller의 파라미터 객체 생성을 요청 
    • supportParameter: 파라미터의 처리 가능 여부를 확인하고 실행 여부 리턴. 해당하는 메시지 컨버터로 변환이 가능한지 
    • resolveArgument: 받은 Parameter를 가공하는 역할 수행 
    • Parameter를 가공할 때, HTTPMessageConverter를 이용해서 Request Message를 알맞은 데이터 타입으로 변환하고 생성한 후 반환

결론적으로 @RequestBody나 @RequestParam을 쓸 때, Dto에 @AllArgsConstructor나 @NoArgsConstructor를 사용하지 않아도 된다. 


@Valid

  • 요청 메시지의 값 여부 및 포맷을 정의한대로 검사해줌
  • HandlerInterceptor가 실행되고 나서 검증 단계로 들어감
  • 검증에서 오류가 발생하면 MethodArgumentNotValidException 예외가 발생한다. 

@Controller 응답 프로세스

  • 결과 값을 받은 컨트롤러는 필요에 따라 Model 객체에 결과 값을 넣거나, View 정보를 담아 DispatcherServlet에게 보낸다.
  • DispatcherServlet은 View Resolver에게 전달 받은 View에 대한 정보를 보낸다. 
    ViewResolver는 해당 View를 찾아 DispatcherServlet에게 알려준다.
  • DispatcherServlet은 응답할 View에게 Render를 지시하고 View는 응답 로직을 처리한다.
  • DispatcherServlet이 클라이언트에게 렌더링된 View를 전달한다. 

@RestController 응답 프로세스

@Controller와 달리 @ResponseBody 어노테이션이 붙어 있다. 

 

  • ViewResolver 대신 Message Convertor가 실행되고, Return Type에 맞는 Convertor#canWrite만 실행된다.
    • 해당하는 리턴 타입에 맞는 Convertor인지 확인하고, 맞으면 등록해줌. 
  • 이 시점에 ControllerAdvice가 Return 값을 가로챈다. 그리고 응답에 대한 공통 로직이 실행된다.
    • 이 시점에 Api 응답을 위한 Wrapper 클래스에 감싸지게 된다. 
  • 위 결과를 ReturnValueHandler가 받아서 Converter@writeInternal이 실행되면서 응답 메시지가 HTTP ResponseBody에 쓰여지고 Client에게 HTTP Response가 전달된다. 

Error Handling 설계

  • Response Message 공통 처리와 마찬가지로 Exception도 공통으로 처리할 수 있도록 하는 것이 가독성과 유지보수성에 좋다. 이또한 AOP로 구현하는 것이 좋다. 
  • Exception은 기본적으로 Spring Boot에서 제공하는 것으로 최대한 사용하고, 기본적으로 제공하는 Exception으로 의미를 정확히 전달하기 어려우면 커스텀해서 표현하는 것을 추천
    • 하지만 커스텀은 추천하지 않음
      • Exception의 이름을 잘못 지으면 의미 전달 어려움
      • 최초의 커스텀한 Exception이 저자의 의도와 다르게 사용될 수도 
  •  
728x90