서블릿(Servlet) - 스프링 MVC 1편

박계현·2025년 1월 3일
1

스프링

목록 보기
2/2
post-thumbnail

📖 김영한 님의 <스프링 MVC 1편 - 백엔드웹 개발 핵심 기술> 강의를 보고 공부하며 정리한 포스트입니다.

만약에 이런 HTML 폼이 있다고 합시다.

여기서 전송을 딱 눌렀을 때 어떤 일이 일어날까요? 웹 브라우저가 요청 HTTP 메시지를 아래와 같이 만듭니다.

POST 메서드와 /save URL로 보내겠다는 메시지가 생성이 되었습니다. Host 헤더에 BaseURL, Content-Type에 Form-data를 보내겠다는게 명시되어 있으며, 메시지 Body에 유저가 입력한 데이터가 들어가 있습니다.
이렇게 만든 메시지를 서버로 전송을 합니다.

만약에 웹 HTTP 서버를 직접 구현을 해야한다면?

유저로부터 받을 위 HTTP 메시지를 풀어헤쳐 처리할 코드를 작성해야 합니다...! 주로 사용되는 TCP/IP 프로토콜 방식의 소켓 연결을 대기하는 코드를 짭니다. 이때 들어올 HTTP 요청 메시지는 그냥 해당 소켓으로 전송되는 단순 텍스트입니다. HTTP라는 프로토콜을 알고 있으므로 해당 규칙에 따라 메시지를 잘라(파싱)줍니다. 이 메시지가 POST 방식이라는 사실, 엔드포인트가 /save라는 사실, Content-Type이 Form-data라는 사실을 확인하고 메시지 Body 내용까지 그에 맞게 해석을 해냅니다. 메시지를 저장하는 프로세스까지 거치고나면 그제서야 이에 맞는 비즈니스 로직에 요청을 연결할 수 있습니다. 이때부터는 우리가 아는 DB에 저장을 요청하고(이러한 DB 연결도 관리해야 할 겁니다) 예외처리를 해줍니다. 다 되고 나면 이제 읽씹할 수 없으니 클라이언트를 위한 HTTP 응답을 만들어줘야 합니다. HTTP 응답 메시지를 텍스트로, 직접 HTTP 시작 라인, Header, Body까지 만들어줍니다. 열려있던 있던 TCP/IP 소켓으로 응답을 전달하고 나면 소켓을 종료합니다.

여기서 저희가 실제로 신경써서(물론 다 신경써야겠지만!) 구현해야할 비즈니스 로직, 즉, 클라이언트의 요청에 따라 이름과 나이를 저장하는 부분은 저 긴 과정 중 중간에 잠깐 뿐입니다. 이런 부분을 매번 다 구현해야 한다면 전세계 개발자들이 가만있지 않겠죠(감히 일을 중복해?). 그래서 등장한 것이 서블릿(Servlet)입니다. 서블릿은 제가 말한 중요한 비즈니스 로직 부분을 제외한 모든 부분에 대한 기능을 지원해줍니다!

✏️ 서블릿(Servlet) 자바 기반 웹 애플리케이션에서 클라이언트 요청을 처리하고 응답을 생성하는 서버 측 프로그램입니다. 서블릿은 Java EE (Java Platform, Enterprise Edition) 기술 스택의 일부로, 웹 서버와 클라이언트(주로 웹 브라우저) 간의 동적 콘텐츠를 생성하는 데 사용됩니다.

JSP 파일의 라이프사이클. Servlet이 포함되어 있어 참고로 가져왔습니다. (출처: 위키백과)

서블릿을 살펴볼까요?

@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
	@Override
    protected void service(HttpServletRequest request, HttpServletResponse response) {
    	// 애플리케이션 로직
    }
}

urlPatterns(/hello)의 URL이 호출되면 위 클래스의 service() 코드가 실행됩니다. 해당 클래스에서 이제 소켓 연결과 관련된 부분을 처리해줍니다. 저희는 HttpServlet만 상속 받아 애플리케이션 로직만 작성하면 됩니다. 또한, HTTP 텍스트를 파싱하는 코드를 작성하는 것도 만만치 않은 귀찮음일 것입니다. 이러한 HTTP 요청 정보 사용과 응답 제공을 편리하게 해주는 HttpServletRequestHttpServletResponse도 제공됩니다. 예를 들어:

