▸JSP & Servlet/기본 문법

서블릿(Servlet) 생성과 생명주기

코데방 2020. 2. 13.
728x90

[ 서블릿 ]

  • HttpServlet : Servlet 인터페이스를 구현한 GenericServlet 추상 클래스를 상속받은 클래스
  • Servlet : HttpServlet 클래스를 상속받은 자바 클래스
  • doGet(), doPost() 메소드를 필수적으로 오버라이딩 해야함

[ doGet() 메소드 ]

  • GET 방식으로 요청이 들어올 경우 처리할 로직 작성

* GET 방식

  • URL 값으로 정보가 전송되는 방식 (URL의 끝에 요청 파라미터(쿼리스트링)을 실어서 보냄)
  • URL 값에 요청하는 정보가 노출되기 때문에 보안에 약함
  • 전송하는 내용의 길이 제한이 있음
  • 웹브라우저의 주소창을 이용해 servlet을 요청한 경우
  • HTML 코드 내 form 태그의 method 속성이 get일 경우

doGet() 메소드는 GET 방식으로 온 요청을 수행하는 로직입니다. GET 방식은 URL에 직접 파라미터를 넣어 전달하기 때문에 개인정보 등의 민감한 정보는 넣지 않고, 캐싱을 사용해 속도를 높이거나 즐겨찾기를 하기 좋게 하기 위해 사용되는 경우가 많습니다. 캐싱은 정적 컨텐츠를 요청한 뒤 요청 내용을 저장해놨다가 재요청이 들어오면 서버에 요청을 다시 보내지 않고 저장된 데이터를 활용하는 방식입니다. 즐겨찾기의 경우, 검색할 내용을 담은 쿼리스트링을 URL에 직접 저장해서 호출함으로써 다시 처음부터 검색하지 않아도 되는 편리함이 생깁니다. 네이버에서 검색해보면 URL에 쿼리 스트링이 붙어있어서 즐겨찾기의 URI주소(URL + 쿼리스트링 주소) 자체가 서버의 페이지에 검색할 내용을 요청하는 주소가 됩니다.

 

 

 

 

[ doPost() 메소드 ]

  • POST 방식으로 요청이 들어올 경우 처리할 로직 작성

* POST 방식

  • 요청 데이터를 HTTP 메세지의 Body에 담아 전송되는 방식
  • URL을 통해 노출되지 않아 상대적으로 보안에 강함 (다만 툴을 사용해 볼 수 있음)
  • 길이에 제한 없이 내용을 서버로 전송할 수 있음
  • HTML 코드의 Form 태그의 method 속성이 post일 경우

doPost() 메소드는 POST 방식으로 들어온 요청을 처리하는 로직입니다. GET방식과는 달리 HTTP 통신의 Body 안에 요청 내용을 담아 전송하기 때문에 URL을 통한 직접적인 노출이 없고, 전송 길이에 제한이 없는 장점이 있습니다. 물론 이런저런 툴을 이용하면 전송되는 내용을 까볼 수 있기 때문에 패스워드와 같은 민감한 정보들은 암호화를 해서 전송해야 합니다. 요즘 대부분의 사이트가 http(80) 대신 https(443, SSL 적용)를 사용하는 이유도 전송되는 데이터를 암호화해줄 수 있기 때문입니다.

 

 


 

 

GET방식과 POST 방식은 상황에 맞게 적절히 결정해서 요청 내용을 서블릿 컨트롤러로 전달해주게 됩니다. 백엔드단에서는 요청 내용을 받아 로직을 수행해주면 됩니다. 따로 처리해줘도 되고 아래와 같이 한 메소드로 모두 전달해서 같은 로직을 수행할 수도 있습니다.

 

package hsweb;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/HsWeb")
public class HsWeb extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// GET으로 요청와도 doAction 실행
		doAction(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		// POST로 요청와도 doAction 실행
		doAction(request, response);
	}
	
	public void doAction(HttpServletRequest request, HttpServletResponse response) { 
		
		// 로직 전개
	}
}

 


 

[ 서블릿의 라이프사이클 ]

 

서블릿은 처음 호출돼서 컴파일된 뒤 메모리에 상주하게 되면 그 이후부터 해당 객체를 계속 재활용합니다. 따라서 객체가 생성되는 순간부터 자원이 해제되는 순간까지가 서블릿의 라이프사이클입니다. 자원의 해제는 서블릿이 수정 되거나 컨테이너 또는 서버를 재가동할 때 발생합니다. 서블릿의 라이프사이클을 잘 이해하고 있으면 비효율적인 코드 중복을 피할 수 있습니다. 

 

