BackEnd/Servlet

[Servlet] 01

JJoajjoa 2023. 9. 27. 16:57

Servlet 서블릿

Server(서버) + let(작은)

 

Java 기반의 웹 프로그램 개발을 위해 만들어진 기술

Java를 사용하여 웹페이지를 동적으로 생성하는 서버 측의 프로그램

 

제어를 담당

 

자바로 작성된 프로그램을 실행할 수 있는 서버 소프트웨어(WAS, ex 톰캣)를 통해 관리됨

서블릿이 실행되기 위해서는 톰캣 같은 서블릿 컨테이너가 필요

> 이러한 서버 소프트웨어는 일반적으로 WAS Web Application Server라고 불림

 

Servlet API를 사용하면

개발자는 요청에 따라 웹 페이지를 동적으로 생성하고

데이터베이스와 상호작용하고

네트워크 서비스를 처리할 수 있음

 

 

정의

서블릿은 자바 클래스

HTTP 요청을 받아 처리하고 HTTP 응답을 생성하는 역할을 함

 

요청 처리

클라이언트에서 보내는 HTTP 요청 메서드(GET, POST 등)를 받아들여 해당 요청에 대한 로직을 처리함

 

응답 생성

로직 실행 결과에 따라 응답 데이터를 만들어 클라이언트에게 반환함

>> HTML or JSON

 

세션 관리

HTTP는 상태 정보를 유지하지 않는 Stateless 프로토콜임

서블릿도 세션(Session) 객체를 활용하여 상태정보 유지가 가능함

 

서블릿 컨테이너

서블릿은 서블릿 컨테이너 또는 서블릿 웹 컨테이너라고 불리는 컴포넌트 내에서 실행됨

이 컨테이너가 서블릿의 생명주기 관리(init(), service(), destroy()), 멀티스레딩 지원 등의 기능을 담당

 

 

 

 

 

1. 서블릿의 생명 주기 (Lifecycle)

서블릿은 컨테이너에 의해 동작하므로 객체의 생성과정과 종료과정도 컨테이너 안에서 이루어짐

서블릿이 생성되고, 요청을 처리하고, 마지막으로 소멸하는 과정을 의미

메서드  
init()
초기화
서블릿이 최초로 생성될 때 한번만 호출되는 메서드
보통 초기화 로직을 포함
>>서블릿 컨테이너가 클라이언트로부터 요청을 받았을 때 호출됨, 응답하면 소멸됨
만약 서블릿에 설정된 로딩 시점이  서버 시작인 경우  웹 어플리케이션 배포 이후  초기화 과정에서 호출될 수 있음
service()
작업
클라이언트의 모든 요청에 대해 호출되는 메서드
여기 안에서 HTTP 요청 방식(GET, POST 등)에 따라 적절한 메서드(doGet(), doPost() 등)를 호출하여 실제 로직을 처리함
destroy()
종료
서블릿 인스턴스가 소멸되기 전에 한번만 호출되는 메서드
여기 안에서 리소스 해체, 정리 작업과 같은 종료 작업들을 처리함

 

이벤트 생명주기 메서드 실행
서블릿 초기화 → init() 초기에 한번만 실행
   

요청/ 응답     
service() → 스레드를 통해 동시에 실행
doGet()
doPost()
   
서블릿 종료 → destroy() 종료될 때 한번만 실행

 

 

예시

처음 클라이언트의 요청으로 해당 서블릿 클래스가 필요할 때, 컨테이너는 해당 클래스를 로딩하여 인스턴스화 하고

init()을 실행시켜 초기화 작업을 진행함

클라이언트의 모든 요청마다 service() [doGet(), doPost(), doPut(), doDelete()] 와 같은

HTTP method-specific 함수들 실행 

웹 어플리케이션이 종료되거나 리로딩되거나 해당 클래스가 더이상 필요하지 않을 경우

destroy()가 실행되어 종료작업을 처리함

 

 

 

 

2. 요청과 응답처리

클라이언트로부터 들어오는 요청을 어떻게 처리하고 어떤 결과를 반환하는지에 대한 과정을 보여줌

 

HttpServletRequest

클라이언트의 요청 정보를 담고있는 객체

HTTP 프로토콜의 request 정보를 서블릿에 전달하기 위한 목적으로 사용

이 친구를 통해 HTTP 메서드(GET, POST 등), URL, 헤더, 본문, 쿼리스트링, 쿠키 등의 다양한 요청 정보에 접근할 수 있음

또 세션 관리 기능도 제공

 

HttpServletResponse

클라이언트에게 보낼 응답을 담는 객체

