[ KOSTA 34일차 교육 ] 스프링 레거시 ( 3버전 ) - 2일차 | Apache, Tomcat, Servlet Container, DispatcherServlet, WebApplicationContext, Spring Container, Java Virtual Machine 사이의 큰 그림 | Spring Container와 DI & Singleton scope

junjun·2024년 6월 12일
0

KOSTA

목록 보기
32/48

정말 궁금했었고,
항상 찾아봐도 제가 원하는 그림 중
일부 단면만 찾아볼 수 있던 내용에 대해 정리할 수 있던 하루였습니다.

이 글을 읽고 나시면,
서블릿 컨테이너와 스프링 컨테이너의 관계
WAS와 WS의 관계에 대해 좀 더 깊이있게 이해할 수 있을 것이라 생각합니다.

Java Web Application에서 Spring Container에게 들어가기 위한 진입점이 Servlet Container인가요?

  • 이 설명은, 마치 아래의 그림과 같다할 수 있습니다.

  • 몇몇 블로그를 찾아보면, 이와 같은 그림의 설명들이 있습니다.

  • 서블릿 컨테이너가 스프링 컨테이너를 포함한다는 것인데, 호출 순서 측면에서 보면 납득할 수 있지만, 이는 잘못된 표현입니다.

  • 회사에 기획 팀, 프론트앤드 팀, 백앤드 팀이 있다면 기획 팀 안에 프론트앤드 팀이 있는 느낌입니다.

  • 기획 팀, 프론트앤드 팀, 백앤드 팀 간에 긴밀하게 상호 협조하여 돌아간다는 표현이 적절할 것입니다.

  • 이와 마찬가지로, 서블릿 컨테이너와 스프링 컨테이너는 긴밀한 서로간의 협조를 통해 웹 어플리케이션을 구동해준다 표현할 수 있겠습니다.

Apache Tomcat

  • Apache는 깃털 모양이고, Tomcat은 고양이입니다.

  • 즉, 원래 두 서비스는 독립된 서비스였습니다.

  • Apache는 웹서버의 역할을, 톰캣은 어플리케이션 서버의 역할을 했습니다.

  • 웹 어플리케이션 서버를 구동하기 위해
    예전에 설치해야하는 서비스는 Apache, Tomcat, 이 둘을 연결해주는 모듈. 이렇게 3가지 요소를 설치했어야 했습니다.

  • 이후 ApacheTomcat이 합쳐졌고, 이것이 Apache Tomcat 이라고 합쳐졌습니다.

  • TomcatApplication Server라고도 하고, Servlet Container라고도 합니다. 뉘앙스로 같은 대상을 가리키는 것이라 할 수 있겠습니다.

Java EE - Servlet 만을 사용하여 웹 개발할 때의 WAS의 모양

  • 웹서버(Apache)가 앞단에 있어서, 정적 리소스를 돌려주고. 동적인 처리를 요구하는 경우, 톰캣(Servlet Container)이 관리하는 서블릿을 호출하여 처리해주었습니다.

  • 즉, 이때는 스프링 ( 스프링 컨테이너 )의 도움 없이, 웹 서비스를 자바 자체만으로 제공하는 구조였습니다.

Spring을 배우고 난 뒤에 Tomcat의 모양

  • 톰캣이 처음 구동될 때, server.xml 을 통해 서버 자체의 설정을 마쳐준 뒤,
    톰캣 자체의 web.xml 로 톰캣이 관리하는 서비스들의 공통 설정을 진행합니다.

  • 우리 웹 어플리케이션의 /WEB-INFweb.xml을 통해 톰캣 자체의 웹 공통 설정을 제외한 우리 어플리케이션 자체의 웹 관련 설정을 해줍니다. 예를 들어, 특정 서블릿을 주어진 URI를 매핑해줍니다.

  • 여기서 초록색으로 표현된 DS는, Spring의 DispatcherServlet으로 서블릿 컨테이너에서 스프링 컨테이너로 들어가는 진입점 역할을 합니다.

  • request 마다 Application Server에서 thread가 생성됩니다. ( Tomcat이 자체적으로 Thread Pool을 관리합니다 )

  • Tomcat ( = Application Server, Servlet Container )가 하는 일
    => JSP -> Servlet ( .class 파일로 컴파일 )
    => 요청 시, 서블릿 초기화 ( init() + service() ) 호출, 이후 요청에 대해 service() 호출

  • 동적 생성, 단일 프로세스에 사용자 요청마다 멀티 쓰레드로 서로가 블록킹, 동기화 제어 없이
    각자가 빠르게 답변을 받아갈 수 있는 형태로 실행됨.

