서블릿과 JSP

BackEnd

1. 서블릿과 컨트롤러의 비교 

 

 

Jsp와 서블릿은 사실 거의 같은 것이라고 할 수 있다서블릿이 발전된게 Spring이다

 

DispatcherServlet이 서블릿이다

 

스프링도 이 서블릿을 이용해서 동작한다

 

너무 깊게 알 필요는 없지만 그래도 기본적인 것을 알고 있어야한다

 

더 중요한 것은 스프링이기 때문이다

 

가벼운 마음으로 기본기만 훑고 넘어가자

 

  우선 위 그림을 보면 

 

@WebServlet이라고 어노테이션이 되어있는데

우리가 흔히 알고있는 Controller와 RequestMapping이 합쳐진 것이 WebServlet이다.

 

그리고 extends로 HttpServlet을 상속을 받아야한다

 

하지만 옆에 박스에 적힌 코드를 보면 @Controller는 상속을 받지 않는다

 

자바는 단일 상속이기 때문이다

 

그러므로 가능하면 상속을 받지 않는게 좋다 그래서 컨트롤러에서는 그런점이 개선이 되어서 상속을 받지 않는 것이다

 

서블릿에서는 Service메서드가 항상 고정이다 request, response는 항상 들어간다

 

그리고 하단에 throws IOException은 밑에서 PrintWriter를 받아올 때 발생할 수 있기 때문에 적어준 것이다

하지만 만약 밑에서 출력을 하지 않는다면 필요없다 별로 중요하지 않다 하지만 출력을 한다면 적어주는 것이 맞다

 

컨트롤러에서는 상속을 받지 않고 어노테이션도 나눠서 Controllet, RequestMapping 따로 쓰고 있으며

매개변수 또한 고정이 아니라 필요에 따라 필요한 것만 적어줄 수 있다

 

서블릿은 클래스에 맵핑을 한다 URL맵핑을 클래스 단위로 하기때문에 클래스를 여러개 만들어야한다

그 말은 즉 맵핑1개=클래스1개 이런식으로 만들어야한다

 

반면에 컨트롤러는 메서드에다가 맵핑을 하기 때문에 하나의 클래스안에 새로운 메서드를 만들기만 하면 되는 장점이 있다

 

서블릿과 아주 유사하지만 서블릿보다 발전된 것이 컨트롤러이다

 

 

2. 서블릿의 생명주기

 

 

서블릿은 기본적으로 3개의 메서드가 있다

 

init, service, destroy 총 3개이다

 

init메서드는 서블릿이 생성될 때 초기화를 위해서 쓰이는 것

 

service메서드는 실제 작업을 처리하는 것 

 

destroy는 서블릿이 메모리에서 제거 될 때 호출되는 메서드이다

 

이 3개의 메서드는 우리가 직접 호출하지 않고 Servlet Container라는 녀석이 자동으로 알아서 호출을 한다

그러므로 우리는 메서드가 호출될 때 이 메서드의 내용만 채워주면 된다

 

이제 이 HelloServelt이라는 것을 직접 만들어보자

 

우선 클래스를 하나 만드는데

 

해당 위치에 HelloServlet이라는 클래스를 만들어주고

 

 

이렇게 만들어졌다면 HttpServlet을 상속받아야한다

 

package com.fastcampus.ch2;

import javax.servlet.http.HttpServlet;

public class HelloServlet extends HttpServlet {

}

 

이렇게 extends를 해줬다면 마우스 우클릭을 해주자 (모든 동작은 인텔리제이로 진행되었습니다)

 

그러면 Generate라는 것이 있다 그걸 클릭해보면

 

그러면 여러가지 선택지가 나오게 되는데 내가 필요한 것은 Override Methods이다 클릭해주자

 

엄청나게 많은 것들이 나오게 되는데 여기서 필요한 것은 init, destroy, service 3가지를 override받아야한다

 

여기있는 밑에서 두번째 서비스 클릭

바로 밑에 destroy 클릭 

 

마지막으로 밑에 init클릭 해주자

 

모든 클릭을 할 때 윈도우는 컨트롤 누른상태로 클릭 맥은 커맨드 누른상태로 클릭해야 다중선택이 된다

 

package com.fastcampus.ch2;

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

public class HelloServlet  extends HttpServlet {

