컨테이너리스 개발 준비
Spring Boot는 서블릿 컨테이너 관련 작업을 수행하므로 개발자는 BEAN 구축에만 집중할 수 있습니다.

컨테이너를 설치 및 배포하지 않고 서블릿 컨테이너가 코드에서 작동하는 방식 구현해보자.
빈 main() 메서드만 남기고 Spring Boot가 사용 중인 것으로 보이는 다음 두 줄을 삭제합니다.
@SpringBootApplication
springApplication.run(HellobootApplication, args);
서블릿 컨테이너 시작

서블릿 컨테이너를 직접 설치하는 대신 독립 실행형 프로그램을 만들어 서블릿 컨테이너를 시작합니다.
Spring Boot 프로젝트 생성 시 웹 모듈을 선택하면 아래와 같은 내장 tomcat 라이브러리(서블릿 컨테이너 제품)가 추가된다.

임베디드 Tomcat의 초기화 및 손쉬운 구성을 지원하기 위해 Spring Boot TomcatServletWebServerFactoryTomcat 웹 서버(서블릿 컨테이너)를 실행하는 코드를 생성할 수 있습니다.
public static void main(String() args) {
ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
WebServer webServer = serverFactory.getWebServer();
webServer.start();
}
- TomcatServletWebServerFactory: Tomcat의 서블릿 웹 서버를 생성하는 팩토리 클래스입니다.
- getWebServer: 실제 웹 서버(서블릿 컨테이너)를 생성하는 생성 함수.
메인 메서드가 실행 중일 때 Tomcat 서버가 포트 8080에서 실행 중인지 확인할 수 있습니다(http 요청을 전송하여 확인할 수 있음).
서블릿 등록
서블릿 컨테이너에 서블릿(웹 구성 요소) 추가.

서블릿을 등록하려면 서블릿 컨텍스트서블릿 등록과 같은 초기화 작업을 수행할 때 ServletWebServerFactory의 getWebServer() 메서드에 ServletContextInitializer를 구현하는 객체를 전달합니다.
ServletContextInitializer @FunctionalInterface그래서 람다 식으로 바꿔서 사용하면 편리합니다. (하나의 기능을 가진 인터페이스)
@FunctionalInterface
public interface ServletContextInitializer {
void onStartup(ServletContext servletContext) throws ServletException;
}
서블릿은 HttpServlet 클래스를 상속하고 필요한 메서드를 재정의하여 만들 수 있습니다.
https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html
HttpServlet(Java(TM) EE 7 사양 API)
서블릿이 PUT 요청을 처리할 수 있도록 서버에서 호출합니다(서비스 메소드를 통해). PUT 작업을 통해 클라이언트는 파일을 서버에 배치할 수 있으며 FTP를 통해 파일을 보내는 것과 유사합니다. 이 메서드를 재정의할 때 모든 콘텐츠 헤더를 그대로 둡니다.
docs.oracle.com
서블릿을 등록할 때 서블릿 이름과 서블릿 객체를 사용합니다. 매핑할 URL 정보는 서블릿 등록 정보에 지정되어 있습니다.
서블릿에서 Http서블릿 요청다음을 사용하여 요청 정보 추출 HttpServlet 응답다음으로 답변 생성
– 3가지 요소(상태 코드, 헤더, 본문)로 웹 요청을 생성합니다.
public static void main(String() args) {
ServletWebServerFactory serverFactory = new TomcatServletWebServerFactory();
WebServer webServer = serverFactory.getWebServer(servletContext -> {
servletContext.addServlet("hello", new HttpServlet() {
@Override
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.setStatus(HttpStatus.OK.value());
res.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE);
res.getWriter().println("Hello Servlet");
}
}).addMapping("/hello");
});
webServer.start();
}
(미리 적어두었다가 다음 강의에 활용합시다.)
프런트 컨트롤러는 처리할 요청을 분류하기 위해 요청을 구문 분석한 후 요청을 처리하는 핸들러(컨트롤러 메서드)로 전달합니다.
핸들러가 반환한 반환 값을 해석하여 웹 요청을 구성합니다.
전면 컨트롤러의 두 가지 주요 기능은 다음과 같습니다. 연결 및 바인딩.
세부 규칙을 지정하면 공통 코드를 사용하여 매핑 및 바인딩을 처리할 수 있습니다.
- 매핑: HTTP 요청을 처리하기 위한 핸들러 식별 및 연결
- 바인딩: 웹 요청 정보를 추출하여 의미 있는 개체로 처리기에 전달하는 프로세스입니다.
if (req.getRequestURI().equals("/hello") && req.getMethod().equals(HttpMethod.GET.name())) {
String name = req.getParameter("name");
String ret = helloController.hello(name);
resp.setStatus(HttpStatus.OK.value());
resp.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE);
resp.getWriter().println(ret);
}
