728x90
HTML Form 데이터 전송
🔍 POST 전송 - 저장
- 클라이언트가 서버로 데이터를 전송할 때 웹 브라우저가 서버로 HTTP 메시지를 생성해서 전송한다.
서버에서 처리해야 하는 업무
🔍 웹 애플리케이션 서버 직접 구현
- 웹 애플리케이션 서버를 직접 구현하려면 비즈니스 로직을 실행 시키기 위해서 해줘야할 처리가 너무 많다.
🔍 서블릿을 지원하는 WAS 사용
- 서블릿은 비즈니스 로직 실행 전, 후 처리를 다 해준다.
- TCP/IP 연결 & 소켓 연결
- HTTP request 메시지 파싱
- HTTP response 메시지 작성
- TCP/IP 및 소켓 연결 종료
- Servlet을 지원하는 WAS 즉, 서블릿 컨테이너는 이러한 과정들을 전부 대신 수행해준다.
서블릿
- 서블릿이란, 클라이언트의 요청을 처리하고, 그 결과를 반환하는 Servlet 클래스의 구현 규칙을 지킨 자바 웹 프로그래밍 기술이다.
- 서블릿은 웹 프로그래밍에서 클라이언트 요청을 처리하고 처리 결과를 클라이언트에 전송하는 기술이다.
- 간단히 말해서, 자바를 사용하여 웹을 만들기 위해 필요한 기술이다.
- 클라이언트가 어떠한 요청을 하면 그에 대한 결과를 다시 전송해주어야 하는데, 이러한 역할을 하는 자바 프로그래밍이다.
예를 들어서 사용자가 로그인을 하려고 할 때, 사용자는 아이디와 비밀번호를 입력하고, 로그인 버튼을 누른다.
그 때 서버는 클라이언트의 아이디와 비밀번호를 확인하고, 다음 페이지를 띄어주어야 하는데, 이러한 역할을 수행하는 것이 바로 서블릿이다. 그래서 서블릿은 자바로 구현된 CGI라고 말한다.
💡 CGI
- CGI는 특별히 라이브러리나 도구를 의미하는 것이 아니고, 별도로 제작된 웹서버와 프로그램간의 교환 방식이다.
- CGI 방식은 어떤 프로그래밍 언어로도 구현이 가능하며, 별도로 만들어 놓은 프로그램에 HTML의 Get 또는 Post 방식으로 클라이언트의 데이터를 환경변수로 전달하고, 프로그램의 표준 출력 결과를 클라이언트에게 전송한다.
- 즉, 자바 애플리케이션 코딩을 하듯 웹 브라우저용 출력 화면을 만드는 방법이다.
💡 HTTP 프로토콜을 이용한 서버와 클라이언트의 통신 과정
- 클라이언트는 정보를 얻기 위해 서버로 HTTP 요청을 전송한다.
- 서버는 이를 해석하여 정적 자원에 대한 요청일 경우 자원을 반환해주고, 그렇지 않은 경우 CGI 프로그램을 실행시켜 해당 결과를 리턴해준다.
- 이 때 서버는 CGI 프로그램에게 요청을 전달해주고, 결과를 전달받기 위한 파이프라인을 연결한다.
- 그래서 CGI 프로그램은 입력에 대한 서비스를 수행하고, 결과를 클라이언트에게 전달하기 위해 결과 페이지를 해당하는 MIME 타입의 컨텐츠데이터를 웹 서버와 연결된 파이프라인에 출력하여 서버에 전달한다.
- 서버는 파이프라인을 통해 CGI 프로그램에서 출력한 결과 페이지의 데이터를 읽어, HTTP 응답 헤더를 생성하여 데이터를 함께 반환한다.
🔍 서블릿 특징
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) {
//애플리케이션 로직
}
}
- @WebServlet 애노테이션의 속성인 urlPatterns의 값을 "/hello" 로 설정을 했으므로 해당 URL이 호출되면 서블릿 코드가 실행된다. → service() 메서드가 호출이 된다.
- HttpServletRequest 객체는 HTTP 요청 정보를 편리하게 제공해준다.
- HttpServletResponse 객체는 HTTP 응답 정보를 편리하게 제공해준다.
- 그러므로 개발자는 HTTP 스펙을 매우 편리하게 사용할 수 있다.
- HTTP 프로토콜 서비스를 지원하는 javax.servlet.http.HttpServlet 클래스를 상속 받는다.
- HTML을 사용하여 요청에 응답한다.
- HTML 변경시 Servlet을 재 컴파일 해야한다.
- MVC 모델2 패턴 중 Controller에 해당한다.
💡 전체적인 그림
- 웹 브라우저가 localhost:8080/hello 사이트를 요청한다.
- WAS는 요청 메시지를 기반으로 HttpServletRequest, HttpServletResponse 객체를 생성한다.
- WAS는 요청 URL에 해당되는 서블릿 객체를 호출한다. (서블릿을 지원하는 WAS == 서블릿 컨테이너)
- 개발자는 HttpServletRequest 를 통해 요청 정보를 편리하게 사용한다.
- === 비즈니스 로직 수행 ===
- 개발자는 HttpServletResponse 를 통해 응답 정보를 작성한다.
- WAS는 HttpServletResponse를 통해 HTTP Response Message를 생성 후 Clinet에 전달한다.
💡 Servlet 동작방식
- 사용자(클라이언트)가 URL을 입력하면 HTTP Request가 Servlet Container로 전송한다.
- 요청을 받은 Servlet Container는 HttpServletRequest, HttpServletResponse 객체를 생성한다.
- web.xml을 기반으로 사용자가 요청한 URL이 어느 서블릿에 대한 요청인지 찾는다.
- WAS 에게 Servlet에 대한 정보를 줘야하는데 이 때 쓰이는 파일이 web.xml이다.
- servlet3.0 부터는 web.xml에서만 Servlet에 대한 정의하지 않고, 자바 소스 설정(java config)으로 설정 가능하다.
- 해당 서블릿에 service 메서드를 호출한 후 클라이언트의 GET, POST 여부에 따라 doGet() 메서드 또는 doPost() 메서드를 호출한다.
- doGet() 메서드 또는 doPost() 메서드는 동적 페이지를 생성한 후 HttpServletResponse 객체에 응답을 보낸다.
- 응답이 끝나면 HttpServletRequest, HttpServletResponse 두 객체를 소멸시킨다.
💡 서블릿 단점 → JSP가 탄생한 배경
- 서블릿은 프로그램 내에서 HTML 텍스트가 변경되었을 때도 java 코드가 다시 컴파일 되어야 한다.
- 그런 이유로 디자이너는 자바 코드를 잘 알아야한다.
- 유지보수가 어렵다.
서블릿 컨테이너
- 서블릿을 관리하기 위한 모든 작업을 수행한다. (생성 / 호출 / 관리)
- 서블릿을 지원하는 WAS 안에는 서블릿 컨테이너가 있다.
- 서블릿 컨테이너는 클라이언트의 요청을 받아주고 응답할 수 있도록 웹 서버와 소켓을 만들어 통신한다.
- 서블릿 컨테이너는 서블릿 객체인 helloServlet 클래스 인스턴스를 스스로 생성, 호출 및 생명 주기 관리를 한다.
- helloServlet 클래스 인스턴스는 위의 서블릿 특징의 자바 코드 참조할 것
- 개발자가 서버에 서블릿을 만들었다고 해서 스스로 작동하는 것이 아니고 서블릿을 관리해주는 것이 필요한데, 그러한 역할을 하는 것이 바로 서블릿 컨테이너다.
- 예를 들어, 서블릿은 어떤 역할을 수행하는 설명서라고 보면, 서블릿 컨테이너는 그 설명서를 보고 수행한다.
- 서블릿 컨테이너는 클라이언트의 요청(Request)을 받아주고 응답(Response)할 수 있게 웹 서버와 소켓으로 통신한다. 대표적으로 톰캣(Tomcat)이 있다.
- 톰캣은 실제로 웹 서버와 통신하여 JSP(자바 서버 페이지)와 서블릿이 작동하는 환경을 제공한다.
- 톰캣처럼 서블릿을 지원하는 WAS를 서블릿 컨테이너라고 한다.
💡 서블릿 컨테이너 역할
- 웹서버와의 통신 지원
- 서블릿 컨테이너는 서블릿과 웹서버가 손쉽게 통신할 수 있게 해준다.
- 일반적으로 우리는 소켓을 만들고 listen, accept 등을 해야하지만, 서블릿 컨테이너는 이러한 소켓 기능들을 API로 제공하여 복잡한 과정을 생략할 수 있게 한다.
- 그래서 개발자가 서블릿에 구현해야 할 비즈니스 로직에 대해서만 집중할 수 있게 해준다.
- 서블릿 생명 주기(Life Cycle) 관리
- 서블릿 컨테이너는 서블릿의 탄생과 죽음을 관리한다.
- 즉, 서블릿 객체 생성, 초기화, 호출, 종료하는 생명 주기를 관리한다.
- 또한 서블릿이 생명을 다 한 순간에 적절하게 GC(가비지 컬렉션)를 진행하여 편의를 제공한다.
- 서블릿 객체를 싱글톤으로 관리한다.
- 고객의 요청이 올 때 마다 계속 객체를 생성하는 것은 비효율이다.
- 최초 로딩 시점에 서블릿 객체를 미리 만들어두고 재활용한다.
- 모든 고객 요청은 동일한 서블릿 객체 인스턴스에 접근한다.
- 공유 변수 사용에 주의해야한다.
- 서블릿 컨테이너 종료시 함께 종료한다.
- 멀티 쓰레드 자원 및 관리
- 동시 요청을 위한 멀티 쓰레드 처리를 지원한다.
- 서블릿 컨테이너는 요청이 올 때 마다 새로운 자바 쓰레드를 하나 생성하는데, HTTP 서비스 메소드를 실행하고 나면, 쓰레드는 자동으로 죽게 된다.
- 원래는 쓰레드를 관리해야 하지만 서버가 다중 쓰레드를 생성 및 운영해주니 쓰레드의 안정성에 대해서 걱정하지 않아도 된다.
- 선언적인 보완 관리
- 서블릿 컨테아너를 사용하면 개발자는 보안에 관련된 내용을 서블릿 또는 자바 클래스에 구현하지 않아도 된다.
- 일반적으로 보완관리는 XML 배포 서술자에 기록하므로, 보안에 대해 수정할 일이 생겨도 자바 소스 코드를 수정하여 다시 컴파일 하지 않아도 보안관리가 가능하다.
🔍 HTTP 요청, 응답 흐름
💡 HTTP 요청시
- WAS는 Request, Response 객체를 새로 만들어서 서블릿 객체를 호출한다.
- 개발자는 Request 객체에서 HTTP 요청 정보를 편리하게 꺼내서 사용할 수 있다.
- 개발자는 Response 객체에서 HTTP 응답 정보를 편리하게 입력할 수 있다.
- WAS는 Response 객체에 담겨있는 내용으로 HTTP 응답 정보를 생성한다.
- 웹 애플리케이션 서버는 HTTP 응답 정보를 웹 브라우저로 보낸다.
- 웹 브라우저는 HTTP 데이터를 랜더링해서 홈페이지를 보여준다.
🔍 Servlet 생명 주기
- 클라이언트의 요청이 들어오면 컨테이너는 해당 서블릿이 메모리에 있는지 확인하고, 없을 경우 init() 메서드를 호출하여 적재한다.
- init() 메서드는 처음 한번만 실행되기 때문에(싱글톤이기 때문에), 서블릿의 쓰레드에서 공통적으로 사용해야할 것이 있다면 오버라이딩하여 구현하면 된다.
- 실행 중 서블릿이 변경될 경우, 기존 서블릿을 파괴하여 init() 메서드를 통해 새로운 내용을 다시 메모리에 적재한다.
- init() 메서드가 호출된 후 클라이언트의 요청에 따라서 service() 메서드를 통해 요청에 대한 응답으로 doGet()가 호출될지, doPost() 메서드가 호출될지 나눠진다.
- 이 때 서블릿 컨테이너가 클라이언트의 요청이 오면 가장 먼저 처리하는 과정으로 생성된 HttpServletRequest, HttpServletResponse에 의해 request와 response 객체가 제공된다.
- 컨테이너가 서블릿에 종료 요청을 하면 destroy() 메서드가 호출된다.
- 종료시 처리해야할 작업들은 destroy() 메서드를 오버라이딩하여 구현하면 된다.
JSP (Java Server Page)
- JSP란, 자바 코드가 들어가 있는 HTML 코드다.
- 서블릿은 자바 소스코드 속에 HTML 코드가 들어있는 구조인데, 반대로 JSP는 HTML 소스코드 속에 자바 소스코드가 들어있는 구조다.
- HTML 속 자바코드는 <%소스코드%> 또는 <%=소스코드=%> 형태로 들어간다.
- HTML 속 자바 코드는 웹 애플리케이션으로 보내는 것이 아니라 웹 서버에서 실행된다.
- 개발자가 소스코드를 수정할 경우에 디자인 부분을 제외하고 자바 코드만 수정하면 되기에 효율을 높여준다.
- 또한, 컴파일 같은 과정이 필요없이 JSP 페이지를 작성하여 웹 서버의 디렉토리에 추가만 하면 사용이 가능하다.
- 이렇게 작성된 HTML 코드는 브라우저로 전송되는 것이 아닌, 웹 서버 내에서 실행된다.
- 서블릿 규칙은 꽤나 복잡하기 때문에 JSP가 나오기 되었다.
- JSP는 WAS에 의하여 서블릿 클래스로 변환되어 사용된다.
🔍 JSP 동작 구조
- 웹 서버가 사용자로부터 서블릿에 대한 요청을 받으면 서블릿 컨테이너에 그 요청을 넘긴다.
- 요청을 받은 컨테이너는 HTTP Request와 HTTP Response 객체를 만들어, 이들을 통해 서블릿 객체의 doGet() 메서드 또는 doPost() 메서드를 호출한다.
- 만약 서블릿만 사용하여 사용자가 요청한 웹 페이지를 보여주려면 out 객체의 println 메서드를 사용하여 HTML 문서를 작성해야 하는데 이는 추가/수정을 어렵게 하고, 가독성을 떨어뜨리기 때문에 JSP를 사용하여 비즈니스 로직과 프레젠테이션 로직을 분리한다.
- 여기서 서블릿은 데이터 입력, 수정 등에 대한 제어를 JSP에게 넘겨서 프리젠테이션 로직을 수행한 후 컨테이너에게 Response를 전달한다.
- 이렇게 만들어진 결과물은 사용자가 해당 페이지를 요청하면 컴파일 되어 자바 파일을 통해 .class 파일이 만들어지고, 두 로직이 결합되어 클래스화 된다.
- 즉 out 객체의 println 메서드를 사용해서 구현해야하는 번거로움을 JSP가 대신 수행한다.
- 웹 브라우저가 웹 서버에게 JSP 페이지를 요청하면, 웹 서버는 JSP에 대한 요청을 웹 컨테이너(서블릿 컨테이너)로 넘긴다.
- 서블릿 컨테이너는 이를 Servlet 객체로 변환하고 요청에 대한 수행 결과를 웹 브라우저에게 응답으로 보낸다.
👀 참고자료
https://mangkyu.tistory.com/14
https://blog.naver.com/gprl1357/221812844248
https://server-engineer.tistory.com/827
728x90
'[ Spring ] > SpringMVC 1편' 카테고리의 다른 글
[Spring] 자바 웹 기술 역사 (0) | 2022.02.12 |
---|---|
[Spring] 서버 사이드 렌더링(SSR), 클라이언트 사이드 렌더링(CSR) (0) | 2022.02.11 |
[Spring] HTML, HTTP API (0) | 2022.02.11 |
[Spring] 멀티 쓰레드 (0) | 2022.02.11 |
[Spring] 웹 서버, 웹 애플리케이션 (0) | 2022.02.11 |