개발자는 이 친구에 상태코드, 헤더, 본문, 쿠키 설정 등을 넣을 수 있음

출력 스트림을 사용하여 동적인 HTML 페이지나 JSON 데이터 등 응답 본문을 작성할 수 있음

 

과 정
1 클라이언트가 HTTP 요청을 보냄
2 서블릿 컨테이너가 해당 요청을 받아 적절한 서블릿을 전달함
3 서블릿 컨테이너는 HttpServletRequest , HttpServletResponse 객체를 생성하고,
해당 서블릿에 service() 등의 메서드 인자로 전달
4 개발자가 구현한 로직 내에서 HttpServletRequest 객체로부터 필요한 데이터를 추출하여 비즈니스 로직을 수행
5 비즈니스 로직의 결과값 혹은 반환 페이지 정보 등으로 HttpServletResponse 객체를 설정하거나,
직접 출력스트림으로 반환값을 내보냄
6 service() 메서드 등의 호출이 종료되면 HttpServletResponse 객체가 가진 정보로 HTTP 응답메세지를 만들어
클라이언트에게 전송함

 

 

3. 세션 관리

정보를 유지하기위해 세션 사용

과 정
1 클라이언트가 처음 요청을 보낼 때 서버는 HttpSession 객체를 생성하고 고유한 세션ID를 부여함
2 서버는 응답할 때 이 세션ID를 쿠키나 URL 리라이팅 등의 방식으로 클라이언트에게 전송함
3 클라이언트가 다시 요청을 보낼 때 마다 세당 세션ID가 함께 전송되어
이 ID로 
HttpSession 객체를 찾아 사용자 정보에 접근할 수 있음
4 필요에 따라 개발자는 HttpSession 객체에 속성(Attribute)을 추가하거나 제거하여
필요한 데이터를 저장하거나 조회할 수 있음

 

 

4. 장단점

장점

  • 효율성
    한번 로딩된 이후에는 메모리에 계속 유지되므로 각 요청마다 새로운 프로세스나 스레드를 생성하지 않아도 됨
    >> CGI(Common Gateway Interface) 등의 기술보다 처리속도가 빠르고, 자원사용량도 적음
  • 편리함
    Java를 사용하여 개발하므로 객체 지향적 코드 작성이 가능하며, 재사용 가능한 클래스 라이브러리를 활용할 수 있음
  • 보안
    Java 언어의 보안 관련 기능들과 웹 컨테이너에서 제공하는 인증 및 권한 관리 기능들을 활용할 수 있음
  • 표준화
    Java EE(Enterprice Edition)스펙의 일부로 정의되어 있어 다양한 웹 컨테이너에서 호환될 수 있음

단점

  • 상태관리
    HTTP프로토콜은 Stateless 특성 때문에 상태정보 유지를 위해서는 추가작업이 필요
  • 비즈니스 로직과 프레젠테이션 로직의 혼합
    서블릿 코드 내에서 HTML을 직접 작성하는 경우 비즈니스 로직과 프레젠테이션 로직이 혼합되어
    코드 가독성과 유지 보수성이 떨어질 수 있음
  • 개발 및 배포 복잡성
    이러한 문제는 스프링 부트(Spring Boot)와 같은 프레임워크를 사용하여 간소화할 수 있음

 


서블릿 자체는 자바로 구현하지만,
서블릿 컨테이너에 해당 클래스가 서블릿임을 알려야 함
어떤 URL 접근에 실행해야 하는지 등록과정이 필요함

 

서블릿 클래스 구조

 

서블릿 클래스는 주로 javax.servlet.Servlet 인터페이스를 구현하거나

javax.servlet.http.HttpServelt 클래스를 상속하여 작성함

 

웹 프로그래밍의 대부분은 HTTP 프로토콜에 최적화되어 있는 HttpServlet 클래스를 상속해 구현하는 것이 좋음

 

 

과정

  1. 패키지 및 임포트
    서블릿 클래스에 적절한 패키를 추가해야 함
    반드시 javax.servlet 패키지와 javax.servlet.http 패키지를 임포트 해야 함
  2. 클래스 선언
    서블릿 클래스는 일반적으로 HttpServelt을 상속함
    >> public class NewServlet extends HttpServlet { } 으로 선언됨
  3. 생명주기 메서드
    init(), service(), destroy() 등을 오버라이딩하여 구현함
  4. HTTP 요청 처리
    HTTP요청에 따라 적적한 메서드(doGet(), doPost() 등)를 오버라이딩하여 구현함
  5. 응답생성
    HttpServletResponse 객체를 사용하여 응답 데이터, 상태 코드 헤더 정보, 출력 스트림으로 동적컨텐츠를 작성함
  6. 추가적으로 세션관리(HttpSession), 쿠키사용(Cookie) 등과 같은 기능을 사용할 수 있음

 

 

