웹 서버와 서블릿 컨테이너
외장 서버
- 톰캣 같은 WAS (웹 애플리케이션 서버) 를 설치
- 서블릿 스펙에 맞추어 코드 작성 후 WAR 로 빌드, war 파일을 만듦 ➡️ 배포
내장 서버
- 스프링 부트가 내장 톰캣을 포함
- JAR 빌드, jar 실행 시 was 도 함께 실행됨
실습
tomcat 10 이상
java 17
웹 서버에 띄울 html 생성

서블릿 등록

동작 순서
- '/test' 로 요청이 오면 서블릿 실행
- 'TestServlet.service' 출력
- 'test' 로 응답
실행 시 톰캣 (WAS)에 배포 후 실행해야함
war 빌드와 배포
- 프로젝트 폴더로 이동
- cmd 창에서 프로젝트 빌드 (윈도우 : gradlew build)
- war 파일 생성 확인 (build/libs/server-0.0.1-SNAPSHOT.war)


war 압축 풀기

파일 구성
- WEB-INF
- classes
- TestServlet 파일이 컴파일 되서 들어가짐 (hello.servlet.TestServlet.class)
- lib
- classes
- Index.html
- META-INF

war를 tomcat 서버에 구동시키기
tomcat ➡️ war 파일을 tomcat 폴더 webapps 에 복사/붙여넣기 ➡️ tomcat 서버 실행
확인



서블릿 컨테이너 초기화 - 1
WAS를 실행하는 시점에 필요한 초기화 작업들이 있음
서비스에 필요한 필터, 서블릿 등록 ➡️ (스프링을 사용한다면) 스프링 컨테이너 생성 ➡️ 서블릿과 스프링을 연결하는 디스페처서블릿도 생성 해야함
이전엔 setting.xml 파일로 초기화 했지만 자바코드를 사용한 초기화도 지원함

서블릿 컨테이너 초기화 개발
ServletContainerInitializer 라는 초기화 인터페이스를 제공
이름 그대로 서블릿 컨테이너를 초기화하는 기능을 제공
서블릿 컨테이너는 실행시점에 초기화 메서드인 onStartup() 을 호출
애플리케이션에 필요한 기능들을 초기화하거나 등록할 수 있음

WAS 실행 시 'MyContainerInitV1' 클래스를 초기화 클래스로 인식하고 로딩 시점에서 실행

서블릿 컨테이너 초기화 - 2
서블릿을 서블릿 컨테이너 초기화 시점에 프로그래밍방식으로 직접 등록 하는 방법
애플리케이션 초기화
애플리케이션초기화를 진행하려면 인터페이스가 필요하기 때문에 생성

AppInit 인터페이스를 구현하기 위해 MyContainerInitV2 클래스 생성

@HandlesTypes 어노테이션
ServletContainerInitializer 인터페이스를 구현할 때 사용
웹 어플리케이션의 시작 시점에 특정 타입의 클래스를 처리하려는 클래스에 적용
프로그래밍 방식으로 HelloServlet 서블릿을 서블릿컨테이너에 직접 등록
/hello-servlet 를 호출하면 HelloServlet 서블릿 실행
프로그래밍 방식을 사용하는 이유
@WebServlet 어노테이션 사용 시 서블릿을 편리하게 등록할 수 있음. 하지만 /test 경로 변경 시 직접 코드를 수정해야함
프로그래밍 방식은 코딩을 더 많이해야하고 불편하지만 무한한 유연성을 제공함
1. /hello-servlet 경로를 상황에 따라 바꿔 외부 설정을 읽어서 등록할 수 있음
2. 서블릿 자체도 특정 조건에 따라 if 문으로 분기해 등록하거나 뺄 수 있음
3. 서블릿을 내가 직접 생성하기 때문에 생성자에 필요한 정보를 넘길 수 있음
애플리케이션 초기화( AppInit )는 어떻게 실행되는가?


* 애플리케이션 초기화 과정
- @HandlesTypes 어노테이션에 애플리케이션 초기화 인터페이스 지정 (여기서는앞서만든 AppInit.class 인터페이스지정)
- 서블릿 컨테이너 초기화( ServletContainerInitializer)는 파라미터로 넘어오는 Set<Class<?>> 에 애플리케이션 초기화인터페이스의 구현체들을 모두 찾아서 클래스 정보로 전달 (AppInit.class 의 구현체인 AppInitV1Servlet.class 정보 전달), 참고로 객체 인스턴스가 아니라 클래스정보를 전달하기 때문에 실행하려면 객체를 생성해서 사용해야 함
- appInitClass.getDeclaredConstructor().newInstance() 리플렉션을 사용, 객체 생성 (= new AppInitV1Servlet())
- appInit.onStartup(ctx) 애플리케이션 초기화 코드를 직접 실행하면서 서블릿 컨테이너 정보가 담긴 ctx 도 함께 전달
MyContainerInitV2 를 실행하려면 V1 과 같이 'jakarta.servlet.ServletContainerInitializer' 에 등록되어야 함

서버 구동 후 '/hello-servlet' 로 가보면 hello servlet! 이 응답값으로 나옴


feat. 스프링부트 - 핵심 원리와 활용 (김영한)
'다시 웹, 백엔드로 > 스프링' 카테고리의 다른 글
스프링 부트 스타터와 라이브러리 관리 (0) | 2023.08.18 |
---|---|
스프링 부트와 내장 톰캣 - 2 (0) | 2023.08.17 |
스프링 부트와 내장 톰캣 - 1 (0) | 2023.08.17 |
웹 서버와 서블릿 컨테이너 - 2 (0) | 2023.08.16 |
Spring Framework (0) | 2023.07.11 |