[springboot] 스프링 부트 동작원리
스프링 부트 동작원리
-
내장 톰켓을 가진다.
- Socket : 운영체제가 가지고 있는것
- A와 B 메시지 교환하려면 운영체제의 Socket을 이용하면된다.
- A 소켓오픈! (5000포트 오픈)-> B가 ip주소:5000 연결임됨 -> 서로 메시지를 연결받을 수 있음 –> C가 갑자기 연결하려고함 -> C가 5000포트로 연결할 수 없음
- 그래서 5000포트(메인 쓰레드) 연결이 되는 용도만 -> 연결이 되는 순간 새로운 Socket 5001포트로 -> 5000연결 끊고 B는 5001포트와 연결하고 통신을함 -> 5001포트(쓰레드1) –> C가 5000포트와 연결 ->500연결 끊고 5002포트(새로운 쓰레드2)와 연결
- 쓰레드는 time slice 동시에 동작하는 것처럼 보임!
- 장점 : 연결이 계속 되어있음
- 단점 : 부하가 크다 (느려진다) = 연결이 백명, 천명단위일때
- http 통신 : 연결을 지속시키지않고 연결을 끊어버리는 stateless방식을 쓴다! (단순히 문서를 전달하는 통신임)
- A와 B가 C에 연결해서 데이터를 받고싶을때
- A가 C에게 a.txt. 요청 -> C Socket이 80포트로 쓰레드를 만들지 않고 direct하게 찾아서 요청에 응답하고 끊어버림
- 장점 : 연결에 끊기기 때문에 부하가 적음
- 단점 : 다시 연결될때 항상 새로운 사람으로 인식함(구분하지 못한다.)
- http : html(확장자로 만들어진 문서)를 필요한 사람에게 전달하는 것(문서 전달의 목적)
- A와 B가 C에 연결해서 데이터를 받고싶을때
- 톰켓
- http는 운영체제가 가지고있는 socket을 가지고 만들어짐 -> 프로그램이 운영체제가 기능을 가져서 만든걸 ‘시스템 콜’ 이라고함
- 웹서버 정의
- ex) 내가 컴퓨터를 사고 재밌는 동영상(3개)을 가지고있음 -> 친구들이 내 동영상을 보고싶어함(나의 데이터를 필요로하는 상황) -> 인터넷통신을 통해서 나에게 보여줄수 있겠니? -> 내가 ‘갑’, 친구는 ‘을’
- 웹서버는 갑, 즉 을이 필요한 데이터를 가지고있다는 것
- (‘을’이 ‘갑’에게 request를 함 -> request를 하기 위해서는 위치를 알아야함(ip주소)) -> 1번,2번,3번 동영상 중 어떤 동영상이 필요한지 명시해줘야함(URL: 자원요청의 주소)
- (‘갑’은 response를 해줌 -> ‘을’이 request할때의 정보를 토대로 response를 해줌)
- 즉, ‘갑’은 ‘을’의 ip주소를 모른다. 왜냐 응답해주는 구조거든
- 요청하지 않았을 때는 응답을 할 수 없음 —> 알기 위해서는 socket연결이 필요하다.
- 우리가 하는
http통신은 단순하게 요청시에 응답만 해주는 구조
고, 응답은 단순하게html문서
혹은특정자원
을 요청에 대해서만 해주면됨 –> 이것을 static 자원(정적인 자원)이라고함
- 아파치가 있다.(request, response)
- 아파치는 요청한 파일을 응답해주는 것
- 톰켓
- 아파치(정적인 자원에 대한 request와 response응답만) + 톰켓
- 아파치가 이해하지 못하는 파일(jsp, 자바코드)의 요청을 제어권을 톰켓에게 넘김
- .톰켓은 jsp안에 있는 모든 자바코드들을 컴파일하고 -> 컴파일 끝나면 -> 컴파일된 데이터를 .html에다가 덮어 씌움 -> 다시 아파치에게 돌려줌 -> 아파치는 html파일을 응답해줌
- 요청한 파일중에 자바코드가 요청이 되면 그것을 컴파일해서 html파일로 번역해서 돌려주는 역할
- Socket : 운영체제가 가지고 있는것
-
서블릿 컨테이너
- 서블릿 : 자바로 웹을 할 수 있는 것을 의미
- 서블릿 컨테이너 : 자바코드로 웹을 할 수 있는 것을 모아서 컨테이너로 만들어 논것(톰켓)
- client —request(자바)—> 서블릿 컨테이너(톰켓) –> 최초요청 여부 –> Y –> 메모리로딩 –> 객체 생성 –> init()
- 최초의 요청이 들어올 때
- 쓰레드 생성(수백명, 수만명의 요청이 있을때, 동시처리를 위해서 쓰레드를 생성) = 서버에 성능에 맞게 생성 —-> 서블릿 객체를 만듬(쓰레드마다 서블릿객체를 만듬) —-> 응답을 하면 —-> 다음 요청에 대기가 있다면 재사용한다.(그래서 빠르게 응답할 수 있다(쓰레드 지우고 이런작업을 안하고 바로 재사용하기 때문에))
- 최초의 요청이 들어올 때
- client –> 서블릿 컨테이너(톰켓) –> 최초요청 여부 –> N –> 이미 생성된 객체 재사용
- URL : 자원에 접근할때 사용하는 주소 요청방식
- 스프링이 다 막아났음, 사용 못함
- ex) http://naver.com/a.png
- URI : 식별자를 통해서 접근하는 방식
- 특정한 파일 요청을 할 수 없다.
- 즉, 요청 시에는 무조건 자바를 타야한다. (제어권을 톰켓이 갖음)
- ex) http://naver.com/picture/a
- URL : 자원에 접근할때 사용하는 주소 요청방식
-
web.xml
filter역할(= 성지키는 문지기)
웹서버에 진입을 하면 최초에 도는 것
- ServletContext의 초기 파라미터
- 한번 설정해두면 어디서든지 사용할 수 있다.
- ex) 성 들어가기 위한 암구호같은 역할
- Session의 유효시간 설정
- ex) 성 안에서 돌아다닐 수 있는 기간설정
- Servlet/JSP에 대한 정의, Servlet/JSP 매핑
- ex) a가 (다)라는 목표를 간다고하면 문지기가 가는 위치를 알려줌
- ex) 정의를 보고 매핑을 해줌((다)는 서울이다. 서울로가라)
- Mime Type 매핑
- ex) a가 들고 온 데이터 타입(Mime Type)을 물어봄
- ex) 너가 우리 성에 들고 들어올때 어떤 물건들 들고 들어왔니? —> 아무것도 안들고 왔을 때 (http의 GET방식 : select) , 쌀을 들고왔음(쌀을 확인하고 쌀창고로 보냄)
- Welcome File list
- ex) a가 그냥 왔음 —> 문지기가 Welcome File(ex 광장)로 보냄
- Error Pages 처리
- ex) a가 (파)라는 곳을 감 –> (파)는 없음 –> 문지기가 에러페이지로 보냄
- 리스너/필터 설정
- 필터
- a의 신분을 확인하는 것 (들어오게/못들어오게)
- 리스너
- ex) 문지기 옆에서 특정한 부분만 확인해서 낚아채서 처리하는 것
- 필터
- 보안
- 보안 하는 것
- ServletContext의 초기 파라미터
-
FrontController 패턴
최초 앞단에서 request요청을 받아서 필요한 클래스에 넘겨준다. 왜? web.xml에 다 정의하기가 너무 힘듬.
- request요청 —> 최초의 요청 (URI나 자바파일 요청)—> 톰켓 —> request객체(요청한 사람의 모든정보, 어떤 데이터를 요청했는지, 데이터를 들고왔는지), response객체(내가 응답해줘야하는 객체) 생성 = 톰켓이 객체로 만들어줌 —> web.xml에서 설정한 특정주소가 들어오면 frontController가 낚아채간다 —> 자원에 다시 새로운 request한다.(내부에서는 자원접근 가능하다.) —> {기존에 있는 request와 response객체를 유지하는 기법이 필요하다 ==
RequestDispatcher
이용한다! }
이때 새로운 요청이 생기기 때문에 request와 response가 새롭게 new될 수 있다. 그래서 아래의 RequestDispatcher가 필요하다
- request요청 —> 최초의 요청 (URI나 자바파일 요청)—> 톰켓 —> request객체(요청한 사람의 모든정보, 어떤 데이터를 요청했는지, 데이터를 들고왔는지), response객체(내가 응답해줘야하는 객체) 생성 = 톰켓이 객체로 만들어줌 —> web.xml에서 설정한 특정주소가 들어오면 frontController가 낚아채간다 —> 자원에 다시 새로운 request한다.(내부에서는 자원접근 가능하다.) —> {기존에 있는 request와 response객체를 유지하는 기법이 필요하다 ==
-
RequestDispatcher
- 필요한 클래스 요청이 도달했을 때 FrontController에 도착한 request와 response를 그대로 유지시켜준다.
- A —> a.jsp 로 요청하면 a.html —-> A로 응답
- 그 다음 페이지인 A —> b.jsp로 요청하면 b.html —> A응답
- 이때 a.html에서 b.html로 이동할때 requestDispatcher을 사용하면 기존의 request객체를 재사용함으로 a.html의 데이터를 가지고 b.html로 이동할 수 있다.
-
DispatchServlet
DispatcherServlet = FrontController 패턴 + RequestDispatcher 임으로 FrontController나 RequestDispatcher을 직접구현할 필요가 없다!
- DispatchServlet이 자동생성되어 질 때 수 많은 객체가 생성(IoC)된다. 보통 필터 혹은 객체들이다(filter, controller, repository, service, configuation….). 해당 필터들은 내가 직접 등록할 수 도 있고 기본적으로 필요한 필터들은 자동 등록 되어진다.
- 스프링에서는 DispatchServlet을 자동 지원함
-
스프링 컨테이너
DispatchServlet에 의해 생성되어지는 수 많은 객체들은 어디에서 관리될까?
- request –> web.xml –> DispatchServlet
- DispatchServlet
- src 소스폴더안에 수많은 자바파일이 있는데
- static파일 : main 메소드가 실행되기전에 메모리에 떠있음
- 자바파일 : new 객체! 특정한 타이밍에 메모리에 뜨고 사라짐.
- 궁극적인 목적 주소분배(ex어떤 주소가 왔을 떄 일로가)
컴포넌트 스캔
을 통해서 src 내부에 있는 모든파일을 new를 해서 필요한것들을 메모리에 올린다. ex) com.cos.blog / 이것을 Ioc라고한다!- @Controller, @RestController, @configration, @Repository, @Service, @Component… 와 같은 어노테이션을 찾아서 스프링이 알아서 메모리에 띄운다. / DI라고한다!
- 그래서 메모리에 뜨면 주소분배를 할 수 있다.
- 공통적으로 쓸 수 있는거! ==> DB Connection — 이런것들은 ContextLoaderListener을 통해서 뛰운다
- ContextLoaderLister가 root-context.xml(ApplicationContext.xml) 파일을 읽음
- 쓰레드마다 따로 관리해야되는것이 아니라 공통적으로 써야되는 것들을 메모리에 띄운다. 그리고 Ioc 컨테이너에서 관리해죠
- web.xml –>1번 ContextLoaderListener 먼저 –>2번 DispatcherServlet
- 그래서 1번으로 띄운 DB는 2번으로 띄운것에 접근을 못해! 반대로는 가능
- ContextLoaderLister가 root-context.xml(ApplicationContext.xml) 파일을 읽음
- DispatchServlet
- ApplicationContext는 두가지 종류가 있음(root-applicationContext, servlet-applicationContext)
- servlet-applicationContext
- 웹 관련된 정보만 관리, 웬 관련되는 어노테이션만 스캔해서 메모리에 띄우는얘
- viewResolver, Interceptor, MultipartResolver객체를 생성하고 웹과 관련된 어노테이션 Controller, RestController를 스캔한다.
- 해당 파일은 DispatcherServlet에 의해 실행된다.
- root-applicationContext
- @Service, @Repository등을 스캔(메모리에 로딩)하여 DB관련 객체를 생성
- 해당파일은 ContextLoaderListener에 의해 실행 된다.
- servlet-applicationContext보다 먼저 로드된다. 생성시점이 다르다.
- servlet-applicationContext
- Bean Factory
- 필요한 객체를 Bean Factory에 등록할 수도 있다.
- 초기에 메모리에 로드하는게 아니고 필요할때 getBean()에다가 메소드를 통해서 호출하여 메모리에 로드함
- ApplicationContext와 다른점
- 미리 로드되는게 아니고 필요할 때 호출하여 로드하기 때문에
lazy-loading
이 된다는 점
- 미리 로드되는게 아니고 필요할 때 호출하여 로드하기 때문에
- request –> web.xml –> DispatchServlet
-
요청 주소에 따른 적절한 컨트롤로 요청(handler Mapping)
- GET 요청(localhost:8080/post/1) –> 해당 주소 요청이 오면 적절한 컨트롤러의 함수를 찾아서 실행됨
-
응답
-
html파일을 응답할지 Data를 응답할지 결정해야 하는데 html파일을 응답하게 되면 ViewResolver가 관여하게 된다.
-
응답의 파일패턴을 만들어줌 ex) WEB-INF/views/xxx.jsp prefix, suffix
-
하지만 Data를 응답하게 되면 MessageConverter가 작동하게 되는데 메시지 컨버팅할 때 기본전략은 json이다.
-
참고
https://www.youtube.com/playlist?list=PL93mKxaRDidG_OIfRQ4nztPQ13y74lCYg 8 ~ 14강