스프링부트 동작 원리-2

joon·2021년 7월 11일
0

스프링부트 이론

목록 보기
5/5

1. 내장 톰켓을 가진다.

톰켓을 따로 설치할 필요 없이 바로 실행 가능하다.

  • 톰켓이란?

    만약 jsp파일이나 자바코드 파일이 요청 받았을시에 아파치는 자바코드를 이해 못 하기때문에 응답하지 못한다. 그래서 아파치에 톰캣을 추가적으로 단다. 톰캣을 달면 아파치가 이해 못하는 파일이 요청될 시 제어권을 톰캣에 넘긴다.
    결국 톰캣이 하는 일은 jsp파일안에 있는 모든 자바 코드를 컴파일하고 컴파일이 끝나면 컴파일 된 데이터를 .html에 덮어씌운다. 다시 아파치에 돌려주고 아파치는 해당 .html파일을 클라이언트에 응답해준다.

결론: 아파치는 요청한 파일을 응답해준는 것이고 톰켓은 요청한 파일 중에 java코드가 요청이 되면 그것을 컴파일해서 html파일로 번역해서 돌려주는 것이다.


2. 서블릿 컨테이너

서블릿은 자바코드로 웹을 할 수 있는 것이고 그것들을 모아 놓은 것을 서블릿 컨테이너라고한다. 톰캣이다. 톰캣은 서블릿 컨테이너이다.

쓰레드의 적정 개수를 정해서 만들고 다 쓰면 삭제하지 않고 사용한 쓰레드를 재사용함으로써 속도를 올린다.
정적인 파일(html,css,javascript) 요청을 할 경우는 아파치가 작동하고 톰캣이 작동을 안한다. 근데 스프링은 정적인 파일을 요청할 수 없다 요청방식에는 URL방식이 있고 URI방식이 있다. URL 방식은 자원 접근 방식이고 URI는 식별자 접근 방식이다. 스프링은 URL 접근 방식을 막아놓았다. 그래서 식별자를 통해서 요청을 해야하는데, 특정한 파일 요청은 할 수 없다는 것이다. 요청 시에는 무조건 자바를 거쳐야한다. (즉 아파치는 무조건 톰캣에 제어권을 넘겨야한다. 톰캣이 자바를 컴파일 할 수 있기 때문)


첫 번째 그림에서 스무번째(이미 설정한) 스레드까지는 'Yes'선을 타서 객체(서블릿 객체)를 생성하는 것이다. 21번째(설정한 수보다 많은) 요청이 오면 'No'선과 같이 객체(서블릿 객체)를 생성하지 않고 이미 생성된 서블릿 객체를 재사용한다.
최종적으로 만들어지는 것은 Request객체와 Response객체이다. 스프링이 아닌 톰캣이 들고있는 객체이다.

3. web.xml의 하는일

  • ServletContext의 초기 파라미터를 설정한다.
  • Session의 유효시간 설정한다.
  • Servlet/JSP에 대한 정의
  • Servlet/JSP 매핑
  • Mime Type 매핑
  • Welcome File List
  • Error Pages 처리
  • 리스너/필터 설정
  • 보안

Servlet/JSP 매핑시에 모든 모든 클래스에 매핑을 적용시키기에는 코드가 너무 복잡해지기 때문에 FrontController 패턴을 이용한다.


4. FrontController 패턴

URI 혹은 자바 파일의 요청이 들어오면 바로 자원으로 가지 못하고 톰캣을 거친다.
이때 톰캣에서 최초에 일어나는 일은 request와 response 객체를 만든다. request나 response객체는 톰캣이 자동으로 생성해준다.

web.xml에 jsp/severlet 매핑이 너무 많이 들어있으면 복잡해진다. 특정 주소가 들어오면 특정 주소는 FrontController가 낚아채도록 지정함. FrontController로 들어온 주소는 자원으로 갈 수 있게끔 request를 한다. (스프링은 내부에서는 자원 접근이 가능하다)
이때 발생하는 request 때문에 기존의 request의 객체와 response 객체가 바뀌는 문제가 있다!
기존의 request,response 객체를 유지한채 새로운 request,response 객체를 생성하는 방법이 필요하다.
그 방법이 RequestDispatcher라는 방법이다.


5. RequestDispatcher

RequestDispatcher는 필요한 클래스 요청이 도달했을 때 FrontController에 도착한 request와 response를 그대로 유지시켜준다.

A가 a.jsp 파일을 요청하면 a.html파일로 응답 받을 것이다. 그러면 a.jsp파일에대한 request객체와 response객체가 만들어진다.해당 화면의 데이터가 request객체에 존재한다.
한편, 새로운 화면에서는 A가 b. jsp 파일을 요청하면 b.html파일로 응답 받을 것이다.
이 때 이전 화면에서RequestDispatcher방식을 이용하면 새로운 화면에서 이전의 requset, response객체를 유지한채로 사용 할 수 있다. 즉, RequestDispatcher방식을 이용해야지 페이지 간 데이터 이동이 가능하다.


