다시 웹, 백엔드로/스프링

웹 서버와 서블릿 컨테이너

EnoughTT 2023. 8. 11. 13:17

웹 서버와 서블릿 컨테이너

외장 서버

  • 톰캣 같은 WAS (웹 애플리케이션 서버) 를 설치
  • 서블릿 스펙에 맞추어 코드 작성 후 WAR 로 빌드, war 파일을 만듦 ➡️ 배포

내장 서버

  • 스프링 부트가 내장 톰캣을 포함
  • JAR 빌드, jar 실행 시 was 도 함께 실행됨

실습

tomcat 10 이상

java 17

 

웹 서버에 띄울 html 생성

index html 파일

서블릿 등록

servlet 코드

동작 순서

  • '/test' 로 요청이 오면 서블릿 실행
  • 'TestServlet.service' 출력
  • 'test' 로 응답

실행 시 톰캣 (WAS)에 배포 후 실행해야함

 

war 빌드와 배포

  • 프로젝트 폴더로 이동
  • cmd 창에서 프로젝트 빌드 (윈도우 : gradlew build)
  • war 파일 생성 확인 (build/libs/server-0.0.1-SNAPSHOT.war)

war 빌드
war 파일 생성 확인

war 압축 풀기

war 압축 풀기

파일 구성

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

파일 구조

war를 tomcat 서버에 구동시키기

tomcat ➡️ war 파일을 tomcat 폴더 webapps 에 복사/붙여넣기 ➡️ tomcat 서버 실행

 

확인

localhost:8080/index.html
localhost:8080/test
service메서드에 들어갔을 경우 호출되는 print문

 

 

서블릿 컨테이너 초기화 - 1

WAS를 실행하는 시점에 필요한 초기화 작업들이 있음

서비스에 필요한 필터, 서블릿 등록 ➡️ (스프링을 사용한다면) 스프링 컨테이너 생성 ➡️ 서블릿과 스프링을 연결하는 디스페처서블릿도 생성 해야함

이전엔 setting.xml 파일로 초기화 했지만 자바코드를 사용한 초기화도 지원함

 

인프런 스프링부트 - 김영한

 

서블릿 컨테이너 초기화 개발

ServletContainerInitializer 라는 초기화 인터페이스를 제공
이름 그대로 서블릿 컨테이너를 초기화하는 기능을 제공


서블릿 컨테이너는 실행시점에 초기화 메서드인 onStartup() 을 호출

애플리케이션에 필요한 기능들을 초기화하거나 등록할 수 있음

서블릿 컨테이너 초기화

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

print문 호출

 

 

서블릿 컨테이너 초기화 - 2

서블릿을 서블릿 컨테이너 초기화 시점에 프로그래밍방식으로 직접 등록 하는 방법

 

애플리케이션 초기화

 

애플리케이션초기화를 진행하려면 인터페이스가 필요하기 때문에 생성

AppInit.class

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

MyContainerInitV2.class

@HandlesTypes 어노테이션
ServletContainerInitializer 인터페이스를 구현할 때 사용
웹 어플리케이션의 시작 시점에 특정 타입의 클래스를 처리하려는 클래스에 적용

 

프로그래밍 방식으로 HelloServlet 서블릿을 서블릿컨테이너에 직접 등록  
/hello-servlet 를 호출하면 HelloServlet 서블릿 실행

 

프로그래밍 방식을 사용하는 이유
@WebServlet 어노테이션 사용 시 서블릿을 편리하게 등록할 수 있음. 하지만 /test 경로 변경 시 직접 코드를 수정해야함

프로그래밍 방식은 코딩을 더 많이해야하고 불편하지만 무한한 유연성을 제공함
1. /hello-servlet 경로를 상황에 따라 바꿔 외부 설정을 읽어서 등록할 수 있음
2. 서블릿 자체도 특정 조건에 따라 if 문으로 분기해 등록하거나 뺄 수 있음
3. 서블릿을 내가 직접 생성하기 때문에 생성자에 필요한 정보를 넘길 수 있음

 

애플리케이션 초기화( AppInit )는 어떻게 실행되는가?

MyContainerInitV2.class

 

애플리케이션 초기화 과정

* 애플리케이션 초기화 과정

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

 

MyContainerInitV2 를 실행하려면 V1 과 같이 'jakarta.servlet.ServletContainerInitializer' 에 등록되어야 함

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

 

 

 

 

feat. 스프링부트 - 핵심 원리와 활용 (김영한)