서블릿의 라이프사이클이 진행되는 과정은 아래와 같습니다.

 

 

 

1. 서블릿 객체의 생성

 

먼저 서블릿이 최초에 호출되면 톰캣에서 서블릿 파일(.java)을 불러와 컴파일한 후 메모리에 로드시킵니다. 톰캣은 서블릿 파일이 변경되지 않는 이상 서버가 종료될 때까지 계속해서 해당 객체를 재활용합니다. jsp파일이나 서블릿 파일이 수정되면 서블릿 자원을 해제 시킨 뒤 새로 객체를 생성해서 메모리에 로드하게 됩니다.

 

 

2. 선처리 작업 수행 (객체 생성 시 최초 1회 수행)

 

서블릿에서 메소드를 임의로 작성하고 @PostConstruct 어노테이션을 부여하면 가장 먼저 해당 메소드를 실행합니다. 서블릿 객체가 생성될 때 먼저 처리하고 싶은 로직이 있다면 만들어줍니다. 다음 과정인 init() 메소드로 실행해줘도 되지만 성격이 다른 로직일 경우 별도로 분리해서 작성할 수 있습니다.

	@PostConstruct
	protected void postConstruct() {

		System.out.println("선처리 작업 메소드");
	}

 

 

3. init() 메소드 실행 (객체 생성 시 최초 1회 수행)

 

서블릿에서 기본 상속받는 HttpServlet 클래스의 부모인 GenericServlet 클래스에서 정의하고 있는 메소드입니다. 서블릿 객체 생성 시 초기화 작업을 수행해주는 역할을 합니다. 톰캣 서버의 환경설정 파일인 web.xml 파일의 내용을 불러와 ServletConfig 객체로 만들어 놓습니다. 추후에 이 정보를 불러와서 여러 작업을 진행할 수 있습니다.

 

아래와 같은 오버로딩 구조로 되어 있고 톰캣에서 먼저 ServletConfig 객체를 파라미터로 넣어 실행시키기 때문에 init()메소드를 오버라이딩하지 않으면 아무것도 실행시키지 않습니다. 추가로 필요한 작업이 있다면 서블릿에서 init() 메소드를 오버라이딩 해주면 됩니다.

 

@Override
    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }
 
    public void init() throws ServletException {
    }
	@Override
	public void init() throws ServletException {

		System.out.println("init 메소드 오버라이딩, 최초 1회 실행");
	}

 

 

4. Service() 메소드 실행 (자원 해제 전까지 요청이 올 때마다 반복 실행)

   - 요청 방식에 따라 doGet() 메소드 또는 doPost() 메소드 실행

 

클라이언트가 서블릿에 요청을 보내면, 톰캣의 서블릿 컨테이너는 요청 내용에 대한 객체(request)와 다시 응답을 보낼 수 있는 객체(response)를 가지고 스레드풀의 스레드를 하나 써서 service() 메소드를 실행합니다. service() 메소드는 요청 내용을 분석해서 doGet()메소드 또는 doPost() 메소드를 실행해줍니다. 위에서 보았듯이 우리는 각각의 메소드를 따로 만들어주거나 또는 별도 메소드를 만들어 실행시켜주는 로직을 짭니다.

 

 

5.  destroy() 메소드 실행 (자원 해제 시 1회 실행)

 

톰캣의 서블릿 컨테이너가 서블릿을 종료시킬 때 호출하는 메소드입니다. 서블릿을 수정하면 컨테이너가 다시 서블릿을 로드 시키는데, 이 때 기존 메모리에 올라와있던 서블릿을 종료시킵니다. 또는 서버가 정상적으로 종료될 때도 실행됩니다. 서버나 컨테이너 자체가 비정상 종료될 경우 실행되지 않을 수 있습니다. destroy() 메소드도 오버라이딩해서 로직을 추가할 수 있습니다.

@Override
	public void destroy() {
	
		System.out.println("destroy 메소드 오버라이딩, 마지막 1회 실행");
	}

 

 

6. 후처리 작업 수행 (객체 삭제 시 마지막 1회 수행)

 

선처리 작업과 마찬가지로 @PreDestroy 어노테이션을 적용하면 destroy() 메소드 다음 마지막으로 해당 메소드를 실행시켜 줍니다. 

	@Override
	public void destroy() {
	
		System.out.println("destroy 메소드 오버라이딩, 마지막 1회 실행");
	}
728x90

댓글

💲 추천 글