6. DispatchServlet

FrontController 패턴을 직접 짜거나 RequestDispatcher를 직접 구현할 필요가 없다.
스프링에는 DispatchServlet이 있기 때문이다.
DispatchServlet은 FrontController+ RequestDispatcher이다.
DispatchServlet이 자동 생성되어 질 때 수 많은 객체가 ioc로 생성된다. 보통 필터들인데 해당 필터들은 직접 등록할 수도 있고 기본적인 필터들은 자동 등록 되어진다.

DispatchServlet은 컴포넌트 스캔 후 메모리에 주소 분배를 한다. src내부에 있는 모든 자바 파일을 다 뒤져서 필요한 것을(필요성은 어노테이션을 이용해서 구분한다.) 메모리에 올린다. 그리고 주소를 분배한다.


7. 스프링 컨테이너

DispatchServlet이 실행되기 전에 ContextLoaderListener가 실행된다.
모든 객체, 스레드가 공통적으로 사용하는 것은 DB관련 된 것인데 ContextLoaderListener를 통해서 미리 띄운다. ContextLoaderListener는 root_ApplicationContext라는 xml파일을 읽는데 root_ApplicationContext가 스레드 끼리 공통적으로 사용하는 것들을 메모리에 띄워주고 ioc컨테이너에서 관리한다.

ContextLoaderListener가 실행되고 DispatchServlet이 실행되기 때문에 DispatchServlet가 메모리에 띄운 것들은 DB에 접근이 가능하지만 그 반대는 불가능하다.

DispatchServlet에 의해 생성되어지는 많은 객체들은 어디서 관리되는가

1. ApplicationContext

수 많은 객체들이 ApplicationContext에 등록된다. IOC(제어 역전)이라 한다. 개발자가 직접 new를 통해 객체를 생성하면 해당 객체를 가리키는 레퍼런스 변수를 관리하기 어렵다. 그래서 스프링이 해당 객체를 관리한다(어노테이션 사용). 이때 주소를 몰라도 된다. 필요할 때마다 DI(의존성 주입)을 하면 되기 때문이다. 필요한 곳에서 ApplicationContext에 접근하여 필요한 객체를 가져올 수 있다. ApplicationContext은 싱글톤으로 관리되기 때문에 어디에서 접근하든 동일한 객체라는 것을 보장한다.

ApplicationContext의 종류에는 두 가지가 있다.
(1) root-applicationContext
(2) servlet-applicationContext

serverlet-applicationContext는 ViewResolver, Interceptor, MulipartResolver 객체를 생성하고 웹과 관련된 어노테이션 Controller, RestController를 스캔하고 메모리에 띄우고 해당 파일은 DispatchServlet에 의해 실행된다. 웹과 관련된 어노테이션들만 스캔하고 메모리에 띄운다.

root-applicationContext는 해당 어노테이션을 제외한 Service, Repository등을 스캔하고 DB관련 객체를 생성한다. (스캔은 메모리에 로딩한다는 뜻)
해당 파일은 ContextLoaderListener에 의해 실행된다. ContextLoaderListener를 실행해주는 것은 web.xml이기 때문에 root-applicationContext는 serverlet-applicationContext보다 먼저 로드 된다. 당연히 serverlet-applicationContext에서는 root-applicationContext가 로드한 객체를 참조할 수 있지만 그 반대는 불가능하다. 생성 시점이 다르기 때문이다.

2. Bean Factory

필요한 객체를 Bean Factory에 등록할 수도 있다. 여기에 등록하면 초기에 메모리에 로드되지않고 필요할 때마다 getBean() 메소드를 호출하여 메모리에 로드 할 수 있다. 이것도 IOC이다. 필요할 때마다 DI를 하여 사용할 수 있다. ApplicationContext와 다른 점은 BeanFactory에 로드되는 객체들은 미리 로드되지 않고 필요할 때 호출하여 로드하기 때문에 lazy-loading이 된다.


8. 요청 주소에 따른 컨트롤로 요청(Handler Mapping)

GET요청 -> http://localhost:8080/post/1
해당 주소 요청이 오면 적절한 컨트롤러 함수를 찾아서 실행한다.


9. 응답

html파일을 응답할지 data파일을 응답할지 결정해야한다. html파일을 응답하게 되면 ViewResolver가 관여하고 data파일을 응답하게 되면 MessageConverter가 작동하게 되는데 메시지를 컨버팅할 때 기본 전략은 jason이다.






유튜브 출처: 데어프로그래밍,데어프로그래밍,데어프로그래밍,데어프로그래밍,데어프로그래밍,데어프로그래밍

profile
개발 및 공부 일기 블로그

0개의 댓글