웹에서 들어오는 요청을 웹 서버에서 받는다.

  • Chrome.exe 도 프로세스, 내가 만든 페이지도 Process
  • 단순한 웹 요청을 받는다 = 멀티 프로세스 형식으로
  • Application Server는 하나의 프로세스, 여러 개의 쓰레드로 동작한다.
  • Web Server ( Apache )는 요청 당 프로세스 하나로, 멀티프로세스 방식으로 동작한다.
  • Application Server => 단일 프로세스, 멀티 쓰레드로 동작한다.

WAS에서 웹 서버와 서블릿 컨테이너의 가장 큰 차이는 무엇인가요?

  1. 정적인 자원을 요구하는 요청을 처리하냐, 동적인 요청을 처리하는 차이가 있습니다.

  2. 멀티 프로세스와 단일 프로세스 - 멀티 쓰레드의 차이입니다.

  3. Apache Web Server의 경우, 요청 당 프로세스가 하나 생성되고
    Tomcat
    Application Server에서 해당 웹 서버의 프로세스에 대한 요청에서 Thread로 받습니다.

  4. 어플리케이션 서버는 메모리의 힙 영역을 참조해서, 힙 영역에 인스턴스가 생성되어 있지 않다면 힙 영역에 인스턴스가 생성되어 있으면 만들어줍니다. 들어온 요청마다 Thread가 동작해서 나눠 사용합니다.

  5. 최초에 부른 애가 서블릿 메서드 - init() 을 해준다.

  • JSPServlet으로 변환해서 메모리에 올려놓는 작업
  • 그 다음번 요청부터는 생성된 서블릿을 참조.

  • 사용자가 몇천명 붙어있어도 견딜 수 있는 이유는, 서블릿의 인스턴스가 하나(싱글턴)으로 생성되고 사용되기 때문입니다.
  • 하나의 인스턴스를 여러 개의 쓰레드가 공유하며 사용하기에, 상태를 가지지 않는 것이 중요합니다.

Thread Pool

  • 쓰레드 풀
  • 위의 설정에 따르면, 동접자가 150명으로 유지될 수 있다.
  • 톰캣 버전마다 다르고, 서버급 컴퓨터는 3000, 4000, 7000 과 같은 형식으로 진행해야 한다.
  • 만약 계속 지속된다면.. Timeout & 잠시 후 다시 시도해주세요 와 같은 메시지가 뜰 것이다.. ( 티켓팅 하다보면 이러지 않는가 )

[ Tomcat(Servlet Container, Application Server), web.xml, DispatcherServlet, servlet-context.xml, ApplicationContext, Spring Container ]

다시 복습하면서, Tomcat의 설정부터 DispatcherServlet, Spring Container의 초기화까지 어떻게 진행될 수 있는지 정리해보겠습나다.

개인적으로 매우 크게 정리가 되어 좋았던 내용입니다.

1) Tomcat이 구동될 때, server.xml 을 참고하여 서버 자체의 초기화를 진행합니다.

2) Tomcat의 web 요청에 대한 동작이 기술된 web.xml 을 참고하여, Tomcat이 관리하는 여러 서비스에 대한 공통 설정을 진행해줍니다.

3) Tomcat이 하는 설정도 있지만, 웹 어플리케이션 자체으 web.xml 초기화 작업또한 진행됩니다. ( 우리 웹 프로젝트의 /WEB-INF 폴더 내의 web.xml을 참조합니다. )

4) web.xml에서 해야할 가장 중요한 일은, 서블릿의 초기화라 할 수 있습니다.

  • 서블릿 클래스를 찾아서 메모리에 올려줍니다.