    @Override
    public void init() throws ServletException {
        // 서블릿이 초기화 될 때 자동 호출되는 메서드
        // 1. 서블릿의 초기화 작업 담당
        System.out.println("[HelloServlet] init() is called.");
    }
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 입력
        // 2. 처리
        // 3. 출력
        System.out.println("[HelloServlet] service() is called.");
    }

    @Override
    public void destroy() {
        // 서블릿이 메모리에서 내려올 때
        // 서블릿이 다시 갱신되서 리로딩 될 때
        // 웹 어플리케이션이 종료될 때 이 메서드가 서블릿과 관련된 뒷마무리 작업을 하기위해 호출이 된다
        System.out.println("[HelloServlet] destroy() is called.");
    }

}

 

그리고 이렇게 적어주자 

 

서블릿의 초기화를 위해 init 메서드가 필요하고 

service는 입력받고 처리하고 출력하기 위해 필요하고

destroy는 서블릿이 메모리에서 내려올 때 필요하다

 

자 그러면 이제 어노테이션을 이용해서 맵핑을 해줘야한다

 

@WebServlet("/hello")
public class HelloServlet  extends HttpServlet {

 

 


이렇게 맵핑을 해준다 한번에 맵핑을 하기 때문에 WebServlet을 적어주고 hello라고 맵핑주소를 써준다

 

이제 실행해보자

 

톰캣으로 실행하고 주소창에 http://localhost:8080/hello 라고 작성해보니까 

 

아무것도 나오지 않는다 

 

하지만 인텔리제이 창을 보면

 

 

이렇게 init과 service가 잘 찍혀있는 것을 볼 수 있다

 

그럼 이제 다시 웹페이지로 돌아가서 새로고침을 여러번 누르고 인텔리제이를 보자

 

아까 설명했던 것 처럼 init은 최초에 1번만 실행되고

service만 계속해서 호출되고 있다

 

그럼 이제 톰캣서버를 꺼보도록 하자

서버를 종료하면 보이는 것 처럼 destroy가 종료되면서 메모리에서 내려왔다는 것을 알 수 있다

 

직접 실습을 해보니까 참 신기하다

 

서블릿의 흐름을 그림과 같이 살펴보도록 하자

 

요청이 오게 되면 Servlet Context에서 요청확인을 한다

 

서블릿 인스턴스가 존재하냐? 

 

존재한다면 -> 서비스를 호출

 

존재하지 않는다면 -> 서블릿 클래스를 로딩한다음 객체를 생성한다 

 

그러면 그 생성된 객체를 Init초기화 하고

 

서비스를 호출해서 응답을 한다 

 

좀 전 실습처럼 처음에는 생성했으니 init이 호출되지만

만들어진 이후부터는 요청을 하면 init을 거치지않고 바로 서비스를 호출하게 된다

 

요청 -> 존재하지않으면 -> init -> service -> 응답

요청 -> 존재 -> service -> 응답 

 

프로그램이 변경되거나 웹 어플리케이션이 종료가되서

서블릿이 메모리에서 내려갈 때 destroy가 딱 1번 호출된다

 

그리고 Servlet Context안에는 children 이라는 멤버가 있다

 

map형태로 서블릿들이 다 등록이 되어있다

 

그래서 요청이 오게되면 서블릿 객체가 존재하는지를 확인할 때

 

map안에 멤버들을 보면서 확인하게 된다

 

서블릿은 기본적으로 싱글톤(Singleton)이다

1개의 객체(인스턴스)만 만들어서 그것을 계속해서 재활용한다

 

요청할 때 마다 새로운 객체를 만들게 할 수도 있는데 기본적으로 싱글톤이다

 

왜냐면 우리가 만든 여러 프로그램들이 있는데 

 

이런것들은 요청하는 사람들마다 처리되어야 할 작업들이 똑같다

 

사람에 따라 작업이 다른 것이 아니고 대부분 똑같은 작업을 하기 때문에

 

사용자마다 프로그램이 여러개있을 필요가 없다 그래서 싱글톤으로 하나의 객체를 가지고 재활용하는 것이다

 

요청이 올 때 마다 새로운 객체를 만들지 않는다는 것을 알고 있자

 

이번에는 JSP페이지를 알아보자

 

3. JSP(Java Server Pages)란? 

 

jsp를 작업하면 자동으로 서블릿으로 변환된다 그러므로 서블릿과 기본적으로 똑같다고 보면 된다

 

이런 페이지가 있을 때 이게 어떻게 변환되냐면

 

 

 

이렇게 변환된다

 

Jsp가 html안에 자바코드가 있는 것이다 

 

자바 코드가 무엇이냐면

<%

여기에 자바 코드를 넣는 것이다

%>

 

 

하단에서는 <%=값%> 이렇게 쓸 수 있는데

 

위에 idx1의 값이 3이라면 하단에 값이 3이 된다고 생각하면 된다

 

그리고 저 <html> <body>이런 것들이 전부

 

out.println이 되는 것이다

저렇게 변환된다

 

그리고 이 모든 내용이 서비스메서드 안으로 들어가게 된다 

 

이렇게 저 코드들이 전부 서비스 메서드 안으로 들어가게된다

 

프로젝트하면서 늘 동작되게 만들기만 바빴는데

 

이렇게 하나씩 뜯어보면서 공부하니까 왜 동작하는지 그 원리를 알 수 있어서 흥미가 있다

 

기본적으로 idx1, idx2는 lv 즉 지역변수인데 

로컬변수가 필요할 경우에는 어떻게 하면 될까?

 

 

<%! ~ %> 이런 형태로 작성해주면 로컬변수로 쓸 수 있다

 

iv, cv 선언을 여기서 해주면 된다

 

그러면 이건 메서드로 가는게 아니라 바로 클래스 안으로 들어가게 된다

 

그래서 <%! ~ %> 는 클래스의 영역이다 

 

<% ~ %> 는 서비스 메서드의 내부로 들어가는 메서드 영역이다 

 

 

jsp페이지는 해당 경로에 만들면 된다

 

그럼 이제 직접 만들어보자 

 

해당 경로인 webapp까지가서 우클릭을 하면 jsp파일을 만들 수 있다

 

twoDice라고 적어주고 생성하자

 

<%@ page contentType="text/html;charset=utf-8"%>
<%@ page import="java.util.Random" %>
<%-- <%! 클래스 영역 %> --%>
<%!
    int getRandomInt(int range){
        return new Random().nextInt(range)+1;
    }
%>
<%-- <%  메서드 영역 - service()의 내부 %> --%>
<%
    int idx1 = getRandomInt(6);
    int idx2 = getRandomInt(6);
%>
<html>
<head>
    <title>twoDice.jsp</title>
</head>
<body>
<img src='resources/img/dice<%=idx1%>.jpg'>
<img src='resources/img/dice<%=idx2%>.jpg'>
</body>
</html>

그리고 이 코드를 붙여넣어주자 

 

jsp페이지는 WebServlet써서 맵핑해주지 않아도 된다 자동으로 맵핑을 해주기 때문이다

 

우리는 호출만 해주면 된다 

 

사진이 정상적으로 잘 나오고 있다

 

 

Jsp의 호출과정에 대해 알아보자

 

그림을 보면 흐름을 알 수 있는데 사실 서블릿과 이름만 약간 다르지 똑같다고 이해하면 된다

 

JspServlet은 객체를 미리 생성하지않고 요청이 들어왔을 때 생성한다

 

서블릿 : 늦은 초기화 

스프링 : 빠른 초기화 

 

둘다 싱글톤으로 되어있다 하나의 객체를 가지고 반복적으로 계산한다

 

서블릿은 미리 객체를 만들어놓는 것이 아니라 요청이 와야 만들지만

스프링은 미리 객체를 만들어놓아서 빠른 초기화가 가능하다

 

둘다 장단점이 있다 

 

서블릿에서도 빠른 초기화가 가능한 방법이 존재하기도 한다

 

 

 

위 이미지처럼 JSP와 서블릿으로 변환된 우측 그림의 JSP를 비교해서 어떤 점이 다른지 알 수 있다

 

jsp가 변환되면서 이름이 twoDice_jsp.java로 바뀌게 된다 

 

JSP의 기본객체라는 것이 존재한다 생성없이 사용할 수 있는 객체인데 

 

여기서 보면 request를 선언한 적 없이 바로 사용하고 있다 그게 가능한 이유는 기본객체로 request가 존재하기 때문이다 

여기 존재하는 Request, Response, pageContext, session, application, config 등등 이런것들이 lv이고 기본객체이다 선언없이 사용이 가능하다 

 

보다시피 기본객체는 이렇게 다양하게 존재한다

 

서비스 메서드의 지역변수로 선언되어있는 것들이기도 하다 

 

이것으로 기본적인 설명 정리를 마치고 다음에 이어서 유효범위와 속성부터 정리해보도록 하자

 

 

'BackEnd' 카테고리의 다른 글

서블릿과 JSP-(3) URL 패턴  (0) 2022.12.17
서블릿과 JSP(2) - 유효범위와 속성  (0) 2022.12.17
관심사의 분리, MVC 패턴 - 실습  (0) 2022.12.15
관심사의 분리, MVC 패턴 - 이론  (0) 2022.12.15
Base64 64진법이란?  (0) 2022.12.15