개발 학습 실습실

이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.

기초개념 › Spring

서블릿

어떤 클래스를 서블릿이라고 부르는가

서블릿은 class로 선언한 자바 클래스입니다. 일반 클래스와 다른 곳은 두 군데입니다. extends HttpServlet은 웹 요청을 받을 수 있는 클래스라는 자격이고, @WebServlet("/hello")는 브라우저가 /hello라는 주소로 보낸 요청을 이 클래스에 맡긴다는 등록입니다. 이 둘을 하나씩 지워 가며 같은 요청을 보내, 톰캣이 이 클래스의 doGet을 불러 주는지를 봅니다.

실행으로 대조 · 톰캣 11.0.24에 열두 가지 조합을 배치하고 요청을 보내 대조

이 실습에 나오는 개념

서블릿 클래스
서블릿 클래스는 Servlet 인터페이스를 구현한 자바 클래스다. 인터페이스를 직접 구현하기보다, 그것을 이미 구현해 둔 HttpServlet을 상속해서 만드는 것이 보통이다. 서블릿 클래스의 객체는 개발자가 new로 만들지 않고 서블릿 컨테이너가 만들며, 요청이 오면 컨테이너가 그 객체의 메서드를 부른다. 컨테이너는 서블릿 선언 하나에 객체를 하나만 만들어 계속 쓴다. 클래스도, 컨테이너가 만든 그 객체도 서블릿이라고 부른다.
HttpServlet
HttpServlet은 서블릿 API에 들어 있는 추상 클래스로, HTTP 요청을 받는 서블릿을 만들 때 상속한다. 모든 서블릿이 구현해야 하는 Servlet 인터페이스를 이미 구현해 두었으므로, 개발자는 extends HttpServlet이라고 쓰고 doGet이나 doPost 같은 메서드만 재정의하면 된다. 요청이 오면 HttpServlet의 service 메서드가 요청의 HTTP 메서드를 보고 알맞은 doXxx 메서드를 부른다. 재정의하지 않은 doXxx 메서드로 요청이 오면 그 HTTP 메서드를 지원하지 않는다는 오류 응답이 나간다.
@WebServlet
@WebServlet은 클래스를 서블릿으로 선언하고 그 서블릿이 맡을 주소(URL 패턴)를 적는 애너테이션이다. 서블릿 컨테이너는 애플리케이션을 배치할 때 이 애너테이션을 읽어 주소와 서블릿을 짝짓는다. 주소는 하나 이상 적어야 하고, 이 애너테이션을 붙이는 클래스는 HttpServlet을 상속해야 한다. 애너테이션을 붙인다고 일반 클래스가 서블릿이 되는 것은 아니다. 같은 등록을 web.xml이라는 설정 파일에 적어서 할 수도 있다.
서블릿과 서블릿 컨테이너
서블릿은 HTTP 요청을 받아 처리하고 응답을 만드는 자바 표준 인터페이스다. 서블릿 컨테이너(톰캣 등)는 네트워크 연결을 받아 요청을 해석하고 알맞은 서블릿을 호출하며 서블릿의 생명주기와 요청 처리 스레드를 관리한다. Spring MVC는 DispatcherServlet이라는 서블릿 하나 위에서 동작한다.

이렇게 바꿔 보세요

처음 설정으로 실행하면

  1. 서버가 뜹니다. 톰캣이 웹 애플리케이션의 클래스 파일을 훑어 @WebServlet이 붙은 클래스를 찾습니다. Hello 클래스에 붙어 있으므로, 거기 적힌 주소와 클래스를 주소 표에 적습니다. 객체는 아직 만들지 않습니다.
  2. 브라우저 주소창에 localhost:8080/hello 주소를 입력하면, 브라우저가 서버에 GET /hello 요청을 보냅니다.
  3. 톰캣이 주소 표에서 /hello 주소를 찾습니다. Hello 클래스가 적혀 있습니다.
  4. 톰캣이 Hello 클래스의 객체를 만듭니다. 우리가 쓴 코드에는 new Hello()라는 줄이 없습니다. 서블릿 객체는 톰캣이 만듭니다.
  5. 톰캣이 이 객체에 요청을 넘깁니다. HttpServlet에 들어 있는 코드가 GET 요청인 것을 보고 우리가 쓴 doGet을 부릅니다. doGet을 부르는 줄도 우리가 쓰지 않았습니다. doGet이 응답에 쓰는 글은 "안녕하세요"입니다.
  6. 브라우저가 200 응답을 받습니다. 본문은 "안녕하세요"입니다.

실행 결과

코드

// 등록: 이 주소로 온 요청을 이 클래스에 맡긴다
@WebServlet("/hello")
// 자격: 웹 요청을 받을 수 있는 서블릿 클래스
public class Hello extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        resp.setContentType("text/plain; charset=UTF-8");
        resp.getWriter().write("안녕하세요");
    }
}

이 모형의 전제

서블릿 컨테이너는 톰캣 11.0.24(Jakarta Servlet 6.1)이고, 브라우저는 주소마다 GET 요청을 한 번씩 차례로 보낸다고 가정했습니다. 주소의 localhost:8080은 내 컴퓨터에서 톰캣을 기본 포트로 띄웠을 때의 예입니다. 열두 가지 조합을 모두, 화면의 코드와 같은 소스를 컴파일해 웹 애플리케이션 폴더(WEB-INF/classes)에 넣고 실제 톰캣을 띄워 요청을 보낸 결과와 대조했습니다. 대조한 것은 클래스가 Servlet 타입인지, 톰캣의 주소 표, 응답의 상태 코드와 본문, 만들어진 객체 수, doGet 실행 횟수입니다. 모든 서블릿이 Servlet 인터페이스를 구현한다는 것과 HttpServlet이 그 구현이라는 것은 Jakarta Servlet 명세 2장을, @WebServlet을 붙인 클래스는 HttpServlet을 상속해야 하고 주소를 하나 이상 적어야 한다는 것은 명세 8.1.1절을 따랐습니다. 화면은 extends HttpServlet 하나로 자격을 나타냈지만, 정확한 조건은 Servlet 인터페이스의 구현이며 HttpServlet을 상속하는 것이 가장 흔한 방법입니다. 주소 등록도 @WebServlet 말고 web.xml 설정 파일이나 코드로 할 수 있는데, 여기서는 @WebServlet만 다뤘습니다. 화면의 코드는 import 줄과, 재정의한 메서드에 흔히 붙이는 @Override를 줄였습니다. @WebServlet만 붙인 일반 클래스가 첫 요청에 500을, 같은 등록으로 가는 그다음 요청부터 404를 돌려준다는 것은 명세가 정한 것이 아니라 이 톰캣 버전에서 관찰한 동작입니다. 톰캣이 객체를 만든 뒤 doGet에 이르기까지 거치는 init과 service 호출은 줄였고, "세부 동작 실습: 서블릿"에서 다룹니다.

앞 실습: AOP와 프록시 · 다음 실습: 컨트롤러

이 실습에 나오는 개념

이 실습에서 보는 것

설정

코드


      
    

그림

실행 비교

이렇게 바꿔 보세요