5) 일반 서블릿의 경우는 그냥 만들어서 올려줄 수 있지만, 스프링의 서블릿 ( = 디스패처 서블릿 ) 또한 올려줍니다. 이 때, Init-Param 이라는 속성을 통해 servlet-context.xml 설정을 받아 DispatcherServlet에 초기화할 설정 정보를 전달합니다. => 이 순간에 Spring Container가 만들어지고 초기화됩니다.

6) Spring Container가 초기화될 때, ApplicationContext가 생성되어 Servlet이 아닌 다른 POJO 자바 클래스를 스프링 빈으로 등록하여 관리해줍니다. ( 스프링 컨테이너 )

7) 서블릿 컨테이너와 스프링 컨테이너는 servlet-context.xml, ApplicationContext를 통해 통신할 수 있습니다.

[ Servlet Container와 Spring Container의 차이? ]

  • Servlet Containerjavax의 것이고, Spring ContainerSpring의 것이라는 것이 차이점입니다.

  • 즉, 해당하는 라이브러리와 관리 체계가 다르고, 사용하는 방법 또한 다릅니다.

  • VM에서 참조하는 라이브러리와 영역 관리가 다른 것입니다.

  • 그렇지만, 상호간 긴밀한 협업을 통해 웹 어플리케이션 서비스를 효율적으로 구동할 수 있도록 해줍니다. ( 이 둘을 하나의 톰캣 안에 꾸겨넣는다 표현할 수 있습니다. )

Spring Container

  • DI ( Dependency Injection )

    • 서블릿 컨테이너가 만들지 않는 그 외 모든 인스턴스 ( 서블릿 제외 모든 POJO )는 스프링 컨테이너가 관리합니다.

    • 쉽게 말해서, Spring Container가 Servlet을 제외한 VO, DAO를 new를 통해 생성해주고 관리해줍니다. ( 사실은 내부적으로 Reflection API를 사용하므로 new를 사용한다는 표현은 잘못되었다 생각합니다 )

    • Spring에서 만들어 중앙 집중형으로 관리하는 스프링 빈을 ApplicationContext 라는 매개체를 통해 자신 내부 혹은 외부 서블릿 (톰캣)에게 전달해줍니다.

    • 스프링 컨테이너는 서블릿 컨테이너가 만들어 관리하지 않는 모든 인스턴스를 생성해주고, 관리하고 제공해줍니다.

    • 스프링에서 관리하는 클래스들을 스프링 빈이라 하고, 스프링 컨테이너가 관리해줍니다.

    • 스프링을 쓰겠다는 말은, 스프링 컨테이너를 통해 우리 빈을 관리하겠다는 말과 동일합니다. 즉, 우리가 쓸 모든 클래스, 인스턴스, 그들간의 관계를 Spring이 관리해주도록 하는 것입니다.

    • 기존에 GC에 의존한 인스턴스 관계를, 스프링 컨테이너가 빈의 생명주기 ( 라이프사이클 )을 관리하도록 해줄 수 있습니다.

    • 이런 인스턴스를 필요로 하는 어떤 다른 클래스에게 제공해주는 것을 의존성 주입이라 합니다.

    • 의존성을 준다는 것은, Bean 이라는 것을 만들어서 ( = 관리 대상의 클래스를 만들어서 ), Bean의 인스턴스를 만들어 Servlet Container ( = Tomcat )에게 주는 것입니다. 이것이 Spring Container가 해야할 일입니다. ( 의존성을 제공해주는 역할 )

    • 인스턴스를 언제 만들고, 누구에게 제공할 것인지, 어떠한 방식으로 생성하고 관리할 것인지가 Spring Container가 해야할 가장 큰 일이라 할 수 있습니다.

    • 서블릿은 스프링 컨테이너의 관리 대상이 아닙니다, 대신 Controller라는 POJO를 등록하여 DispatcherServlet에게 위임받은 웹 요청을 라우팅하여 이를 처리할 수 있도록 합니다.

    • 이렇게, 웹 요청을 처리하는 주체인 서블릿 컨테이너 (톰캣)에 대해 톰캣이 필요로 하지만, 서블릿이 아닌 POJO 클래스들(= 스프링 빈)을 하나하나 생성하고 관리하다 필요할 때 꽂아주는 역할을 하는 것이 스프링 컨테이너라 할 수 있겠습니다.

    • 이런 스프링 빈은 결과적으로 JVM위의 Heap 메모리 영역에 생성되기에, 사용 대상이 서블릿이던, 다른 스프링 컨테이너의 스프링 빈이던 모두 참조하여 사용할 수 있습니다.

    • 스프링에서는 기본적으로 어플리케이션 생성-종료시 까지 필요한 인스턴스가 하나씩만 유지되는 singleton 방식으로 빈을 생성합니다만, 빈을 요청할 때마다 생성해주는 prototype scope, 웹 요청시마다 생성되는 request scope, HttpSession 유지 시간까지 유지되는 session scope, 톰캣 위에 우리 어플리케이션 레벨에서 유지되는 application scope, 톰캣 자체가 shutdown 될 때 까지 유지되는 global session scope로 생성될 수 있습니다.

