본문 바로가기
강의/웹 프로그래밍(풀스택)

부스트코스 웹 프로그래밍(풀스택) - 1. 웹 프로그래밍 기초 - 5-3-2 강의 정리

by 리드민 2022. 4. 16.
반응형

[1] 강의

웹 프로그래밍(풀스택)

5. Servlet - BE

3) Servlet 라이프 사이클-2

 

[2] 개념 정리

HttpServlet의 3가지 메소드

- init :  딱 한 번만 호출됩니다. 서블릿 컨테이너가 서블릿 객체를 생성한 후 호출합니다. 서블릿이 작업하는데 필요한 자원을 준비시키는 코드를 넣습니다.
- service : 클라이언테의 HTTP 메소드(GET, POST 등)를 참조하여 doGet()을 호출할지, doPost()를 호출할지 판단합니다.

- destory : 딱 한 번만 호출됩니다. 웹 어플리케이션의 실행이 멈출 때, 서블릿이 사용한 자원을 초기화시킬 수 있도록 이 메서드를 호출합니다. 서블릿이 사용한 자원을 초기화 시키는 코드를 넣습니다.

 

HttpServlet의 3가지 메소드

- init :  딱 한 번만 호출됩니다. 서블릿 컨테이너가 서블릿 객체를 생성한 후 호출합니다. 서블릿이 작업하는데 필요한 자원을 준비시키는 코드를 넣습니다.
- service : 클라이언테의 HTTP 메소드(GET, POST 등)를 참조하여 doGet()을 호출할지, doPost()를 호출할지 판단합니다.

- destory : 딱 한 번만 호출됩니다. 웹 어플리케이션의 실행이 멈출 때, 서블릿이 사용한 자원을 초기화시킬 수 있도록 이 메서드를 호출합니다. 서블릿이 사용한 자원을 초기화 시키는 코드를 넣습니다.

 

Servlet 생명주기
WAS는 서블릿 요청을 받으면 해당 서블릿이 메모리에 있는지 확인합니다.
 if (메모리에 없음) {
 - 해당 서블릿 클래스를 메모리에 올림
 - init() 메소드를 실행
}
 - service()메소드를 실행
was가 종료되거나, 웹 어플리케이션이 새롭게 갱신될 경우 destroy() 메소드가 실행됩니다.

 

