서블릿 등장
HTTP를 공부하셨던 분이라면, 인터넷을 사용하기 위한 과정들을 간략하게나마 알고 계실 겁니다.
1. Connection을 생성하고, 소켓을 연결
2. HTTP 요청 메시지를 파싱하여 읽기.
3. 요청 메시지의 헤더 정보 파악
3-1. 메서드 파악(GET, POST, PUT, ...)
3-2. 인코딩 타입 (Content-Type)
3-3. 등등..
4. 요청 메시지 바디 내용 파싱
5. 프로세스 실행
6. 로직 실행
7. DB 최신화
8. HTTP 응답 메시지 생성
9. 응답 메시지 전송
9-1. 소켓 종료, Connection 종료(응답 메시지 전송과 함께 FIN Flag 전송)
서블릿을 사용하기 전에는 이 과정을 모두 개발자가 구현해야 했습니다.
그런데 곰곰이 생각을 해 보면 내용이 계속 바뀌게 되는 건 6~7번 정도이지 그 외의 과정들은 모두 리팩터링을 할 수 있을 것 같습니다.
1. Connection을 생성하고, 소켓을 연결
2. HTTP 요청 메시지를 파싱하여 읽기.
3. 요청 메시지의 헤더 정보 파악
3-1. 메서드 파악(GET, POST, PUT, ...)
3-2. 인코딩 타입 (Content-Type)
3-3. 등등..
4. 요청 메시지 바디 내용 파싱
5. 프로세스 실행
=================================================
6. 로직 실행
7. DB 최신화
=================================================
8. HTTP 응답 메시지 생성
9. 응답 메시지 전송
9-1. 소켓 종료, Connection 종료(응답 메시지 전송과 함께 FIN Flag 전송)
(사실 이러한 기능을 구현해주는 프로그램은 점점 생겨나는 추세였습니다. 하지만 일단 JAVA 진영을 공부하고 있기 때문에 자바 서블릿을 특정하겠습니다!)
이렇게 클라이언트측의 요청을 받아 자바 코드로 제시된 로직을 통해 처리를 한 후 반환을 하는 동적 웹 프로그래밍 자바 클래스를 서블릿이라고 합니다.
특징
- 클라이언트의 요청에 대해 동적으로 작동하는 웹 애플리케이션 컴포넌트
- 자바 코드 안에 HTML을 사용하여 요청에 응답한다. (그래서 HTML 변경 시 항상 재컴파일을 해야 함)
- Java Thread를 이용하여 동작한다. (상대적으로 가볍다)
- MVC 패턴에서 Controller로 이용된다. (차츰 만들어갈 예정)
- UDP보다 처리 속도가 느리다.
사용 방법
자바 서블릿은 HttpServlet을 상속받으며 특히 service(HttpServletRequest, HttpServletResponse)를 통해 제공된 URL이 호출되면 서블릿을 실행하는 구조로 되어 있습니다.
- HttpServletRequest : 요청 메시지 정보 파싱
- HttpServletResponse : 응답 메시지 정보 파싱
이렇게 HTTP 규약의 메시지들을 사용하기 쉽게 파싱을 해 주기 때문에 개발자들은 편리하게 요청 메시지 정보들을 가져와 쓸 수 있고, 또 응답 메시지에 편리하게 입력할 수 있습니다.
정리를 해 봅시다!
1. 웹 브라우저에서 클라이언트가 요청 메시지를 전송한다.
2. 웹 애플리케이션 서버에서는 받은 요청 메시지를 파싱해 request 객체를 생성하고, 빈 response 객체를 생성한다.
3. 생성한 두 객체를 기반으로 서블릿 컨테이너에 필요한 서블릿을 선택 한 후 실행 그 서블릿이 가지고 있는
로직을 실행한다.
(이 과정을 통해 비어있던 response 객체에 정보가 들어간다.)
4. response 객체를 HTTP 규약에 맞게 응답 메시지로 생성한다.
5. 웹 브라우저에 전달해 렌더링
서블릿 컨테이너
- 스프링 빈 컨테이너와 같이 서블릿을 지원하는 WAS가 가지고 있는 컨테이너
- 이 컨테이너가 서블릿 객체의 생명주기(생성, 초기화, 호출, 종료)를 관리.
- 각 서블릿들을 싱글톤으로 관리
- 어차피 서블릿이 할 일 = request, response를 받아 로직을 통해 정보를 입력한 response를 반환.
- 그러면 request, response만 새롭게 필요한 것이고 로직 자체는 똑같아도 무방
- 그래서 이 로직을 가지는 서블릿을 최초 로딩 시점에 미리 만들어 두어 재사용
- 서블릿 컨테이너 종료 시 함께 종료
- 단, 싱글톤 객체는 항상 Stateful을 주의해야 한다!
- 동시 요청을 위한 멀티 스레드 처리를 지원하기 때문에, 개발자는 싱글 스레드처럼 개발을 해도 상관없다.
- 싱글톤 객체만 주의!
번외 : 서블릿의 멀티 스레드
서블릿의 특성에서 JAVA 스레드를 통해 실행된다고 했습니다. 그렇기 때문에 지연이 발생하게 된다면 멀티스레드를 고려하게 될 것입니다. 이에 따른 생성 비용, 콘텍스트 스위칭 비용이 발생하는 것은 넘어갈 수 있습니다. 그런데 가장 큰 문제는 스레드 생성에 제한이 없다는 것입니다. 정말 많은 요청에 대응해 스레드가 생성이 된다면 서버가 죽을 수도 있습니다.
이를 대응하기 위해 일정량의 스레드를 미리 생성해 담아두었다가, 요청이 들어올때마다 빌려주는 형식으로 스레드를 사용하게 되는데 이를 바로 스레드 풀(Pool)이라고 합니다.
이 기술 덕분에 스레드를 생성, 종료 비용을 절약할 수 있었고, 스레드의 생성 최대치가 있기 때문에 서버가 죽을 걱정을 하지 않아도 되었습니다.
최대 스레드 수
각 서버마다 스레드 수는 커스텀할 수 있습니다. (톰캣은 최대 200개) 이 스레드 수가 WAS 튜닝의 최대 중요점입니다.
- 너무 적으면? : 서버 리소스는 엄청 여유롭고, 스레드는 적기 때문에 지연 발생 가능성이 매우 높아집니다.
- 너무 많으면? : 서버 리소스가 간당간당합니다. 삐끗하면 서버가 죽습니다.
그래서 항상 성능 테스트가 중요합니다! (Feat. 아파치의 AB와 JMETER, 네이버의 nGrinder)
구현
MVC 패턴 이전의 서블릿은 HttpServlet 클래스를 상속받아 사용됩니다.
@WebServlet(name = "helloServlet", urlPattern = "/helloServlet")
public class HelloServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException) {
resp.getWriter().write("HELLO SERVLET!");
}
}
- @WebServlet( ) : 서블릿 컨테이너에 서블릿을 등록하는 어노테이션입니다. (태그) 이 어노테이션을 사용하기 위해서는 Application 클래스에 @ServletComponentScan을 기입해야 합니다!
- name : 서블릿의 이름입니다. 중복이 되면 안됩니다. (같으면 서블릿 컨테이너가 뭘 꺼내야 할지 모름)
- urlPattern : url입니다. 맨 앞'/'에 따라 상대주소로 입력할지, 절대 주소로 입력할지가 달라집니다.
- getWriter( ) : 응답 메시지의 바디에 입력하기 위한 PrintWriter 객체를 얻는 메서드입니다.
- write("String") : 응답 메시지 바디에 입력하는 메서드 입니다.
Request 객체 정보 얻기
HttpServletRequest가 지원하는 메서드들을 통해 요청 메시지의 정보들을 얻을 수 있습니다.
메서드 | 설명 |
getMethod( ) | 메서드 정보를 얻는 메서드. (GET, PUT, POST, ...) |
getProtocol( ) | 프로토콜 정보를 얻는 메서드. |
getRequestURL( ) | 요청 URL를 얻는 메서드 |
isSecure( ) | SSL 보안이 되어 있는가 여부를 물어보는 메서드 (HTTPS) |
getHeaderNames( ) | 요청 메시지의 헤더 정보들을 얻을 수 있는 메서드 (하나씩 알려면 getHeader("헤더명")) |
getLocales( ) | 요청 메시지의 Accept-Charset 헤더 정보를 얻는 메서드 |
getCookies( ) | 요청 메시지의 쿠키 정보를 얻는 메서드 |
getContentType( ) | 요청 메시지의 Content-Type을 얻는 메서드 |
자세한 정보는 javax.servlet.http.HttpServlet를 찾아보시면 됩니다. 웬만한 정보들은 모두 get...( )을 통해 얻을 수 있습니다!
다음장에서는 본격적으로 요청 데이터와 응답 데이터를 가지고 입력해봅시다.
'SPRING > Spring MVC' 카테고리의 다른 글
서블릿, JSP, MVC (0) | 2021.11.02 |
---|---|
HTTP 요청 데이터와 응답 데이터 입력 (0) | 2021.11.01 |