Servlet 이 왜 나왔는가? 🤔
1. 정적데이터만 전달하는 Web Server
초창기 웹 어플리케이션은 단순히 html 파일과 같은 정적 데이터만 제공할 수 있었습니다.
즉, 그림과 같이 모든 사용자는 같은 화면만 제공받을 수 있었습니다.
정적 컨텐츠만 제공하는 웹서버는 사용자들에게 다양한 화면을 제공하기 위해 동적 컨텐츠의 필요성을 느끼게 됩니다.
🚨문제점🚨
- 사용자(요청)에 따라 다른처리를 해줄 수 없다.
- 동적인 처리를 해주는 웹 어플리케이션이 없다.
2. 동적 데이터를 처리하는 CGI(Common Gateway Interface)
이러한 문제 해결을 위해 CGI(Common Gateway Interface)라는 동적인 데이터를 제공하기 위한 규약이 나오게 됩니다.
1) Client로 부터 요청이 들어오면
2) Server는 CGI를 구현한 구현체에게 동적인 데이터를 제공해달라고 요청합니다.
3) CGI 수행하면 Client 는 동적인 데이터를 제공받을 수 있습니다.
동적인 데이터를 제공 받을 수 있게 되었지만 CGI 는 문제점이 있습니다.
🚨문제점🚨
- 1. 모든 사용자 요청마다 프로세스를 사용하여 처리한다.
- 프로세스는 메모리에 적재된 실행중인 프로그램 인스턴스이므로 무겁고 더많은 자원을 가지고 있어 구조적인 문제가 발생합니다.
- 같은 요청이라도 동일 CGI를 생성한다.
- 매번 객체를 생성하고 종료하는 작업은 필요없는 서버 리소스를 불필요하게 낭비하는 구조를 가지고 있습니다.
3) CGI를 보완한 Servlet
이러한 문제를 해결하기 위하여 Servlet이 등장하게 된다.
Web Server는 정적 데이터 처리
Web Application Server는 동적 데이터 처리
WebContainer 요청(Request)이 들어오면 Thread를 생성하고, Servlet을 실행시킨다.
Servlet Interface에 따라 Servlet을 관리한다.
💡문제 해결💡
- Process를 Thread로, 동일 구현체 생성을 Singleton 패턴을 적용한다.
Servlet Container 란,
: 서블릿들의 생성, 실행, 파괴를 담당한다.
: 서블릿들을 위한 상자(Container)입니다.
서버에 만들어진 서블릿이 스스로 작동하는 것이 아니라, 서블릿을 관리 해주는 것이 필요한데, 이러한 역할을 하는 것이 바로 서블릿 컨테이너 입니다.
즉, 서블릿을 '요구사항 명세서'라고 표현한다면, 서블릿 컨테이너는 그 명세서를 보고 개발하는 '개발자'입니다.
서블릿 컨테이너는 Clinet의 Request를 받아주고 Response할 수 있게, 웹 서버와 소켓을 만들어 통신합니다.
대표적으로 무료 서비스인 Tomcat(톰캣)이 있습니다.
톰캣은 웹 서버와 소켓을 만들어 통신하며 JSP(java server page)와 Servlet이 작동할 수 있는 환경을 제공합니다.
서블릿 컨테이너와 서블릿이 호출되는 과정
1. Servlet Request / Servlet Responser 객체 생성
2. 설정 파일을 참고하여 매핑할 Servlet을 확인
3. 해당 서블릿 인스턴스 존재 유무를 확인하여 없으면 생성 (init())
4. Servlet Container에 스레드를 생성하고, res, req를 인자로 service를 실행
5. 응답을 처리한 뒤 Request, Response 객체를 소멸시키고 끝이 납니다.
서블릿은 컨테이너에서 싱글톤으로 관리되기 때문에 요청 이후에 소멸되지 않고, 다음에 같은 요청이 들어왔을 때 재사용됩니다.
서블릿을 생성하고 필요한 순간에 호출하고 적절한 시점에 소멸시키는 역할을 담당하는 것입니다.
🚨Servlet 문제점🚨
Servlet 은 각 요청마다 1:1로 매핑되는 구조를 가지고 있어 Servlet 마다 공통되어 실행되는 로직이 매번 반복되서 생성되고 실행되는 문제점이 발생합니다.
프론트 컨트롤러 패턴(Front Controller Pattern)
프론트 컨트롤러 패턴은 앞단에서 서블릿을 만들어 공통 로직을 처리하도록 하는 패턴입니다.
Spring MVC도 프론트 컨트롤러 패턴을 따르고 모든 요청을 받는 전면 컨트롤러를 Dispatcher Servlet이라고 부릅니다.
즉, 서블릿을 하나만 두고 모든 요청을 다 받을 수 있도록 하는 것입니다.
프론트 컨트롤러 패턴 이전에는 요청마다 서블릿을 정의하고 요청을 수행할 때마다 매번 스레드를 생성했다면, 이제는 하나의 서블릿만 정의하고 이 서블릿이 모든 요청을 수행하게 됩니다.
Front Controller 가 하는 일?
1. 클라이언트 - 서버 연결
2. 각 요청에 맞는 컨트롤러를 매핑하여 정보를 보관
3. 요청이 들어오면 매핑 정보를 찾아 해당 컨트롤러 호출
4. 전달할 결과를 생성
5. 결과를 사용자에게 반환
Spring MVC 구조
실제로 Spring MVC의 구조는 위와 같습니다.
- 핸들러 조회
- 핸들러 매핑을 통해 요청 URL에 매핑된 핸들러(컨트롤러)를 조회한다.
- 핸들러 어댑터 조회
- 핸들러를 실행할 수 있는 핸들러 어댑터를 조회한다.
- 핸들러 어댑터 실행
- 조회한 핸들러(컨트롤러)를 인자로 핸들러 어댑터에 넘겨서 핸들러를 실행시킨다.
- ModelAndView 반환
- 핸들러(컨트롤러)가 로직을 수행하고 반환하는 정보로 ModelAndView로 변환해서 반환한다.
- viewResolver 호출
- 적절한 viewResolver를 찾고 해당 viewResolver를 호출한다.
- View 반환
- viewResolver는 뷰의 논리 이름을 물리 이름으로 바꾸고, 랜더링 역할을 담당하는 뷰 객체를 반환한다.
- 뷰 랜더링
- 뷰를 통해서 뷰를 랜더링한다.
프론트 컨트롤러 패턴 적용 전보다 상당히 복잡한 구조를 가지게 되는데 실질적으로 개발자가 신경써야할 부분은 핸들러(컨트롤러) 입니다.
컨트롤러 외 다른 부분은 Dispatcher Servlet이 스프링 컨테이너로부터 주입을 받아서 사용하고 동작하게 됩니다.
스프링 컨테이너는 프로그램이 동작하는 동안 사용되는 자바 객체들을 프레임워크가 대신 보관하고 관리하는 역할을 합니다.
서블릿 웹 애플리케이션 컨텍스트는 웹 요청 처리 관련 객체들이 담겨있고, 루트 웹 애플리케이션 컨텍스트 안에는 웹 요청처리와 관련된 빈 외의 나머지 컴포넌트들(서비스, 레포지토리 관렬 객체들)이 관리 됩니다.
따라서, 스프링 컨테이너는 개발에 필요한 부분이나 디스패치 서블릿이 요청을 처리할 때, 필요한 부분을 알아서 주입해주는 것입니다.
결국, Spring Web MVC 가 가져다 주는 이점을 사용하면서 비즈니스 로직에 집중할 수 있게 된다. !
참고
https://www.youtube.com/watch?v=calGCwG_B4Y&t=44s
'🎨 Programming > Spring' 카테고리의 다른 글
롬복(Lombok) 설치 및 적용 (0) | 2020.11.04 |
---|---|
[Spring] 개념 및 Spring BooT (0) | 2020.11.03 |