[3] 강의 정리

  이번 강의에서는 서블릿 생명주기에 대해서 다시 한번 정리해보도록 하겠다. 지난 강의에서 LifecycleServlet이라는 클래스를 하나 만들어서 실습을 진행해봤다. HttpServlet의 세 가지 메서드를 오버라이딩했다. 그리고 처음 요청했을 때 어떤 메서드들이 실행되는지 두 번째는 또 어떤 메서드가 실행되는지 애플리케이션 자체가 변경됐을 때 이럴 때는 어떤 메서드가 실행되는지 이런 부분들을 확인해 봤다. 그림을 보면서 다시 정리를 해보면 앞에서 말했던 것처럼 서블릿이 처음 호출되면 init()이라는 메서드가 호출이 된다. 그리고 나서 service()라는 메서드가 호출이 된다. destroy()라는 메서드는 항상 호출이 되는 건 아니고. 웹 애플리케이션이 갱신되거나 WAS가 종료될 때 호출이 되었다. 다시 그림을 보면서 한번 더 정리를 해보자면 WAS는 서블릿의 요청을 받으면 일단 해당 서블릿이 메모리에 있는지 없는지를 확인을 하게 된다. 만약에 메모리에 없다면 해당 서블릿 크래스를 메모리에 올리는 작업을 하게 된다. 이 메모리에 올리는 작업은 객체가 생성되는 작업이다. 그랬기 때문에 처음 요청을 했을 때 생성자의 메시지 부분이 출력됐었던거 여러분이 기억할 거 같고요. 그런 다음 init()이라는 메서드가 호출됐었다. 그리고 service()라는 메서드가 또 호출이 돼서 실행이 됐었다.

  두 번째 요청이 들어왔을 때는 이 생성자라던가 init()이라는 메서드는 호출이 되지 않고 service()라는 메서드만 계속 실행이 되고 있었던 거 기억할 거다. 실제 여러분들 여기서 기억해야 할 것은 요청이 들어왔을 때 응답해야 되는 모든 내용은 service()라는 메서드에 구현해야겠다. 이정도로 기억을 하면 좋을 거 같다. WAS가 종료되거나 웹 애플리케이션이 새롭게 갱신될 경우만 destroy()라는 메서드가 실행이 된다. 이렇게 기억하면 될 거 같다. 그런데 이쯤 들으면서 지금까지 강의를 열심히 들었던 사람은 궁금한 점이 하나 생겼을 거다. 분명히 전에 HelloServlet을 만들었을 때 이런 service()라는 메서드는 본적이 없는데라는 생각이 드는가? 들었으면 좋을 거 같다. HelloServlet에서는 doGet()이라는 메서드만 호출했었다. 그런데 분명히 doGet()이라는 메서드가 잘 실행이 됐던 과정들을 살펴봤었다. 분명히 WASinit()이라는 메서드를 호출하고 다음은 service()라는 메서드를 호출하는 예만 수행했는데 doGet()이라는 메서드는 어떻게 실행됐을까? 분명히 WASinit()이라는 메서드를 호출하고 다음은 service()라는 메서드를 호출하는 예만 수행하는데 doGet()이라는 메서드는 어떻게 실행됐을까? service()라는 메서드가 약간 특이하게 동작이 된다. service()라는 메서드는 실제 HttpServlet의 이 service()라는 메서드가 이미 구현이 되어있는 상태이다.

  상속 기억나나요? 내가 만든 클래스가 service()라는 메서드를 갖고 있지 않다면 누구의 service()가 실행될까? 나의 부모 클래스의 service()라는 메서드가 실행되겠지. 그러니까 우리가 HelloServlet을 만들었을 때는 doGet()이라는 메서드만 오버라이드 했고 이 service()라는 메서드는 오버라이드 하지 않았었기 때문에 그런건데 WAS는 매번 service()만 호출한다. 그러니까 내가 service()를 오버라이드 하지 않았다면 이 service()는 나의 부모인, 서블릿의 부모인 HttpServletservice() 메서드가 실행이 됐겠지. 그러면 HttpServletservice() 메서드는 어떻게 구현이 되어 있는지를 알면 된다. HttpServletservice() 메서드는 템블릿 메서드 패턴으로 구현이 되어 있는데. 클라이언트 요청이 GET인 경우에는 자신이 가지고 있는 doGet()이라는 메서드를 호출한다. 클라어언트 요청이 POST 일 경우에는 자신이 가지고 있는 doPost()라는 메서드를 호출한다. service()라는 메서드가 그렇게 동작하고 있었기 때문에 HelloServlet에서 service() 메서드를 오버라이드 하지 않고 doGet() 메서드만 오버라이드 했지만 알아서 doGet() 메서드가 호출되면서 그 안에 구현해두었던 HelloServlet 이런 것을 응답 결과로 보내주는 이런 부분들을 여러분들이 확인하실 수 있으셨을 거다. 만약에 여러분이 doPost()라는 메서드를 오버라이드 했다면 POST 방식으로 요청이 들어오게 되면 그 부분이 실행되게 될 거다. 그러면 우리 또 이런 부분들을 조금 실습을 해보면 좋을 거 같다. 그래서 어떤 부분을 실습해볼 거냐면 기존에 LifecycleServlet에서 service()라는 메서드를 오버라이드 했었는데 이 service() 메서드를 주석으로 바꾸어 주고.

  doGet()이나 doPost() 메서드를 오버라이드 해볼 거다. 그랬을 때 각각 어떻게 동작하는지 알아보도록 하겠다. 전에 구현해놨었던 Lifecycle Servlet을 열어보고. service()라는 메서드는 주석으로 바꿔볼 거다. 그리고 doGet()이나 doPost()를 오버라이드 하면 된다. 메서드 오버라이드 할 때는 이렇게 Override/Implement Methods에서 선택을 해주면 되고. 여기 보면 doGet(), doPost() 이런 부분들이 존재하고 있는 걸 볼 수 있을 거다. 초기에는 메서드 요청이 GET이나 POST 이런 방식만 존재했었다면 현재는 요청 자체가 DELETE로 들어온다던가 PUT으로 들어온다던가 이런 식으로 여러 가지 방법으로 들어올 수도 있다. 이런 부분들도 활용해 볼 수 있다. 일단 현재는 doGet()doPost() 메서드만 오버라이드 해서 테스트를 해볼 거다. 코드를 직접 입력하기는 시간이 너무 많이 걸린다. 나는 코드를 미리 마련을 해봤다. 일단은 doGet()이라는 메서드 내에서는 이런 HTML. 지금 out.println() 안에 들어있는 거만 응답으로 들어간다고 했지? 이런 HTML을 응답을 보내줄 거다. doPost()에서는 요청 결과에서 Parameter 중에 name으로 들어있는 값을 꺼내서 이 name을 응답 결과에 hello, 입력받은 name 이렇게 응답을 하도록 두 개의 코드를 만들어 봤따. 저장하고 한번 실행해보도록 하자.

  이렇게 이제 실행을 해보면 HTML 태그가 그대로 넘어가서 좀 더 예쁜 페이지면 좋겠지만 예쁜 페이지로 만들기 위해서는 태그가 더 많이 들어가니. 지금 보시면 오른쪽 버튼을 클릭해가지고 소스 보기 한번 해보자. 제가 doGet() 메서드 안에 out.println() 에다가 문자열로 넣어줬던 코드들이다. 그 값이 그대로 응답 결과롤 넘어가 있었던 것을 여러분들이 확인할 수 있을 거다. HTML 코드가 실제 화면에 나오는 것은 이 부분이다. input 상자로 typetext고 이름은 name인 거. 이렇게 넣어준다. 지금 이런 부분이고. 그 다음에 submit이라는 버튼 이 버튼의 값은 ok라고 여기에 들어있다. 이렇게 넣어준다, 지금 이건데 이거보다 조금 더 중요한 건 뭐냐면 form이라는 태그다. form 태그 안에 method라는 값과 action이라는 값이 있는데 이건 각각 무슨 의미냐면 submit이라는 버튼이 눌렸을 때 이 주소로 요청해줘요 하는 거다. 그런데 이때 요청이 들어갈 때 메서드는 post라는 값으로 넣어주세요 이런 의미라고 생각하면 된다. 무슨 말인지 이해되는가? 아까 요청했을 때 LifecycleServlet이 요청이 들어왔다.

  URL에서 직접 요청했을 때에는 메서드 값이 GET이라는 값으로 넘어간다. 아까 이 service()라는 메서드 기억나나요? 클라이언트 요청이 GET일 경우에는 doGet()으로 호출하고 클라이언트 요청이 POST일 경우에는 doPost()로 호출한다. 라고 이야기 했었다. 그 부분을 조금 더 기억하면 될 거 같다. 그래서 URL에서 직접 넘어갔을 때는 GET이라는 요청이 들어왔을 거기 때문에 HttpServlet이 가진 service() 메서드는 doGet()이라는 메서드를 호출했을 거다. 그래서 doGet()이 실행된 거다. doGet()에 있는 내용이 응답 결과로 넘어갔기 때문에 이런 내용이 응답으로 보였을 거다. 그럼 두 번째 요청해서 ok하게 되면 아까 말씀드렸던 것처럼 이 submitok. 눌렸을 때 어디로, URL로 요청해줘요 한다. 사실 똑같다. 메서드만 빼고. 그래서 이 요청이 들어갔을 때는 누가 실행될 거냐면 doGet() 메서드가 실행되는 게 아니라 doPost()라는 메서드가 실행될 거다. doPost()라는 메서드를 보면 ContentType을 지정했다. 응답 결과를 넣어줄 통로를 하나 얻었다. 그런 다음에 이 request 객체로부터 뭘 얻어내려면 Parametername으로 지정된 애. 그것의 값을 꺼내서 String 변수 name에 넣어준다. 지금 이런 부분이 수행된다. request는 요청 정보를 추상화해서 갖고 있는 객체라고 했었다. 이때 요청이 들어왔을 때 정보다.

  이때 이 input 상자에 있는 이 name. 값이 name으로 되어 있다. 이 값에 따라서 getParameter() 했을 때 나와있는 값이 달라지는 거다. 이 값이 name인 애. 이것의 value를 찾아서 name인 애. 이것의 value를 찾아서 어디다가, String name에다가 넣어주고, 그리고 응답 결과를 어떻게 할 거냐면 hello, 그때 받아온 name을 넣어서 응답 결과를 만들어 주는 거다. 정적인 페이지, 동적인 페이지 이야기를 여러 번 했었다. 현재 이거 잘 생각해봐라. 우리가 form에서 요청할 때 값을 뭐라고 넣느냐에 따라서 페이지가 달라지는 거다. 내가 kang이라는 값을 넣어서 요청을 하게 되면 응답 결과로는 hello kang이라는 값이 응답이 되는 것을 볼 수 있다. 그렇다면 이번에는 kang이 아니라 hahaha 이렇게 요청해볼까? 그랬더니 응답 결과는 hello hahaha 이렇게 응답 결과가 만들어지는 거 볼 수 있나? 계속 실행되는 부분은 이 똑같은 코드가 실행이 됐을 텐데 프로그램이 동작하면서 응답 결과를 만들어내기 때문에 응답 결과가 매번 바뀌겠지.

  우리 이런 것을 동적인 페이지라고 한다. 그래서 이렇게 실행이 되는 것을 볼 수 있었을 거다. 다시 정리해보면 해당 서블릿에 URL 주소를 직접 입력하거나 링크를 클릭하는 것은 GET 방식으로 서버에서 요청을 보내게 되는 거다. 이랬을 경우에는 service() 메서드가 호출이 되면서 해당 service() 메서드는 자신의 doGet() 메서드를 호출한다. 그런데 요청할 때 메서드가 GET이 아니라 우리 아까 form에서 요청했을 때처럼 여기처럼 이제 메서드가 POST 이런 방식으로 들어갔더니 메서드가 post 값이라는 거를 전달하게 될 거다. 그러면 실제 service() 메서드는 메서드가 post로 들어왔기 때문에 doPost()를 호출해서 doPost() 메서드 안에 있는 내용이 출력이 되고 있는 것을 볼 수 있다. 이렇게 GET 방식이냐 POST 방식이냐에 따라서 같은 URL 매핑 주소지만 다른 메서드가 호출이 되고 있는 것을 확인할 수 있다. 이렇게 서블릿의 라이프 사이클과 관련된 메서드들에 대해서 알아보았다.

 

[4] 코드 정리

package examples;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
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("/LifecycleServlet")
public class LifecycleServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
 
    public LifecycleServlet() {
        System.out.println("LifecycleServlet 생성!!");
    }

	public void init(ServletConfig config) throws ServletException {
		System.out.println("init test 호출!!");
	}

	
	public void destroy() {
		System.out.println("destroy 호출!!");
	}

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head><title>form</title></head>");
		out.println("<body>");
		out.println("<form method='post' action='/firstweb/LifecycleServlet'>");
		out.println("name : <input type='text' name='name'><br>");
		out.println("<input type='submit' value='ok'><br>");                                                 
		out.println("</form>");
		out.println("</body>");
		out.println("</html>");
		out.close();
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		String name = request.getParameter("name");
		out.println("<h1> hello " + name + "</h1>");
		out.close();
	}

//	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//		System.out.println("service 호출!!");
//	}
//	
	

}

 

반응형