String name = request.getParameter("name");

등의 코드로 폼데이터의 파라미터를 간단하게 가져올 수 있습니다(와 편리해~). 그러나 기본적인 HTTP 스펙을 알아야 Servlet이 정확히 어떤 부분을 추상화해서 기능을 제공하는지 알 수 있고, 어떤 기능을 사용해야할 지도 알 수 있습니다. 때문에 이러한 HTTP 스펙 공부가 필요합니다.

전체 그림을 볼까요?

서버 주소를 localhost:8080라고 하겠습니다. 클라이언트 웹 브라우저가 localhost:8080/hello라고 요청을 합니다. 그러면 WAS에서 요청 메시지를 기반으로 request, response 객체를 생성합니다. 그 다음 서블릿 컨테이너(추후 설명합니다)에서 저희가 만든 helloServlet이라는 이름의 서블릿을 생성된 requestresponse 객체를 넘겨 실행해줍니다. helloServlet 끝나고 리턴을 하고 나면, 기존에 넘겨받았던 response 객체를 바탕으로 HTTP 응답 메시지를 생성하고 이를 웹 브라우저에 반환해줍니다.

정리해봅시다

서블릿 HTTP 요청, 응답 흐름

  • HTTP 요청 시
    • WAS는 Request, Response 객체를 새로 만들어서 서블릿 객체를 호출합니다.
    • 개발자는 Request 객체에서 HTTP 요청 정보를 편리하게 꺼내서 사용합니다.
    • 개발자는 Response 객체에 HTTP 응답 정보를 편리하게 입력합니다.
    • WAS는 Response 객체에 담겨있는 내용으로 HTTP 응답 정보를 생성합니다.
  • 웹 브라우저로 응답을 전송합니다.

서블릿 컨테이너는 뭐죠?

자바는 아시다시피 코드 실행을 위해 객체가 있어야합니다. 그런데 위와 같은 서블릿 객체를 저희가 직접 생성하지 않습니다. 서블릿 클래스만 코드로 작성하면 이를 서블릿 컨테이너가 자동으로 생성하고, 호출하고, 생명주기를 관리해줍니다. 이 관리를 맡은 걸 서블릿 컨테이너라 부르기로 했다는 설명이 좀 더 매끄럽겠네요.

서블릿 컨테이너

  • 톰캣(Tomcat)처럼 서블릿을 지원하는 WAS를 서블릿 컨테이너라고 합니다.
  • 서블릿 컨테이너는 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리합니다.
  • 서블릿 객체는 싱글톤으로 관리됩니다.
    • 고객의 요청이 올 때 마다 계속 객체를 생성하는 것은 비효율 적이기 때문입니다(Request와 Response는 고객마다 다르기 때문에 매번 새로 만듭니다. 그러나 메서드 내 애플리케이션 로직만 존재하는 서블릿의 경우 모든 요청에 대해 동일하게 동작합니다).
    • 최초 로딩 시점에 서블릿 객체를 미리 만들어두고 재활용합니다.
    • 모든 고객 요청은 동일한 서블릿 객체 인스턴스에 접근합니다.
    • 싱글톤이기 때문에 공유 변수 사용에 주의해야 합니다! (서로 다른 요청에 대해 값이 공유될 수 있습니다)
    • 서블릿 컨테이너 종료 시 함께 종료됩니다.
  • JSP도 서블릿으로 변환 되어서 사용됩니다.
  • 동시 요청을 위한 멀티 쓰레드 처리를 지원합니다(동시에 천 명, 만 명이 요청해도 잘 처리하는 이유가 멀티 쓰레드가 지원되기 때문입니다).

🙇‍♂️ 오타, 잘못된 정보, 추가 정보 등이 있으면 얼마든지 알려주세요! 감사합니다.

profile
안녕하세요, 백엔드 열심히 공부 중인 개발자입니다😊

0개의 댓글

관련 채용 정보