DispatcherServlet에 servlet-context.xml을 초기화 파라미터로 넘겨줄 때 일어나는 일

  • XML을 읽어서 무엇을 하는지?

    • ContextLoaderListener에게 일을 시킨다. = 이 친구가 ApplicationContext를 로드합니다

    • 각자 Context와 관련한 일 = servlet-context.xml ( = DispatcherServlet )

    • DispatcherServlet이 ApplicationContext에게 일을 시킵니다.

    • root-context.xml에게 시키는 일? = Tomcat이 여러 개의 웹 어플리케이션 사이의 공통 초기화 작업을 수행해줍니다.

    • 학급이 생성되면 반장이 생기는 것 처럼, DispatcherServlet이 생성되는 순간 servlet-context.xml을 통해 ApplicationContext가 생성됩니다 ( 정확히는 Web 환경이기에, WebApplicationContext 가 생성됩니다. 이 때, ViewResovler또한 초기화되어 빈으로 매핑됩니다.

DispatcherServlet <-> ApplicationContext

  • ApplicationContext에 Web관련 기능을 추가한 것이 WebApplicationContext입니다.

  • Controller, ViewResolver, LocaleResolver, HandlerMapping 등과 같은 웹 관련 스프링 빈들을 관리해줍니다.

  • 여러 개의 WebApplicationContext가 있는 것은, 톰캣 위에 여러 개의 웹 어플리케이션이 떠있을 수 있기 때문입니다.

DI ( Dependency Injection )

  • BeanFactory

    • 빈 객체 관리 및 빈 객체간 의존관계 설정 기능을 제공합니다.

    • 주된 구현체 : XmlBeanFactory

    • new 해서 만들어주는 기능만을 합니다 (초간단)

    • 인스턴스를 만들어서 가져가는 역할을 합니다.

  • ApplicationContext

    • AOP, 메시지 지원, 국제화 지원 등 BeanFactory 보다 많은 일들을 더 시킵니다.
      • ClassPathXmlApplicationContext
        • 프로젝트 내의 src/main/resource 읽어들이기 ( ex. log4j.xml )
      • FileSystemXmlApplicationContext
        • /WEB-INF/spring 내의 파일 등, C:\IT\Installation.. 등의 src/main/resource 외부의 파일 시스템
        • 참고 : 자바 어플리케이션의 src/main/resourcessrc/main/webapp/resources는 각각 자바 어플리케이션 자체의 자원 vs 웹 어플리케이션에서의 자원의 차이이다.
  • WebApplicationContext

    • Web Application 당 하나씩 생성되고, 웹 관련 컴포넌트들의 의존성을 관리해줍니다.
    • XmlWebApplicationContext

Spring Bean

  • 말 그대로, Spring Framework에서 생명주기가 관리되는 클래스들입니다. ( POJO 형태입니다 )

  • 종류로는 DAO, DataSource, Transaction Manager, Persistence Managers, Service 등이 있습니다.

  • Bean은 생성 방식에 따라 싱글톤, 프로토타입 .. 자동 의존관계 주입을 지원하며, Spring Container에게 초기화 시 발동되는 메서드, 소멸되기 전에 발동되는 메서드 등을 가집니다.

0개의 댓글