예시  

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

public class NewServlet extends HttpServlet {
    @Override
    public void init() {
        //초기화 작업
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String name = request.getParameter("name");
        response.setContentType("text/html");
        response.getWriter().println("<h1>Hello, " + name + "</h1>");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if(isValidUser(username, password)) {
            response.setStatus(HttpServletResponse.SC_OK); # 200
            response.getWriter().println("로그인 성공!!");
        } else {
            response.setStatus(HttpServletResponse.SC_UNAUTORIZED); # 401
            response.getWriter().println("로그인 실패!!");
        }
    }

    private boolean isValidUser(String username, String password) {
        return username.equals("admin") && password.equals("password");
    }

    @Override
    public void destroy() {
        //종료작업
    }
}

 

 

 


 

HttpServletRequest

주요 메서드

메서드 설 명
getRequestURI() 
getRequestURL()
클라이언트가 요청한 URI, URL 을 반환함
getMethod() HTTP 요청 메서드를 문자열로 반환함
getParameter(String name) 요청 파라미터 중 지정한 이름의 값을 반환
>> 여러개 있으면 첫번째 값 반환
getParameterValues (String name) 동일한 이름을 가진 모든 요청 파라미터의 값을 문자열 배열로 반환
getParameterNames()
getParameterMap()
모든 요청 파라미터의 이름들을 Enum형태 또는 Map 형태로 반환
getHeader(String name) 지정한 이름의 HTTP 헤더 값을 문자열로 반환
getHeaders(String name)
getHeaderNames()
지정한 이름의 모든 HTTP헤더값들/ 모든 헤더 이름을 열거형으로 반환
getCookies() 요청에 포함된 모든 쿠키 객체를 배열로 반환
getSession(boolean create) 현재 세션 객체(HttpSession)를 가져온다
인자값이 없으면 새로 생성할 지 결정할 수 있음
package com.example.demo;

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.IOException;

public class RequestServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("Request URI : " + request.getRequestURL()); // 요청 URL 출력
		
		System.out.println("Request Method : " + request.getMethod()); // 요청 메소드 출력
		
		// 모든 파라미터들의 이름과 값 출력
		for(String paramName : request.getParameterMap().keySet()) {
			String[] paramValues = request.getParameterValues(paramName);
			for (String value : paramValues) {
				System.out.println("Name : " + paramName + ", value : " + value);
			}
		}
		
		//모든 헤더들의 이름과 값 출력
		java.util.Enumeration<String> headerNames = request.getHeaderNames();
		
		while(headerNames.hasMoreElements()) {
			String headerName = headerNames.nextElement();
			System.out.println("Header Name : " + headerName + ", Value : " + request.getHeader(headerName));
		}
		
		// 쿠키 정보 출력
		Cookie[] cookies = request.getCookies();
		
		if(cookies != null) {
			for(Cookie cookie : cookies) {
				System.out.println("Cookie Name : " + cookie.getName() + ", value : "+ cookie.getValue());
			}
		}
	}
}

 

 

 

HttpServletResponse

주요 메서드

메서드 설 명
setStatus(int sc HTTP 응답 상태를 설정
sendError(int sc, String msg) 에러코드와 에러 메세지를 클라이언트에게 전송
setContentType(String type) 응답의 컨텐츠 타입을 설정
HTML문서로 반환하는 경우 : text/html
JSON 데이터를 반환하는 경우 : application/json
setHeader(String name, String value)
addHeader(String name, String value)
HTTP 헤더의 이름과 값을 추가함
>> 중복된게 있을 때 셋헤더는 덮어쓰기, 애드헤더는 새 값 추가
getWriter()
getOutputStream()
클라이언트에게 전송될 응답 본문을 작성하기 위한 출력 스트림을 반환
addCookie(Cookie cookie) 새로운 쿠키 객체 (javax.servlet.http.Cookie)를 응답에 추가
sendRedirect(String location) 클라이언트에게 지정된 URL로 리다이렉션을 하도록 지시하는 302 상태코드와 함께 location 헤더값을 설정하여 전송함

 

package com.example.demo;

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;

public class ResponseServlet extends HttpServlet {
	@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>response sample</title></head>");
		out.println("<body>");
		out.println("<h1>리스폰 예제 페이지</h1>");
		out.println("</body>");
		out.println("</html>");
		
		out.close();
	}
}