본문 바로가기

Study/개발일지

[백엔드온라인TIL] java 학습 34일차

-특강내용- 

서블릿(Servlet)이란? 

자바 서블릿(Java Servlet)은 웹페이지를 동적으로 생성하는
서버 측 프로그램 혹은 그 사양을 말하며, 흔히 "서블릿"이라 불린다.
-위키피디아-

 

서블릿은 웹 서버의 성능을 향상하기 위해 사용되는 자바 클래스의 일종이다. 기존에 서버는 정적인 자료(HTML, 사진, 글 등)만을 주고받았다. 하지만 웹에 다양한 기능이 요구되면서 정적인 자료뿐만 아니라 사용자 요구에 맞춘 동적인 페이지들을 만들 필요가 생겼다. 이를 위해 만들어진 것이 바로 서블릿이다.

 

쉽게 말해 서블릿은 클라이언트의 요청에 맞춰 동적인 결과를 만들어 주는 자바 웹 프로그래밍 기술이라고 할 수 있다. 이러한 서블릿은 WAS(Web Application Server)의 서블릿 컨테이너 안에서 동작하게 된다. 

 

 

서블릿의 특징

  • 클라이언트의 요청에 동적으로 응답하는 웹 어플리케이션 컴포넌트
  • HTML을 사용하여 응답한다.
  • JAVA의 쓰레드를 이용한다.
  • MVC 패턴의 Controller 역할을 맡는다.
  • HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속받는다.
  • UDP보다 처리 속도가 느리다.
  • HTML 변경 시 서블릿을 재 컴파일해야 한다는 단점이 존재한다.

이러한 서블릿은 WAS내의 서블릿 컨테이너에서 동작하며, 요청(Request)을 받으면 요청에 맞는 로직을 실행하고 클라이언트에게 HTTP 형식으로 응답(Response)하게 된다. 

 

서블릿 컨테이너란?

 

[그림 1] 서블릿 컨테이너

 

서블릿 컨테이너는 서블릿을 담고 관리해주는 컨테이너이다. 서블릿 컨테이너는 구현되어 있는 서블릿 클래스의 규칙에 맞게 서블릿을 관리하며 클라이언트의 요청을 받으면 HttpServletRequest와 HttpServletResponse 객체를 생성하여 post, get 여부에 따라 동적인 페이지를 생성하여 응답한다.

 

서블릿 컨테이너는 다음과 같은 기능을 한다.

 

 

1. 서블릿 생명주기 관리

서블릿 컨테이너는 서블릿의 탄생과 죽음을 관리한다. 서블릿 클래스를 로딩하여 인스턴스화하고, 초기화 메서드를 호출하고, 요청이 들어오면 적절한 서블릿 메서드를 찾아서 동작한다. 또한 서블릿의 생명이 다하면 가비지 컬렉션(Garbage Collection)을 통해 메모리에서 제거한다.

 

2. 통신 지원

서블릿 컨테이너는 웹 서버와 소켓을 만들어서 클라이언트의 요청을 받고 응답할 수 있는 통신을 지원해준다. 통신을 하기 위한 listen, accept 등의 과정을 API로 제공하여 복잡한 과정을 생략해주기 때문에 개발자가 비즈니스 로직 개발에 집중할 수 있게 도와준다. 

 

3. 멀티쓰레드 지원 및 관리

서블릿 컨테이너는 클라이언트의 요청을 받을 때마다 새로운 자바 스레드를 생성한다. 따라서 동시에 여러 요청이 들어와도 멀티쓰레딩 환경에서 동시다발적인 작업을 관리할 수 있다.

 

4. 선언적인 보안 관리

서블릿 컨테이너는 보안 관련 기능을 제공하기 때문에 개발자는 서블릿에 보안 관련 메서드를 구현하지 않아도 된다. 

 

--- 개인 학습 --

1. BindingResult

BindingResult는 검증오류를 보관하는 객체다. BindingResult에 검증오류를 보관하는 방법은 세 가지가 있다.

  1. @ModelAttribute 객체에 타입 오류등으로 바인딩이 실패하는 경우
  2. 사용자가 정수형 필드에 문자를 넣는 경우를 생각해보면 된다. 객체에 타입 오류 등으로 바인딩이 실패하면 스프링이 FieldError를 생성해서 BindingResult에 넣어준다. BindingResult가 있으면 쿼리 파라미터를 ModelAttribute 객체로 바인딩하는데에 실패해도 컨트롤러가 호출된다. BindingResult는 Model에 자동으로 포함되기 때문에 어떤 오류가 발생했는지 사용자에게 친절하게 알려줄 수 있다. BindingResult가 없으면 400 오류가 발생하면서 컨트롤러가 호출되지 않고 오류 페이지로 이동한다. 오류 페이지로 이동하면 사용자가 입력했던 값이 모두 날아간다. 이는 사용자 경험 측면에서 나쁘다.
  3. 개발자가 직접 넣어주는 경우
  4. 개발자는 검증을 수행해서 BindingResult에 직접 오류 객체를 넣어줄 수 있다.
  5. Validator를 사용하는 경우
  6. 검증 로직을 Validator로 분리하면 컨트롤러 코드를 간단하게 유지할 수 있는데, 이는 뒤에서 살펴보겠다.

BindingResult 는 핸들러 매개변수에서 자신이 검증할 객체 바로 다음에 위치시켜야한다.

 

1. @PostContruct 

 

1. @PostConstruct란?

 

@PostConstruct는 의존성 주입이 이루어진 후 초기화를 수행하는 메서드이다. @PostConstruct가 붙은 메서드는 클래스가 service(로직을 탈 때? 로 생각 됨)를 수행하기 전에 발생한다. 이 메서드는 다른 리소스에서 호출되지 않는다해도 수행된다. 

 

출처: Oracle Doc

 

 

2. 왜 사용하는가(장점)?

 

1) 생성자(일반)가 호출 되었을 때, 빈(bean)은 아직 초기화 되지 않았다. (예를 들어, 주입된 의존성이 없음)

하지만, @PostConstruct를 사용하면, 빈(bean)이 초기화 됨과 동시에 의존성을 확인할 수 있다. 

+ 개인 의견으로 클래스 내에 @Autowired를 붙여서 객체를 사용할 때, 생성자가 필요하다면 @PostConstruct를 사용하면 될 것 같다. 빈(bean)이 등록되고 사용할 수 있으니까 말이다. 나도 그렇게 사용했고..

 

2) bean lifecycle에서 오직 한 번만 수행된다는 것을 보장할 수 있다. (WAS가 올라가면서 bean이 생성될 때 딱 한 번 초기화함) 그래서 @PostConstruct를 사용하면 bean이 여러번 초기화되는 것을 방지할 수 있다.

 

 

3. SecurityFilterChain은 Filter 인터페이스를 구현한 여러 종류의 필터들을 List 객체에 가지고 있습니다.

스프링 시큐리티를 커스터마이징 하기 위해서는 SpringSecurity에서 제공하는 필터들에 대해 이해하는게 좋습니다.
SpringSecurityFilterChain은 아래 표와 같이 여러 종류의 필터들을 가지고 있습니다.

SpringSecurityFilterChain 종류

728x90