728x90
반응형

[Servlet] 자바 서블릿과 네트워크 | 요청과 응답이 오가는 과정을 파헤쳐보자

 

[Servlet] 자바 서블릿과 네트워크 | 요청과 응답이 오가는 과정을 파헤쳐보자

[Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | Java 웹 구조의 이해 - 2 [Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | Java 웹 구조의 이해 - 2[Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | Java 웹 구조의 이해 - 1 [Serv

crushed-taro.tistory.com

1. Thread

1. Thread 개요

1. Process와 Thread

  • Process
    • 실행 중인 프로그램을 가리키며, 프로그램이 실행될 때마다 개별적으로 생성된다.
    • 하나의 프로세스는 프로그램을 수행함에 있어 필요한 데이터, 메모리 등의 할당 받은 자원, 하나 이상의 스레드로 구성된다.
  • Thread
    • 프로세스 내에서 할당된 자원을 이용해 실제 작업을 수행하는 작업 단위로, 모든 프로세스는 하나 이상의 스레드를 가지며 각각 독립적인 작업 단위를 지닌다.

 

2. main thread

  • 모든 자바 프로그램은 메인 스레드가 main() 메소드를 실행하며 시작되어, main() 메소드의 첫 코드부터 아래로 순차적으로 실행되다가 return을 만나면 종료된다.
  • 필요에 의해 작업 스레드들을 만들어서 병렬 코드를 실행(= 멀티 스레드를 이용한 멀티 태스킹)할 수 있다.
  • 싱글 스레드는 메인 스레드가 종료되면 프로세스도 종료되지만, 멀티 스레드는 실행 중인 스레드가 하나라도 있다면 프로세스가 종료되지 않는다.

 

2. Multi Thread

1. Multi Process와 Multi Thread

Thread 사진 1

  • 멀티 프로세스 : 각각의 프로세스를 독립적으로 실행한다.
  • 멀티 스레드 : 하나의 프로세스 내에서 여러 스레드가 동시에 작업을 수행한다.

 

2. Single Thread와 Multi Thread

Thread 사진 2

  • 싱글 스레드 : 메인 스레드 하나만 가지고 작업을 처리하며, 한 작업씩 차례대로 처리한다.
  • 멀티 스레드 : 메인 스레드 외의 추가적인 스레드를 이용하여 병렬적으로 작업을 처리한다.

Thread 사진 3

  • 멀티 스레드의 장점
    1. 자원을 보다 효율적으로 사용할 수 있다.
    2. 사용자에 대한 응답성이 향상된다.
    3. 애플리케이션의 응답성이 향상된다.
    4. 작업이 분리되어 코드를 간결하게 작성할 수 있다.
    5. CPU 효율성이 향상된다.
  • 멀티 스레드의 단점
    1. 동기화(= Synchronization)에 주의해야 한다.
    2. 교착상태(= dead-lock)가 발생하지 않도록 주의해야 한다.
    3. 이처럼 프로그래밍 시 고려해야 할 사항이 많다.

 

3. Thread 사용

1. Thread 구현 방법

  • Thread 클래스를 상속 받아 구현하는 방법이 있다.
  • Runnable 인터페이스로 구현하는 방법이 있다.

 

2. Thread 동작 구조

  • run() 호출

Thread 사진 4

 

  • start() 호출

Thread 사진 5

 

  • 스레드 스케줄링

Thread 사진 6

 

3. Java Thread Scheduling 방식

  • 우선 순위 방식 (Priority)
    • 우선 순위가 높은 스레드가 작업 시간을 더 많이 가지도록 하는 스케쥴링 방식이다.
    • 스레드에 1부터 10까지 우선 순위 번호를 부여할 수 있으며, 번호가 높을수록 우선 순위가 높다.
    • 스레드 생성 시 우선 순위 기본값은 5이다.
    • 사용 예시
public class Run {
	public static void main(String[] args) {
		클래스명 레퍼런스 = new 생성자(); //Thread를 상속한 객체 생성
		레퍼런스.setPriority(1 ~ 10);
	}
}

 

  • 순환 할당 방식 (Round-Robin)
    • 시간 할당량(Time Slice)을 정하여 하나의 스레드를 정해진 시간만큼 실행시키는 방식이다.
    • JVM에 의해 정해지기 때문에 코드로 제어가 불가하다.

 

4. Thread control

  • 효율적이고 정교한 스케쥴링을 위하여 실행 중인 thread의 상태를 제어하는 기능을 한다.

Thread 사진 7

  • Thread control의 주요 method는 다음과 같다.
method명 설명
void interrupt() - (sleep() 이나 join() 에 의해) 일시정지 상태인 스레드를 실행대기 상태로 변경
- 해당 스레드에서 InterruptException이 발생해 일시정지 벗어남
void join()
void join(long millis)
void join(ling millis, int nanos)
- 지정된 시간 동안 스레드 실행시킴
- 지정 시간이 지나거나 작업이 종료되면 join() 호출한 스레드로 돌아와 실행 계속함
static void sleep(long millis)
static void sleep(long millis, int nanos)
- 지정된 시간 동안 스레드 일시정지 시킴
- 지정 시간이 지나면 자동으로 실행대기 상태로 변경
static void yield() 실행 중 다른 스레드에게 양보하고 실행대기
void wait()
void wait(long timeout)
void wait(long timeout, int nanos)
동기화 된 블록 안에서 다른 스레드가 이 객체의 notify(), notifyAll()을 호출하거나 지정된 시간이 지날 때까지 현재 thread 대기시킴
void notify() - 동기화 된 블록 안에서 호출한 객체 내부에서 대기 중인 스레드 깨움
- 여러 스레드가 있을 경우 임의의 스레드 하나에만 통보
void notifyAll() - 동기화 된 블록 안에서 호출한 객체 내부에서 대기 중인 모든 스레드 깨움
- 하지만 lock은 하나의 스레드만 얻을 수 있음

 

4. 동기화 (Synchronized)

1. 동기화란

  • 한번에 한 개의 스레드만 프로세스 공유 자원(= instance)에 접근할 수 있도록 락(Lock)을 걸어 다른 스레드가 진행 중인 작업에 간섭하지 못하도록 하는 것이다.

Thread 사진 8

 

2. 동기화 method와 동기화 block

  • 동기화 method
public synchronized void method() {
	// 한 개의 스레드만 실행할 수 있다.
}

 

  • 동기화 블록
public void method1() {
	// 여러 스레드를 실행할 수 있다.

	synchronized (공유 인스턴스) {
		// 한 개의 스레드만 실행할 수 있다.
	}

	// 여러 스레드를 실행할 수 있다.
}

 

Thread 사진 9
Thread 사진 10

 

5. Daemon Thread

1. Daemon Thread란

  • 다른 스레드의 작업을 돕는 보조 역할을 수행하는 스레드이다.
  • 데몬 스레드 이외의 스레드가 모두 종료되면 데몬 스레드는 강제로 종료된다.
  • ex) 가비지 컬렉션, 워드 프로세서의 자동 저장, 화면 자동 갱신 등

 

2. Daemon Thread 생성

  • 데몬 스레드가 될 스레드의 레퍼런스 변수에 setDaemon(true)를 호출하여 생성한다.
  • 단, start() method 호출 전에 setDaemon(true)를 호출해야 한다.
  • → 그러지 않으면 IllegalThreadStateException이 발생한다.

 

6. 실습 예제

1. 간단한 웹 서버 구현 예제

  • 요청 시 Header 값을 출력하는 간단한 웹서버를 구현하는 코드이다.
  • 클라이언트가 요청을 한번 보내면 서버에는 총 3번의 요청이 들어온다. 왜냐하면 브라우저가 favicon 요청을 위해 request를 다시 한 번 보내기 때문이다.
  • 해당 예제에서는 favicon 설정 없이 진행하므로 3번째 요청에 대해서만 처리하도록 구현한다.
public static void main(String[] args) throws IOException {

      /* 클라이언트의 요청을 기다릴 ServerSocket 생성 */
      ServerSocket listener = new ServerSocket(8002);

      /* 요청 횟수를 판단하기 위한 변수 선언 */
      int count = 1;

      try {

          System.out.println("Http Server started at 8002 port");

          while (true) {

              /* 클라이언트 요청이 들어오면 통신할 socket 생성 */
              Socket socket = listener.accept();

              try {
                  /* 요청한 클라이언트의 정보 받아옴 */
                  System.out.printf("New Client Connect! Connected IP : %s, Port : %d\n",
                          socket.getInetAddress(), socket.getPort());

                  count++;

                  InputStream in = socket.getInputStream();
                  OutputStream out = socket.getOutputStream();

                  /* 파비콘 요청을 위한 요청은 건너뛰고 header 내용은 3번째 요청인 본 요청으로 읽음 */
                  int value = 0;
                  while((value = in.read()) != -1 && count == 3) {
                      System.out.print((char)value);
                  }

                  String responseText = "<h1>Hello World</h1>";

                  String responseGeneralHeader = "HTTP/1.1 200 OK \r\n";
                  String contentType = "Content-Type: text/html; charset=utf-8\r\n";
                  String contentLength = "Content-Length: " + responseText.length() + "\r\n";
                  String whiteLine = "\r\n";

                  /* 패킷 통신을 위해 byte 단위로 출력하도록 함 */
                  out.write(responseGeneralHeader.getBytes());
                  out.write(contentType.getBytes());
                  out.write(contentLength.getBytes());
                  out.write(whiteLine.getBytes());

                  out.write(responseText.getBytes());
                  out.write(whiteLine.getBytes());

                  out.flush();

              } finally {
                  /* 자원 반납 */
                  socket.close();
              }
          }
      } finally {
          /* 자원 반납 */
          listener.close();
      }

  }

 

2. Multi Thread를 생성하는 간단한 웹 서버 예제

  • 요청 시마다 멀티 스레드를 생성하여 Header 값을 출력하는 간단한 웹 서버를 구현하는 코드이다.
public static void main(String[] args) throws IOException {

		// 8000번 포트로 서버소켓 생성
    ServerSocket serverSocket = new ServerSocket(8000);

    Socket client;

    while ((client = serverSocket.accept()) != null) {

        Socket finalClient = client;

        /* client socket의 요청을 승인하여 연결될 때마다 스레드 생성 */
        new Thread(() -> {
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(finalClient.getInputStream()));

                // General header parsing
                String generalHeader = reader.readLine();
                System.out.println("generalHeader = " + generalHeader);

                String requestMethod = generalHeader.split(" ")[0];
                String requestPath = generalHeader.split(" ")[1];

                System.out.println("requestMethod = " + requestMethod);
                System.out.println("requestPath = " + requestPath);

                // Request header parsing
                Map<String, String> requestHeader = new HashMap<>();
                String line;
                while ((line = reader.readLine()) != null) {

                    /* 읽어온 라인이 비어있지 않은 경우 */
                    if (line.isBlank()) {
                        break;
                    }

                    /* 읽어온 라인을 :(콜론)을 기준으로 나누어 key-value 구분해서 받음 */
                    String key = line.split(": ")[0];
                    String value = line.split(": ")[1];

                    requestHeader.put(key, value);
                }
                System.out.println("requestHeader = " + requestHeader);

                // POST방식의 요청인 경우 body parsing
                String body = null;
                if ("POST".equals(requestMethod)) {

                    int contentLength = Integer.parseInt(requestHeader.get("Content-Length"));
                    char[] temp = new char[contentLength];
                    reader.read(temp);
                    body = new String(temp).trim();
                }
                System.out.println("body = " + body);

            } catch (IOException e) {
                throw new RuntimeException(e);
            }

        }).start();

    }

}
728x90
반응형
728x90
반응형

[Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | Java 웹 구조의 이해 - 2

 

[Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | Java 웹 구조의 이해 - 2

[Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | Java 웹 구조의 이해 - 1 [Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | Java 웹 구조의 이해 - 1[Servlet] Servlet Listener란? 웹 애플리케이션의 생명주기 관리하기 [Servl

crushed-taro.tistory.com

1. Network

1. Network 개요

1. Network란

Network 사진 1

  • 여러 대의 컴퓨터를 통신 회선으로 연결한 것이다.
  • (홈 네트워크, 지역 네트워크, 인터넷 등이 해당된다.)

 

2. Server & Client

  • 서버와 클라이언트는 네트워크로 연결된 컴퓨터 간의 관계를 역할로 구분한 개념이다.
    • 서버는 서비스를 제공하는 컴퓨터(혹은 프로그램)로, 클라이언트의 연결을 수락하고 요청 내용을 처리하여 응답을 보내는 역할이다.
    • 클라이언트는 서비스를 받는 컴퓨터(혹은 프로그램)로, 네트워크 데이터를 필요로 하는 모든 애플리케이션에 해당한다.
  • 클라이언트는 서버에 연결 요청을 하려면 IP주소와 Port 번호를 알아야 한다.

Network 사진 2

  • IP 주소는 네트워크 상에서 컴퓨터를 식별하는 번호이며, 네트워크 어댑터(랜카드)마다 할당된다.
  • Port는 같은 컴퓨터 내에서 프로그램을 식별하는 번호이다.

 

2. Java Network

1. Inet Class

  • IP주소를 다루기 위해 Java에서 제공하는 Class이다.
  • 주요 method는 다음과 같다.
Method 명 설명
byte[] getAddress() IP주소를 byte배열로 반환
static InetAddress[] getAllByName(String host) 도메인명에 지정된 모든 호스트의 IP주소를 배열로 반환
static InetAddress getByAddress(byte[] addr) byte 배열로 IP주소 반환
static InetAddress getByName(String host) 도메인명으로 IP주소 반환
String getCanonicaHostName() FQDN(Full Qualified Domain Name) 반환
String getHostAddress() 호스트의 IP주소 반환
String getHostName() 호스트의 이름 반환
static InetAddress getLocalHost() 지역호스트의 IP주소 반환
boolean isMulticastAddress() IP주소의 멀티캐스트 주소 여부 반환
boolean isLoopbackAddress() IP주소의 loopback 주소(127.0.0.1) 여부 반환

 

2. Socket Programming

1. Socket Programming이란

  • 소켓을 이용한 통신 프로그래밍이다.
    • 소켓(Socekt)이란 프로세스 간 통신에 사용되는 양쪽 끝 단을 의미한다.

 

2. Socket Programming 프로토콜 종류

  • TCP
    • 연결 지향적 프로토콜로, 서버가 수락해야 데이터 송수신이 가능하다. (Like 전화)
    • 데이터 전송 속도가 느리지만 정확하고 안정적으로 전달할 수 있다.
  • UDP
    • 비연결 지향적 프로토콜로, 연결 없이 일방적으로 데이터를 전달한다. (Like 택배)
    • 데이터 전송 속도가 빠르지만 신뢰성 없는 데이터를 전송한다.

 

3. TCP Socket Programming

Network 사진 3

  • 클라이언트와 서버 간의 1:1 소켓 통신을 한다.
  • 서버가 먼저 실행되어 클라이언트의 요청을 기다려야 하고, 서버용 프로그램과 클라이언트용 프로그램을 따로 구현해야 한다.
  • 자바에서는 TCP 소켓 프로그래밍을 위해 java.net패키지에서 ServerSocket과 Socket Class를 제공한다.

 

  • 서버용 TCP 소켓 프로그래밍 순서
    1. 서버의 port 번호를 정한다.
    2. 서버용 Socket 객체를 생성한다.
    3. 클라이언트 쪽에서 접속 요청이 올 때까지 대기한다.
    4. 접속 요청이 오면 요청 수락 후, 해당 클라이언트에 대한 Socket 객체를 생성한다.
    5. 연결된 클라이언트와 입출력 stream을 생성한다.
    6. 보조 stream을 통해 성능을 개선할 수 있다.
    7. stream을 통해 읽고 쓰기를 진행한다.
    8. 통신을 종료한다.

 

  • 클라이언트용 TCP 소켓 프로그래밍 순서
    1. 서버의 IP 주소와 서버가 정한 port번호를 매개변수로 하여 클라이언트용 Socket 객체를 생성한다.
    2. 서버와의 입출력 Stream을 오픈한다.
    3. 보조 Stream을 통해 성능을 개선할 수 있다.
    4. Stream을 통해 읽고 쓰기를 진행한다.
    5. 통신을 종료한다.

 

  • TCP upgrade → HTTP

Network 사진 4

  • TCP에서 업그레이드된 것이 HTTP이다.
    • 몇 번째 요청인지 순번까지 포함하여 보내고, 받는 쪽에서 재조합해 사용한다.
    ⇒ Socket class를 이용한다.

 

4. UDP Socket Programming

Network 사진 5

  • UDP는 비연결 지향이므로 연결 요청을 받아 줄 서버 소켓이 필요 없다.
  • Java.net 패키지에서 제공하는 두 개의 DatagramSocket간에 DatagramPacket으로 변환된 데이터를 주고 받는다.
728x90
반응형
728x90
반응형

[Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | Java 웹 구조의 이해 - 1

 

[Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | Java 웹 구조의 이해 - 1

[Servlet] Servlet Listener란? 웹 애플리케이션의 생명주기 관리하기 [Servlet] Servlet Listener란? 웹 애플리케이션의 생명주기 관리하기[Servlet] Servlet Filter 구현 예제와 실전 적용 방법 [Servlet] Servlet Filter 구

crushed-taro.tistory.com

 

1. MVC Architecture

1. MVC Architecture 구성

1. Model

  • 웹 애플리케이션의 비즈니스 로직, 즉 수행할 서비스를 담당한다.
    1. Service
      • 여러 DAO를 호출하여 데이터 접근 및 갱신을 하는 클래스이다.
      • DAO를 통해 읽은 데이터에 대한 비즈니스 로직을 수행하여 Controller에 그 결과를 전송한다.
    2. DAO (Data Access Object)
      • 데이터베이스에 직접 접근하여 요청 받은 결과를 반환하는 클래스이다.
    3. VO (Value Object)
      • 계층 간 데이터 교환을 위한 객체 클래스를 말한다.
      • 동의어: DTO(Data Transfer Object), Domain Object, Bean, Entity
      • ※ VO의 동의어는 유래에 따라 의미가 다른 부분이 있지만, 정확한 구분이 어려워 유사한 의미로 쓰인다.

 

2. View

  • 사용자가 요청을 하거나, 요청한 정보를 응답으로 받아서 볼 수 있는 화면을 담당한다.
  • JSP, HTML 등을 통해 표현한다.

 

3. Controller

  • 사용자의 요청을 전달받아 응답 처리를 위한 Service를 호출하고 결과를 View에 전송하는 클래스로, Servlet으로 작성한다.
  • 전달 받은 정보를 바탕으로 사용자 요청을 분석하고, 이를 서비스에 전달할 VO객체를 생성하여 Service에 전달한다. 그리고 Service로부터 받은 결과를 관련된 View 화면에 담아 사용자에게 응답한다.

 

2. 요청의 전달

1. RequestDispatcher

  • 사용자의 요청을 다른 Servlet이나 JSP 페이지에 전달할 때 사용하는 클래스로, request 객체를 사용해 생성할 수 있다.
  • 예시
RequestDispatcher view = request.getRequestDispatcher("/result.jsp" );
view.forward( request, response );

 

2. 동적 페이지 View(JSP)로 응답할 경우

  • request 내장 객체를 통해 RequestDispatcher 객체를 생성한다.
RequestDispatcher view = request.getRequestDispatcher("/result.jsp");

 

  • 대상 View에서 필요한 정보를 request 영역에 저장한다.
request.setAttribute("member", member);

 

  • request와 response를 인자 값으로 전달하여 정보를 전송한다.
view.forward( request, response );

Servlet 사진 1

 

3. 정적 페이지(JSP) View로 응답할 경우

  • 정적인 html은 동적으로 화면을 생성할 필요가 없으므로 응답 view에 정보를 전달할 필요가 없다.
  • 이때 사용하는 것이 HttpServletResponse 객체의 sendRedirect() 메소드이다.
response.sendRedirect("/error.html");
  • 이렇게 sendRedirect 정보를 받은 클라이언트는 서버로부터 받은 페이지 주소로 다시 요청을 시도한다.
  • ※ request 객체는 한 번 요청한 후 제거되기 때문에 sendRedirect()를 통해 request의 정보를 전달해야 하면, 쿼리스트링을 통해 데이터를 전달해야 한다.

Servlet 사진 2

728x90
반응형
728x90
반응형

[Servlet] Servlet Listener란? 웹 애플리케이션의 생명주기 관리하기

 

[Servlet] Servlet Listener란? 웹 애플리케이션의 생명주기 관리하기

[Servlet] Servlet Filter 구현 예제와 실전 적용 방법 [Servlet] Servlet Filter 구현 예제와 실전 적용 방법[Servlet] Servlet에서 Request와 Response를 가공하는 가장 좋은 방법 | Wrapper 클래스1. Servlet Filter1. Servlet Fil

crushed-taro.tistory.com

1. MVC Architecture

1. MVC Architecture 개요

1. Model - View - Controller

  • 웹 어플리케이션 개발 시 MVC 패턴을 적용하여 각각의 역할별 작업이 가능하도록 분담하는 설계 패턴을 의미한다.
  • 대부분의 웹 어플리케이션 구조는 MVC 패턴을 적용하고 있다.

Servlet 사진 1

 

2. MVC Architecture 단계별 이해하기

1. 원시적 애플리케이션 프로그램 구조

  • 시스템은 위에서 아래로 실행되므로 아래 그림처럼 최초 화면부터 로직을 거쳐 결과 화면 현출까지 구성되어 있다.
  • 비즈니스 로직에서는 데이터베이스에 접근하여 데이터를 처리한다.

Servlet 사진 2

 

  • 이처럼 모든 흐름을 하나의 소스 코드에서 관리하는 경우 아래처럼 진행되기 때문에 두 가지 문제점이 발생한다.

Servlet 사진 3

  1. 중복되는 코드 작성의 우려가 있다.
  2. 일부 수정 사항이 발생하면 모든 로직의 쿼리에 영향을 준다.

 

  • 이러한 문제들로 비즈니스 로직 재사용성 저하되므로 이를 해결하기 위하여 각각의 로직을 분리하여 코드를 작성하고 호출하도록 개선한다.

 

2. DAO

💡 DAO(Data Access Object) : 데이터베이스에 접근하기 위한 용도의 객체
⇒ CRUD 연산을 담당하는 메소드의 집합으로 이루어진 클래스
C(Create) : 삽입(insert)
R(Read) : 조회(select)
U(Update) : 수정(update)
D(Delete) : 삭제(delete)

 

  • DAO의 사용 목적은 쿼리문 단위로 기능을 분리해 재사용하기 위함이다.
    • 기능을 하나의 로직으로 통째로 묶어 사용하는 것보다 잘게 분리해 놓을수록 재사용 가능성이 높아지기 때문이다.
     

Servlet 사진 4

  • 위의 블럭 조각을 예시로 볼 때도, A 조각보다는 잘게 쪼개진 B조각이 더 많은 블럭에 끼워 맞출 수 있으므로 활용도가 높다.

 

  • 생산성과 유지보수성을 고려했을 때 작은 단위로 구분하는 편이 훨씬 - 유리하므로, 작은 단위로 구성하고 이를 모아둔 것이 DAO이다.

Servlet 사진 5

 

  • 논리적 작업은 하나의 트랜잭션으로 작동해야 하고, 하나의 트랜잭션은 반드시 하나의 Connection으로 수행해야 한다.

Servlet 사진 6

  • 따라서 Connection을 통제하는 쪽은 논리 기능을 하는 기능 수행 쪽이고, DAO는 해당 Connection을 매개변수로 빌려줘 사용하도록 하는 것이다.
  • 조회 결과를 담은 resultSet은 java.sql 패키지에 의존하고 있고, 그 의존에 의한 영향을 최소화하기 위하여 resultSet은 데이터베이스에 직접 접근하는 DAO 클래스 내에서만 사용하고 기능 수행단에서 쓰지 않는 것이 일반적이다.

 

3. Service

  • DAO를 활용해 아래처럼 구성하면 화면과 로직이 하나의 코드로 이루어진다.

Servlet 사진 7

  • 이 경우에는 문제점은 크게 세 가지로 볼 수 있다.
    1. 화면마다 로직을 작성해야 한다.
    2. 화면이나 로직 둘 중 하나만 다른 경우(같은 화면-다른 로직 or 다른 화면-같은 로직)에 매번 파일을 새로 작성해야 한다.
    3. 화면단 코드를 작성하는 프론트엔드 개발자와 기능 로직의 코드를 작성하는 백엔드 개발자가 다른 경우가 많은데, 같은 파일에 화면과 로직을 동시에 포함하면 작업 시 충돌 가능성이 있다.

⇒ 따라서 Service 클래스를 추가하여 화면과 로직을 분리한다.

Servlet 사진 8

 

  • Connection 객체의 autoCommit 속성을 통해 DML 처리 후 자동 commit 여부를 지정할 수 있는데, 보통 비즈니스 로직을 하나의 트랜잭션으로 처리할 수 있도록 false로 설정한다.
    • commit/rollback 여부는 하나의 트랜잭션을 처리하는 로직에서 처리한다.
     

Servlet 사진 9

  • Service 역할에는 비즈니스 로직에서 처리를 위하여 다음 두 가지도 포함된다.
    • connection에 대한 전반적 라이프사이클 관리
    • transaction 제어

 

  • 즉, 트랜잭션 제어를 담당하는 클래스에서 connection의 open부터 commit, rollback과 객체 반납을 처리하는데 해당 Class들의 패키지가 Service이다.

Servlet 사진 11

  • MVC 패턴에서 가장 핵심은 model이고, 그중에서도 service이다.
  • ⇒ SOA (Service Oriented Architecture)

 

4. Controller

  • Service가 추가되더라도 view에서 service를 직접 호출하는 결합(의존)이 여전히 존재한다.
    • service 이름, 내용 등이 바뀌면 view에도 영향을 준다
    • 비즈니스 로직을 직접 호출한다.
    • 사용 기기 종류 등에 따른 view가 추가될 때마다 service의 수정에 영향을 받는 파일 갯수가 늘어난다.
     

Servlet 사진 12

  • 각 view에 특성에 따라 service 내용을 수정해야 하는 경우도 발생한다. 예를 들어 web과 Android는 값 전달 방식이 다른데, 비즈니스 로직에 view마다 적용되는 로직을 작성하고 수정해야 한다.

⇒ view-service 간 의존 관계 낮추고자 controller를 추가하여 중간 다리 역할을 하도록 한다.

 

  • Controller 역할을 다음과 같다.

Servlet 사진 13

  • view에서 파라미터 값을 받아 필요에 따라 가공하여 service로 전달한다.
    • 시간 등의 정보는 view에서 받으면 사용자 조작으로 이상한 정보를 입력할 가능성이 있으므로 Controller에서 생성하기도 한다.
  • service 로직 처리 결과를 받아 view 호출 및 결과 반환한다.

 

5. MVC Architecture 완성

  • 결과적으로 프로그램 흐름 구성은 아래처럼 구성된다.

Servlet 사진 14

 

  • 흐름에 따라 처리하는 내용을 간략하게 보면 아래 그림과 같다.

Servlet 사진 15

 

  • 이 구조를 계층 구조로 나누어보면 아래와 같다.

Servlet 사진 16

💡 DTO (Data Transfer Object)
여러 계층간 데이터 전송을 위해 다양한 타입의 데이터를 하나로 묶어 전송할 용도의 클래스이다.
(VO, Bean, Entity 등은 모두 DTO를 의미한다.)

DTO 클래스의 필수 작성 조건
- 모든 필드의 접근 제한자는 private (외부에서 직접 접근 불가해야 함)
- 기본생성자와 모든 필드를 초기화하는 생성자
- 모든 필드에 대한 setter/getter
- toString Overriding을 이용한 필드 값 반환용 메소드
- 직렬화 처리 (DB와 byte 단위로 데이터 송수신하기 위함)

DTO 클래스 작성 시 참고 사항
- 컬럼 하나에 DTO 필드(변수) 하나가 대응되도록 만드는 것이 일반적이다.
- 필드 네이밍은 컬럼명을 낙타봉 표기법으로만 바꿔주면 된다.
728x90
반응형
728x90
반응형

[Servlet] Servlet Filter 구현 예제와 실전 적용 방법

 

[Servlet] Servlet Filter 구현 예제와 실전 적용 방법

[Servlet] Servlet에서 Request와 Response를 가공하는 가장 좋은 방법 | Wrapper 클래스1. Servlet Filter1. Servlet Filter 개요1. Servlet Filter란jakarta.servlet.Filter Interface를 상속 받아 구현하는 Class이다.HTTP 요청과 응

crushed-taro.tistory.com

1. Servlet Listener

1. Servlet Listener 개요

1. Servlet Listener란

  • 웹 컨테이너가 관리하는 LifeCycle 사이에 발생하는 이벤트를 감지하여, 이벤트 발생 시 그에 대한 일련의 로직을 처리하는 인터페이스이다.

 

2. Servlet Listener 동작 구조

Servlet 사진 1
Servlet 사진 2

https://docs.oracle.com/cd/B14099_19/web.1012/b14017/filters.htm

 

Servlet Filters and Event Listeners

Servlet filters are used for preprocessing Web application requests and postprocessing responses, as described in the following sections: Overview of Servlet Filters When the servlet container calls a method in a servlet on behalf of the client, the HTTP r

docs.oracle.com

  • 대상 서블릿 동작에 따른 리스너 메서드가 동작한다.

 

3. Servlet Listener 사용하는 경우

- Page scope : 하나의 Servlet, 즉 하나의 Class에서만 공유 가능하다.
- Request scope : forward에 한정해 공유할 수 있는 범위이다.
- Session scope : redirect 방식에서도 활용할 수 있는 범위로, 대표적으로 로그인 정보가 이 영역에 속한다. 사용자가 사용하는 모든 페이지에서 사용자의 정보를 가지고 있어야 하기 때문이다.
- Application scope : 브라우저별 정보보다 넓은 범위이다.

Servlet 사진 3

  • Context 변경이 발생하는 경우 (→ 톰캣 컨테이너 자체에 리스너 연결)
    • 웹 애플리케이션의 시작, 종료 시점
    • context에 attribute 추가, 제거, 수정 시점
  • Session 객체에 변경이 발생하는 경우 (→ 세션에서 발생 가능한 이벤트)
    • HttpSession의 시작, 종료 시점
    • HttpSession에 attribute 추가, 제거 , 수정 시점
  • Request 객체에 변경이 발생하는 경우 (→ request 관련 이벤트)
    • ServletRequest 생성, 소멸 시점
    • ServletRequest에 attribute 추가, 제거, 수정 시점

 

2. Servlet Listener 종류

1. Context Listener

  • ServletContextListener
    • 웹 애플리케이션의 시작과 종료 시 자동 발생하는 이벤트로, Context 생성/소멸 및 Application 생성/소멸 시점에 로직을 처리한다.
    • Method
      • contextInitialized (ServletContextEvent e) : void
      • → 웹 컨테이너가 처음 구동되어 ServletContext가 생성될 때 작동
      • contextDestoryed (ServletContextEvent e) : void
      • → 웹 컨테이너가 종료될 때, ServletContext가 소멸될 때 작동
  • ServletContextAttributeListener
    • 웹 컨테이너에 저장된 속성의 값이 변경될 경우 발생하는 이벤트로, ServletContext 객체에 속성이 추가, 삭제, 수정되는 시점에 로직을 처리한다.
    • Method
      • attributeAdded (ServletContextAttributeEvent e) : void
      • → 새로운 속성 값이 추가될 때 실행
      • attributeRemoved (ServletContextAttributeEvent e) : void
      • → 속성 값이 제거될 때 실행
      • attributeReplaced (ServletContextAttributeEvent e) : void
      • → 속성 값이 변경될 때 실행

 

2. Session Listener

  • HttpSessionListener
    • HTTP session의 생성 및 소멸 시에 작동하는 이벤트로, HttpSession 객체가 생성되거나 소멸되는 시점에 로직을 처리한다.
    • Method
      • sessionCreated (HttpSession e) : void
      • → Session 생성 시 실행
      • sessionDestoryed (HttpSession e) : void
      • → Session 무효화 될 때 실행
  • HttpSessionAttributeListener
    • Session에 대한 속성의 값이 변경될 경우 발생하는 이벤트로, HttpSession에 대한 속성 값이 변경될 경우 로직을 처리한다.
    • Method
      • attributeAdded (HttpSessionBindingEvent e) : void
      • → Session에 새로운 속성 값이 추가될 때 실행
      • attributeRemoved (HttpSessionBindingEvent e) : void
      • → Session에 속성 값이 제거될 때 실행
      • attributeReplaced (HttpSessionBindingEvent e) : void
      • → Session에 속성 값이 변경될 때 실행
  • HttpSessionBindingListener
    • 현재 Session에 객체가 추가되거나 해제될 때 발생하는 이벤트로, 사용자의 현재 Session에 바인딩 되거나 해제될 객체가 발생할 경우 로직을 수행한다.
    • Method
      • valueBound (HttpSessionBindingEvent e) : void
      • → 객체가 Session에 연결될 때 실행
      • valueUnBound (HttpSessionBindingEvnet e) : void
      • → 객체가 Session으로부터 연결이 해제될 때 실행

    • HttpSessionAttributeListener : 세션에 어떤 속성이 추가/수정/삭제되는 이벤트가 발생한 경우
    • HttpSessionBindingListener : 자신이 세션에 속성으로 추가/삭제된 경우

 

  • HttpSessionActivationListener
    • HTTP session이 활성화 또는 비활성화를 감지했을 때 작동하며, HttpSession이 새로 생성되어 활성화될 때 로직을 처리한다.
    • Method
      • sessionDidActivate (HttpSessionEvent e) : void
      • → Session 활성화 될 때
      • sessionWillPassivate (HttpSessionEvent e) : void
      • → Session 비활성화 되려고 할 때

    • session migration : session 활성화 상태에 따라 동작한다.
    • changes to id : session id 새로 발급되거나 변경되었을 때, session migration과 엮어서 사용한다.
    • session migration이 필요한 경우는 다음과 같다.
     

Servlet 사진 4

  • 사용자가 많아지면 똑같은 프로그램 탑재한 서버를 추가로 사용한다.
  • 이런 경우 클라이언트로부터 요청이 들어왔을 때 중간에서 요청을 각 서버로 분산시키는 역할을 하는 것이 L4 스위치로 로드 밸런서라고도 부른다. 이 스위치는 라운드 로빈 방식 사용한다.

Servlet 사진 5

  • 서버가 분산된 경우 세션을 공유해 사용(= 세션 클러스트링)할 수 있도록 하는데, 이때 세션이 유효한지, 활성화 상태인지 등을 확인하기 위해 이벤트 리스너를 사용한다.

 

3. Request Listener

  • ServletRequestListener
    • 클라이언트로부터 서버로 요청 시 자동 발생하는 이벤트로, request 객체가 생성되거나 소멸되는 시점에 로직을 처리한다.
    • Method
      • requestInitialized (ServletRequestEvent e) : void
      • → request 생성 시 작동
      • requestDestroyed (ServletRequestEvent e) : void
      • → request 소멸 시 작동
  • ServletRequestAttributeListener
    • request에 대한 속성의 값이 변경될 경우 발생하는 이벤트로, request객체에 대한 속성 값이 변경될 경우 로직을 처리한다.
    • Method
      • attributeAdded (ServletRequestAttributeEvent e) : void
      • → request에 새로운 속성 값이 추가될 때 실행
      • attributeRemoved (ServletRequestAttributeEvent e) : void
      • → request에 속성 값이 제거될 때 실행
      • attributeReplaced (ServletRequestAttributeEvent e) : void
      • → request에 속성 값이 변경될 때 실행

 

3. Servlet Listener 활용 예시

1. Context Listener

  • ServletContextListener와 ServletContextAttributeListener
import jakarta.servlet.ServletContextAttributeEvent;
import jakarta.servlet.ServletContextAttributeEvent;
import jakarta.servlet.ServletContextAttributeListener;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.annotation.WebListener;

@WebListener
public class ContextListenerTest implements ServletContextListener, ServletContextAttributeListener {

    public ContextListenerTest() {
        /* context가 생성될 때 변화를 감지하는 Listener 인스턴스 함께 생성 */
        System.out.println("context listener 인스턴스 생성");
    }

    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
        /* context에 attribute가 추가될 때 동작 */
        System.out.println("context attribute added!!");
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
        /* context에 attribute가 제거될 때 동작 */
        System.out.println("context attribute removed!!");
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
        /* context에 attribute가 변경될 때 동작 */
        System.out.println("context attribute replaced!!");
    }

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        /* context가 최초 생성될 때 생성자 호출 이후 동작하는 메소드 */
        System.out.println("context init!!");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        /* context가 소멸할 때 동작 */
        System.out.println("context destroy!!");
    }

}

 

2. Session Listener

  • HttpSessionListener와 HttpSessionAttributeListener
import jakarta.servlet.annotation.WebListener;
import jakarta.servlet.http.HttpSessionActivationListener;
import jakarta.servlet.http.HttpSessionAttributeListener;
import jakarta.servlet.http.HttpSessionBindingEvent;
import jakarta.servlet.http.HttpSessionBindingListener;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;

@WebListener
public class SessionListenerTest implements HttpSessionListener, HttpSessionAttributeListener {

    public SessionListenerTest() {
        /* context가 로드될 때 인스턴스 생성 */
        System.out.println("session listener 인스턴스 생성");
    }

    public void sessionCreated(HttpSessionEvent se)  {
        /* 세션이 생성될 때 동작*/
        System.out.println("session created!!");
        System.out.println("생성된 session id : " + se.getSession().getId());
    }

    public void sessionDestroyed(HttpSessionEvent se)  {
        /* 세션이 만료될 시 동작 */
        System.out.println("session destroyed!!");
    }

    public void attributeAdded(HttpSessionBindingEvent se)  {
        /* session에 attribute가 추가될 때 동작 */
        System.out.println("session attribute added!!");
        System.out.println("session에서 추가된 attr : " + se.getName() + ", " + se.getValue());
    }

    public void attributeRemoved(HttpSessionBindingEvent se)  {
        /* session에 attribute가 추가될 때 동작 */
        System.out.println("session attribute removed!!");
        System.out.println("session에서 제거된 attr : " + se.getName() + ", " + se.getValue());
    }

    public void attributeReplaced(HttpSessionBindingEvent se)  {
        /* session의 attribute가 갱신될 때 동작 */
        System.out.println("session attribute replaced!!");
        System.out.println("session에서 수정된 attr : " + se.getName() + ", " + se.getValue());
    }

}

 

  • HttpSessionBindingListener
import jakarta.servlet.http.HttpSessionBindingEvent;
import jakarta.servlet.http.HttpSessionBindingListener;

public class UserDTO implements HttpSessionBindingListener {

    private String name;
    private int age;

    public UserDTO() { }
    public UserDTO(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

    @Override
    public String toString() {
        return "UserDTO [name=" + name + ", age=" + age + "]";
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        /* 해당 클래스로 만든 인스턴스가 세션에 바인딩(값이 추가) 되는 경우 동작 */
        System.out.println("value bound!!");

    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        /* 해당 클래스로 만든 인스턴스가 세션에 바인딩 해제(값 제거 혹은 세션 만료) 되는 경우 동작 */
        System.out.println("value unbounded!!");
    }

}

 

3. Request Listener

  • ServletRequestListener와 ServletRequestAttributeListener
import jakarta.servlet.ServletRequestAttributeEvent;
import jakarta.servlet.ServletRequestAttributeListener;
import jakarta.servlet.ServletRequestEvent;
import jakarta.servlet.ServletRequestListener;
import jakarta.servlet.annotation.WebListener;

@WebListener
public class RequestListenerTest implements ServletRequestListener, ServletRequestAttributeListener {

    public RequestListenerTest() {
        /* context가 로드될 떄 생성자 호출하여 인스턴스 생성 */
        System.out.println("request listener 인스턴스 생성");
    }

    public void requestDestroyed(ServletRequestEvent sre)  {
        /* request가 소멸될 때 호출 */
        System.out.println("request destoryed!!");
    }

    public void attributeRemoved(ServletRequestAttributeEvent srae)  {
        /* request에 attribute가 제거될 때 호출 */
        System.out.println("request attribute removed!!");
    }

    public void requestInitialized(ServletRequestEvent sre)  {
        /* request가 생성될 때 호출 */
        System.out.println("request init!!");
    }

    public void attributeAdded(ServletRequestAttributeEvent srae)  {
        /* request에 attribute가 추가될 때 호출 */
        System.out.println("request attribute added!!");
    }

    public void attributeReplaced(ServletRequestAttributeEvent srae)  {
        /* request에 attribute가 갱신될 때 호출 */
        /* (참고) org.apache.catalina.ASYNC_SUPPORTED라는 attribute가 자동 수정되어 한번 호출됨
         *       서블릿 3.0에서부터 비동기 방식의 요청 처리를 지원한다는 내용 */
        System.out.println("request attribute replaced!!");
        System.out.println(srae.getName() + ", " + srae.getValue());
    }

}
728x90
반응형
728x90
반응형

[Servlet] Servlet에서 Request와 Response를 가공하는 가장 좋은 방법 | Wrapper 클래스

1. Servlet Filter

1. Servlet Filter 개요

1. Servlet Filter란

  • jakarta.servlet.Filter Interface를 상속 받아 구현하는 Class이다.
  • HTTP 요청과 응답 사이에서 전달되는 데이터를 가로채어, 서비스에 맞게 변경하고 걸러내는 필터링 작업을 수행한다.

Servlet 사진 1

  • 필터 설정에 따라 해당하는 요청 및 응답 시에 반드시 거쳐야 하며, 비밀번호 암호화 처리, 인코딩 설정 등 공통 관리에 해당하는 기능을 수행할 수 있다.
  • 필터는 인증 필터, 압축 필터, 리소스 접근 트리거 이벤트 필터, 로깅 필터, 이미지 변환 필터, 토크나이져 필터 등 다양하게 활용 가능하다.

 

2. Servlet Filter 처리 내용

  • Request에 대한 처리
    • 보안 관련 사항
    • 요청 header와 body 형식 지정
    • 요청에 대한 log 기록 유지
  • Response에 대한 처리
    • 응답 stream 압축
    • 응답 stream 내용 추가 및 수정
    • 새로운 응답 작성
    +@ : 여러 가지 필터를 연결(= chain, 서로 호출)하여 사용할 수 있다.

 

3. Servlet Filter 동작 구조

Servlet 사진 2

  • 요청 및 응답에 따른 서블릿 수행 전후에 지정한 필터를 거치며 데이터를 가공하는 역할을 한다.

 

4. Servlet Filter 내부 동작

Servlet 사진 3

  • 서블릿의 실행 전후에 동작하므로 서블릿의 service() 메소드 실행 전후에 작동한다.
  • 필터가 여러 개일 경우 stack 방식으로 순차적으로 수행된다.

 

5. Filter Chain (Interface)

  • Filter를 여러 개 사용하는 경우, Filter Chain으로 동작시킬 수 있다.

Servlet 사진 4

  • Chain처럼 서로 연결되어 있는 Filter를 doFilter() 메소드를 이용하여 순차적으로 실행시키는 인터페이스이다.
  • doFilter() 메소드는 chain으로 연결되어 있는 다음 필터 또는 서블릿을 실행하는 메소드이다.
doFilter(ServletRequest req, ServletResponse res);
  • 마지막 필터가 실행된 후에는 service() 메소드를 실행시켜 서블릿의 메소드(= doGet(), doPost())를 실행한다.

 

2. Servlet Filter 사용

1. DD 설정 (= web.xml 설정)

  • Filter를 등록한다.
<filter>
	<filter-name>Filter 설정명</filter-name>
	<filter-class>Filter 구현 Class명</filter-class>
	<init-param> // filter에서 사용한 값 설정
		<param-name>초기값 설정명</param-name>
		<param-value>초기 설정값</param-value>
	</init-param>
</filter>

 

  • url 패턴과 Filter를 mapping한다.
<filter-mapping>
	<filter-name>등록된 Filter명</filter-name>
	<url-pattern>요청할 페이지 형식</url-pattern>
</filter-mapping>

 

  • Filter를 적용할 서블릿을 지정하여, 서블릿과 Filter를 mapping한다.
<filter-mapping>
	<filter-name>등록된 Filter명</filter-name>
	<servlet-name>적용할 Servlet명</servlet-name>
</filter-mapping>

 

2. @WebFilter Annotation 설정

  • Filter 인터페이스를 구현한 클래스 상단에 @WebFilter(url-pattern) 어노테이션을 추가한다.
@WebFilter("/first/*")
public class FirstFilter implements Filter {
	필터 동작 내용
}

 

3. Filter Interface method

  • init (FilterConfig config);
    • 웹 컨테이너가 Filter를 호출하면, init method가 호출되어 Filter 객체를 생성하며 초기화한다.
    • 매개변수 FilterConfig는 web.xml에 있는 <filter>정보를 가지고 있다.
  • doFilter (ServletRequest req, ServletResponse res, FilterChain chain);
    • Filter가 수행될 때 구동하는 method로, 요청 객체와 응답 객체를 사용해 일련의 작업을 수행한 뒤, chain을 통해 가공된 값을 목적지로 전송한다.
  • doFilter (ServletRequest req, ServletResponse res, FilterChain chain);
    • Filter가 수행될 때 구동하는 method로, 요청 객체와 응답 객체를 사용해 일련의 작업을 수행한 뒤, chain을 통해 가공된 값을 목적지로 전송한다.

 

4. Filter Class 작성

public class Class명 implements Filter {
	@Override
	public void init(FilterConfig config) throws ServletException { 
		(Filter 호출 시 작업 설정)
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { 
		(Filtering 작업할 내용)
	}

	@Override
	public void destroy() { 
		(삭제 시 작업 설정)
	}
}

 

5. Filter Class 활용 예시

  • 공통적인 인코딩 설정을 할 CharsetEncodingFilter Class를 작성한다.
import java.io.IOException;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;

public class EncodingFilter implements Filter {

    private String encodingType;

    public void destroy() {}

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest hrequest = (HttpServletRequest) request;
        if("POST".equals(hrequest.getMethod())) {
            request.setCharacterEncoding(encodingType);
        }

        chain.doFilter(request, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {
        /* xml 팡리에 init-param을 지정하여 fConfig로 값을 꺼내 사용 */
        encodingType = fConfig.getInitParameter("encoding-type");
    }

}

 

  • web.xml에 필터 및 초기 파라미터 값을 등록한다.
<filter>
    <filter-name>encoding</filter-name>
    <filter-class>com.section02.uses.EncodingFilter</filter-class>
    <init-param>
        <param-name>encoding-type</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
728x90
반응형
728x90
반응형

[Servlet] Servlet에서 Session과 Cookie 완벽 이해하기 | 차이점, 사용법, 예제까지 정리

 

[Servlet] Servlet에서 Session과 Cookie 완벽 이해하기 | 차이점, 사용법, 예제까지 정리

[Servlet] Servlet Forward와 Redirect의 차이점과 사용법 완벽 정리 [Servlet] Servlet Forward와 Redirect의 차이점과 사용법 완벽 정리[Servlet] Servlet 메서드와 파라미터 제대로 알기 - 초보자를 위한 웹 개발 가이

crushed-taro.tistory.com

1. Servlet Wrapper

1. Servlet Wrapper

1. Servelt Wrapper란

  • 관련 클래스(ServletRequest, ServletResponse, HttpServletRequest, HttpServletResponse)를 내부에 보관하며 해당 인터페이스를 구현한 객체를 참조하여 구현 메소드를 위임한다.
  • Java Event처리의 Adapter Class와 비슷한 기능을 한다고 볼 수 있다.
  • 사용자가 별도의 request나 response 객체를 생성하여 활용할 때 Wrapper Class를 상속하여 활용하면, 편하게 원하는 Class만 재정의하여 사용할 수 있다.

 

2. Wrapper Class

  • HttpServletRequestWrapper
    • 요청한 정보를 변경하는 Wrapper Class로, HttpServletRequest 객체를 매개로 하는 생성자를 가진다.
public SampleWrapper(HttpServletRequest wrapper) {
	super(wrapper);
}

 

  • HttpServletResponseWrapper
    • 응답할 정보를 변경하는 Wrapper Class로, HttpServletResponse 객체를 매개로 하는 생성자를 가진다.
public SampleWrapper(HttpServletResponse wrapper) {
	super(wrapper);
}

 

3. Wrapper Class 활용 예시

  • HttpServletRequestWrapper 클래스를 상속받아 비밀번호를 암호화하는 Wrapper 클래스를 작성한다.
    • 요청 받은 정보로부터 값을 꺼내올 때 암호화된 값을 꺼내오도록 request 객체 등을 자체적으로 조작하기 위하여 wrapper를 활용한다.
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class RequestWrapper extends HttpServletRequestWrapper {

    /* 부모에 기본생성자가 존재하지 않으므로 request를 전달해주는 생성자 필요 */
    public RequestWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getParameter(String key) {

        String value = "";
        if("password".equals(key)) {
            /* spring-security-crypto 라이브러리 사용 */
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            value = passwordEncoder.encode(super.getParameter(key));
        } else {
            value = super.getParameter(key);
        }

        return value;
    }

}

 

  • 위 에서 작성한 Wrapper를 적용하는 필터 클래스를 작성한다.
import java.io.IOException;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;

@WebFilter("/member/*")
public class PasswordEncryptFilter implements Filter {

    public void destroy() {}

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest hrequest = (HttpServletRequest) request;
        RequestWrapper wrapper = new RequestWrapper(hrequest);

        chain.doFilter(wrapper, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {}

}

 

  • 요청을 처리하는 서블릿에서 확인하면 암호화된 값이 현출되는 것을 확인할 수 있고, BCryptPasswordEncoder 클래스의 matches() 메소드를 통해 암호화된 값이 특정 값과 일치하는지 확인할 수 있다.
@WebServlet("/member/regist")
public class RegistMemberServlet extends HttpServlet {

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

        String password = request.getParameter("password");
        System.out.println("userPwd : " + password);

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        System.out.println(passwordEncoder.("pass01", password));

    }

}

 

4. (참고) 암호화 및 Bcrpt

Servlet 사진

  • 위 그림처럼 중간에 패킷 정보를 빼내어 가져가는 해킹 기법인 ‘패킷스니핑’에 대비하여 개인 정보 등 보안에 민감한 데이터에는 암호화 처리가 필요하다.
    • 암호화하면 패킷스니핑으로 해킹해도 복호화하지 못하는 이상 크게 의미가 없기 때문이다.
    • 데이터베이스 해킹에 대비해 DB 저장 시에도 암호화된 데이터를 넣어야 한다.
  • 서버는 양방향 암호화 처리를 한다.
    • 암호화란 평문을 다이제스트(= 기존 문자열을 변환한 일정 길이의 문자열)로 변경하는 것이고, 복호화는 다이제스트를 다시 평문으로 변경하는 것이다.
    • 이때 암호화는 가능하지만 복호화는 불가한 것이 단방향 암호화이고, 암호화와 복호화 모두 가능한 것이 양방향 암호화이다.

저장한 서버도 관리자도 알아서는 안되는 고객의 개인 정보 등이 있을 수 있으므로 데이터베이스는 단방향 암호화 처리를 한다.

💡 BCrypt 암호화
비밀번호를 데이터베이스에 저장할 목적으로 설계된 암호화 알고리즘이다.
랜덤 솔팅 기법을 적용한 다이제스트 생성을 지연시킨 단방향 해시 암호화 알고리즘이다.
암호화는 가능하나 복호화가 불가능한 높은 수준의 암호화 알고리즘이다.
  • 해시 알고리즘이란 어떤 메시지를 넣더라도 해시 함수를 통과하면 동일한 길이의 랜덤한 문자열이 반환되는 것으로, 빠른 속도로 다이제스트 생성이 가능하다.
    1. 무차별 대입 → 모든 경우의 수에 대해 다이제스트를 생성해 맞춰보면서 패턴 탐색
    2. 사전식 대입 → 사전 속 단어를 다이제스트로 변경해 다이제스트와 비교해 패턴 탐색
  • 이러한 해시 알고리즘은 다이제스트 생성 방식이 동일하므로 아래 두 가지 방법으로 패턴만 알아내면 복호화가 가능해진다.
  • 따라서 위와 같은 패턴 탐색을 방지하고자 Bcrypt 암호화에서 적용한 salting 기법은 원문만 암호화하지 않고 지정한 다른 글자(= salt값)를 붙여 암호화하는 것이고, BCrypt는 암호화할 때마다 랜덤한 salt값을 이용한다.
728x90
반응형
728x90
반응형

[Servlet] 초보자를 위한 Servlet Mapping과 생명주기, 초기 설정법 총정리

 

[Servlet] 초보자를 위한 Servlet Mapping과 생명주기, 초기 설정법 총정리

[Servlet] Servlet 기초 완벽 가이드 | 동작 방식과 DD(web.xml) 설정법 [Servlet] Servlet 기초 완벽 가이드 | 동작 방식과 DD(web.xml) 설정법[Servlet] 초보 개발자를 위한 Servlet 이해하기 | 웹 서버와 클라이언트

crushed-taro.tistory.com

1. Servlet Method

1. HTTP 데이터 전송 방식

1. 데이터 전송 구조

Servlet 메서드 사진

  • 브라우저에서 요청 정보를 HTTP 객체에 담아 전송한다.
    • 요청과 응답을 주고받는 패킷은 요청 정보와 응답 정보를 직렬화한 Byte단위의 문자열 데이터로, 인코딩과 디코딩이 필요하다.
  • 전달받은 HTTP객체를 서버(=Tomcat)이 해석하여 요청을 처리할 서블릿을 호출한다. 서블릿의 service() 메소드에서는 request, response 요청 정보를 가지고 처리 로직을 거쳐 응답한다.
    • HttpServletRequest는 ServletRequest 타입을 상속 받아 구현하였으며, HTTP 프로토콜의 정보를 담고 있기 때문에 실제 사용 시에는 HttpServletRequest 타입으로 다운캐스팅해서 사용해야 한다.

 

2. 데이터 전송 방식

  • GET 방식
    • URL 주소란에 ?뒤에 데이터를 입력하는 방법, 즉 쿼리스트링(query string) 방식으로 전송한다.
    • 전송 데이터가 여러 개이면 &로 묶어서 보낸다.
      • URL 쿼리스트링 예시
      • <http://localhost:8080/sendMessage?message=abc&code=20>
    • 데이터 검색에 주로 사용되며, 데이터 크기 한계가 있고 보안에 취약하다.
  • POST 방식
    • HTTP header의 내용으로 데이터를 전송한다.
    • 전송 데이터 크기에 제한이 없고, header에 포함해 전송하므로 보안이 뛰어나다.

 

2. 데이터 전송 방식에 따른 Servlet Method

1. Servlet Method

  • 서블릿이 get/post의 두 방식 중 하나로 요청 정보를 전달 받으면, request와 response를 전달하면서 해당하는 처리 메소드(doGet() 메소드 또는 doPost() 메소드)를 호출한다.⇒ 이때, 서블릿 메소드에 대하여 반드시 ServletException 처리를 해야 한다.
  • → 즉, 톰캣 서블릿 컨테이너가 요청 url로 매핑된 서블릿 클래스의 인스턴스를 생성하여 service() method를 호출하고 HttpServlet을 상속받아 오버라이딩한 현재 클래스의 doGet() 또는 doPost() 메소드가 동적바인딩에 의해 호출된다.
  • HTML에서 method 속성을 이용해 방식을 결정하며, default는 get 방식이다.

 

2. doGet() 메서드

  • 클라이언트에서 데이터 전송 방식을 get으로 전송하면 호출되는 메소드이다.
  • GET 방식의 데이터는 HTML charset에 기술된 인코딩 방식으로 브라우저가 한글을 이해하고, ‘%’ 문자로 URLEncoder를 이용해 변환 후 url 요청으로 전송한다.
  • 이때 header의 내용은 ascii 코드로 전송되므로 어떤 언어든 서버의 설정 인코딩 방식과 맞기만 하면 해석하는데 문제가 없으므로 한글이 깨지지 않는다.
  • GET 요청은 보통 서버의 리소스를 가져오는 행위를 요청하는 http 요청 방식이기에 별도의 데이터가 필요 없어 요청 본문(= 페이로드)는 해석하지 않는다.
  • 쿼리스트링으로 보내는 데이터가 노출되므로 보안에 취약하다는 단점이 있으나, 속도면에서 더 빠르므로 검색 기능에 적합하다.

 

3. doPost() 메서드

  • 클라이언트에서 데이터 전송 방식을 post로 전송하면 호출되는 메소드이다.
  • POST 요청은 서버의 리소스에 내용을 추가하는 요청이기 때문에 요청하는 데이터가 필요한 경우가 대부분이다. 서버의 리소스에 추가해야 하는 정보를 페이로드에 key&value 방식으로 담아 전송하는데, 헤더와는 별개로 URLEncoder를 이용하지 않고 페이지 meta에 기술된 charset에 따라 UTF-8로 해석된 데이터를 서버로 전송한다.
  • 기본적으로 서버단에서 페이로드를 디코딩 하는 방식은 지정되어 있지 않고, 인코딩된 방식을 명시하지 않으면 기본 ISO-8859-1로 해석하므로 값을 꺼내오면 한글인 글자가 깨지는 현상이 발생한다.
    • request 객체의 getCharacterEncoding() 메소드를 호출해보면 null을 반환한다.
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

	System.out.println(request.getCharacterEncoding());

}
  • 따라서 parameter를 꺼내오기 전에 이를 해석할 인코딩 방식을 UTF-8로 지정해야 브라우저에서 요청한 인코딩 방식과 일치하여 한글 깨짐 현상을 막을 수 있다.
  • request의 body 영역에 데이터를 담아보내므로 데이터를 많이 보낼 수 있으나 비교적 속도가 느리다. 또한 개발자 도구를 통해 담은 데이터를 볼 수 있으므로 보안이 엄청 뛰어난 수준은 아니다.

 

2. Servlet Method Parameter

  • HttpServletRequest : 요청 객체
    • 요청 정보 접근
    • 요청 파라미터 처리
    • 헤더 정보 접근
    • 요청 바디 읽기
    • 세션 관리
  • HttpServletResponse : 응답 객체
    • 응답 상태 코드 설정
    • 응답 헤더 설정
    • 응답 바디 작성
    • 리다이렉션 처리
    • 컨텐츠 타입 설정

 

1. HttpServletRequest

1. HttpServletRequest의 역할

  • HTTP Servlet을 위한 요청 정보(request information)를 제공하는 메소드를 지정한다.
  • Interface 구현은 컨테이너가 알아서 설정하므로 메소드만 이용한다.
  • (상속 받는 인터페이스 : jakarta.servlet.ServletRequest (interface))
  • HttpServletRequest 객체의 주요 메소드
method명 내용
getParameter(String) client가 전송한 값의 명칭이 매개변수와 같은 값 가져옴
getParameterNames() client가 전송한 값의 명칭 가져옴
getParameterValues(String) client가 전송한 값이 여러 개이면 배열로 가져옴
getParameterMap() client가 전송한 값 전체를 Map방식으로 가져옴
setAttribute(String, object) request 객체로 전달할 값을 String 이름-Object 값으로 설정
getAttribute(String) 매개변수와 동일한 객체 속성 값 가져옴
removeAttribute(String) request객체에 저장된 매개변수와 동일한 속성 값 삭제
setCharacterEncoding(String) 전송 받은 request객체 값들의 CharaterSet 설정
getRequestDispatcher(String) 컨테이너 내에서 request, response객체를 전송하여 처리한 컴포넌트(jsp파일 등)를 가져옴 (forward() method와 같이 사용)

 

2. Request Header

  • General header
    • 요청 및 응답 모두에 적용되지만 최종적으로는 body에 전송되는 것과 관련이 없는 헤더이다.
  • Request header
    • Fetch될 리소스나 클라이언트 자체에 대한 상세 정보를 포함하는 헤더이다.
  • Response header
    • 위치나 서버 자체와 같은 응답에 대한 부가적인 정보를 갖는 헤더이다.
  • Entity header
    • 컨텐츠 길이나 MIME타입과 같은 엔티티 body에 대한 상세 정보를 포함하는 헤더이다.
    • (요청 응답 모두 사용되며, 메시지 바디의 컨텐츠를 나타내기에 GET요청은 해당하지 않는다.)
  • getHeader() 메소드로 확인 가능한 값
header 속성
accept 요청을 보낼 때 서버에게 요청할 응답 타입
accept-encoding 응답 시 원하는 인코딩 방식
accept-language 웅답 시 원하는 언어
connection HTTP 통신이 완료된 후에 네트워크 접속을 유지할지 결정 (기본값: keep-alive = 연결을 열린 상태로 유지)
host 서버의 도메인 네임과 서버가 현재 Listening 중인 TCP포트 지정 (반드시 하나가 존재. 없거나 둘 이상이면 404)
referer 이 페이지 이전에 대한 주소
sec-fetch-dest 요청 대상
sec-fetch-mode 요청 모드
sec-fetch-site 출처(origin)와 요청된 resource 사이의 관계
sec-fetch-user 사용자가 시작한 요청일 때만 보내짐 (항상 ?1 값 가짐)
cache-control 캐시 설정
upgrade-insecure-requests HTTP 메시지 전송 시 보안 적용
user-agent
현재 사용자가 어떤 클라이언트(OS, browser 포함)을 이용해 보낸 요청인지 명시

 

2. HttpServletResponse

1. 요청에 대한 Servlet의 역할

  1. 요청을 받는다.
    1. : HTTP method GET/POST 요청에 따라 parameter로 전달받은 데이터를 꺼내어 활용할 수 있다.
  2. 비지니스 로직을 처리(DB접속과 CRUD에 대한 로직 처리)한다.
    1. : 서비스 메소드를 호출하여 처리 로직을 수행하도록 한다.
  3. 응답한다.
    1. : 문자열로 동적인 웹(HTML 태그)페이지를 만들고 스트림을 이용해 내보내거나 응답 데이터를 담아 결과 페이지를 호출한다.

 

2. HttpServletResponse의 역할

  • 요청에 대한 처리 결과를 작성하기 위해 사용하는 객체이다.
  • Interface 구현은 컨테이너가 알아서 설정하므로 메소드만 이용한다.
    • (상속 받는 인터페이스 : jakarta.servlet.ServletResponse (interface))
  • HttpServletResponse 객체의 주요 메소드
method 명 내용
setContentType(String) 응답으로 작성하는 페이지의 MIME type을 설정
setCharacterEncoding(String) 응답하는 데이터의 CharacterSet을 지정
getWriter() 페이지에 문자 전송을 위한 Stream을 가져옴
getOutputStream() 페이지에 byte단위의 전송을 위한 Stream을 가져옴
sendRedirect(String) client가 매개변수의 페이지를 다시 서버에 요청함
💡 MIME 타입(Multipurpose Internet Mail Extensions Type)은 클라이언트(브라우저)에게 서버가 전송하는 데이터의 형식을 알려주는 표준화된 방식이다. MIME 타입은 type/subtype와 같은 형식으로 표기하며, 아래와 같이 수백 가지의 MIME 타입이 존재한다.
  • MIME 타입 목록
    • 텍스트 형식:
      • text/html: HTML 문서
      • text/plain: 일반 텍스트
      • text/css: CSS 스타일시트
      • text/csv: CSV 형식의 데이터
    • 이미지 형식:
      • image/jpeg: JPEG 이미지
      • image/png: PNG 이미지
      • image/gif: GIF 이미지
      • image/svg+xml: SVG 벡터 이미지
    • 애플리케이션 형식:
      • application/json: JSON 데이터
      • application/xml: XML 데이터
      • application/pdf: PDF 문서
      • application/zip: ZIP 압축 파일
      • application/octet-stream: 바이너리 데이터(주로 파일 다운로드에 사용)
    • 오디오/비디오 형식:
      • audio/mpeg: MP3 오디오 파일
      • audio/ogg: OGG 오디오 파일
      • video/mp4: MP4 비디오 파일
      • video/webm: WebM 비디오 파일
    • 폰트 형식:
      • font/ttf: TrueType 폰트
      • font/woff: Web Open Font Format
      • font/woff2: Web Open Font Format 2

 

3. Exception Handler

  • sendError()메소드를 사용하여 에러를 발생시킬 수 있다.
// response.sendError(에러상태 코드, "현출할 에러 메시지");
response.sendError(500, "서버 내부 오류입니다.");
  • web.xml 파일에 <error-page>를 등록하여 에러 상태코드에 해당하는 에러가 발생하면 서블릿에서 가로채도록 설정할 수 있다.
<error-page>
    <error-code>404</error-code>
    <location>/showErrorPage</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/showErrorPage</location>
</error-page>
  • 위 설정은 아래 그림처럼 원래라면 일반적인 오류 페이지가 반환될 시점에 오류 송출을 가로채 지정된 페이지로 사용자에게 반환하는 구조이다.

Servlet Method 사진

 

4. 스트림을 활용한 동적 페이지 응답

  • 응답 헤더의 타입을 설정한다.
response.setContentType("text/html");
  • 기본값은 text/plain이다.
  • HTML태그를 사용하면 요청 시 text/html도 응답으로 수락 가능하도록 헤더 설정이 되어있어 자동으로 text/html로 인식한다.

 

  • 응답할 내용의 인코딩 방식을 설정한다.
response.setCharacterEncoding("UTF-8");
  • 응답 시 별도 인코딩을 지정하지 않으면 기본으로 설정된 인코딩 방식(ISO-8859-1)을 따르므로 한글 데이터가 깨져서 현출된다.
  • 따라서 응답할 인코딩 방식이 UTF-8임을 응답 헤더에 설정하면 브라우저가 이를 해석할 때 UTF-8로 인식하고 해석하여 한글 데이터가 정상적으로 현출된다.
  • 응답 헤더와 인코딩 설정을 동시에 할 수도 있다.
response.setContentType("text/html; charset=UTF-8");

 

  • 응답을 위한 스트림을 가져와 응답을 내보낸다.
PrintWriter out = response.getWriter();
out.print(responseBuilder.toString());

 

  • 응답에 사용한 스트림을 닫는다.
out.close();
728x90
반응형
728x90
반응형

[Servlet] Servlet 기초 완벽 가이드 | 동작 방식과 DD(web.xml) 설정법

 

[Servlet] Servlet 기초 완벽 가이드 | 동작 방식과 DD(web.xml) 설정법

[Servlet] 초보 개발자를 위한 Servlet 이해하기 | 웹 서버와 클라이언트 사이 [Servlet] 초보 개발자를 위한 Servlet 이해하기 | 웹 서버와 클라이언트 사이1. Servlet1. Network 통신1. Server-client Model서버는 특

crushed-taro.tistory.com

1. Servlet

1. Servlet mapping

1. Servlet mapping 방법

  • client가 servlet에 접근할 때 원본 클래스명이 아닌 다른 명칭으로 접근할 수 있다.
  • 별칭 사용 설정 방법은 web.xml을 이용한 적용과 @annontation으로 두 가지 방법이 있다.

2. Servlet mapping 구조

  • 클라이언트가 서블릿의 url로 요청을 보내면, 톰캣이 이를 해석해 매핑된 서블릿으로 연결하는 구조이다.

Servlet 사진 3

  • mapping 경로 잘못되면 tomcat 실행 자체가 되지 않는다.
    • 정의되지 않은 경로이거나 중복된 경로를 사용하면 톰캣 서버 실행 오류가 발생한다.

3. web.xml 이용

  • xml 파일로 매핑 정보를 관리하면 한눈에 확인하고 관리할 수 있다는 장점이 있지만, 새로운 서블릿을 추가할 때마다 파일을 이동해 매핑하고 일일이 확인해야 하는 단점이 있다.
  • <servlet>과 <servlet-mapping>은 묶어서 함께 설정해야 한다.
  • 사용법
<servlet>
	<servlet-name>mapping명칭</servlet-name>
	<servlet-class>실제 클래스명</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>mapping명칭</servlet-name>
	<url-pattern>사용자 접근명칭</url-pattern>
</servlet-mapping>
  • 사용 예시
<servlet>
    <servlet-name>xmlmapping</servlet-name>
    <servlet-class>com.section01.xml.LifeCycleTestServlet</servlet-class>
    <load-on-startup>100</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>xmlmapping</servlet-name>
    <url-pattern>/xml-lifecycle</url-pattern>
</servlet-mapping>
  • <load-on-startup> 속성을 설정하고 숫자로 우선순위를 주면, 낮은 숫자를 우선하여 서버가 구동될 때 서블릿을 생성한다.

4. @annotation 이용

  • 어노테이션(Annotation)이란
    • 사전적 의미로는 ‘주석’을 뜻한다.
    • 실제로 주석처럼 쓰이며 특별한 의미, 기능을 수행하도록 하는 기술이다.
    • 프로그램에 추가 정보를 제공해주는 메타데이터로 볼 수 있다.
    • (meta data : 데이터를 위한 데이터)
  • 서블릿을 새로 개발할 때 클래스 바로 윗쪽에 어노테이션만 추가하면 되므로 간편하다는 장점이 있다.
  • 하지만 별도의 문서 등으로 관리하지 않으면 시스템의 모든 서블릿 매핑 정보를 한눈에 볼 수 없다는 단점이 있다.
  • 사용법
@WebServlet(“/mapping명칭”)
public class Servlet명 extends HttpServlet {
	(Servlet code)
}
  • 사용 예시
@WebServlet(value = "/annotation-lifecycle", loadOnStartup = 1)
public class LifeCycleTestServlet extends HttpServlet {
	(Servlet code)
}

 

2. Servlet 초기값 설정

1. ServleConfig

  • web.xml의 정보를 가져와 저장한 Interface 객체로, getServlet method로 정보가 저장된 객체를 호출할 수 있다.
  • getInitParam(“저장명”)으로 초기화된 값을 가져올 수 있다.
  • 지정된 servlet에서만 활용 가능한 초기값이며, 동적 수정이 불가한 상수값으로 보면 된다.
  • servlet이 초기화된 이후에 활용 가능하다.
<web-app>
	<servlet>
		<servlet-name>mappin명</servlet-name>
		<servlet-class>설정 Class명</servlet-class>
		<init-param>
			<param-name>저장명</param-name>
			<param-value>저장값</param-value>
		</init-param>
	</servlet>
</web-app>

 

2. ServletContext

  • ServletConfig의 초기값은 지정된 Servlet에서만 사용이 가능하나, ServletContext는 모든 Application 이 공용으로 사용하는 초기값을 설 정한다.
  • 값은 getContext().getInitParam(“저장명”)으로 호출한다.
  • <servlet> 태그 내부가 아닌 <web-app> 내부에 설정한다.
  • getContext 앞에는 getConfig() / this가 생략되어 있다.
<web-app>
	<context-param>
		<param-name>저장명</param-name>
		<param-value>설정값</param-value>
	</context-param>
</web-app>

 

3. Context Path

  • Application에 접근하는 경로로, 컨테이너에서 Application을 구분하는 root 경로라고 볼 수 있다.
  • 프로젝트의 별칭은 Tomcat 서버 설정의 server.xml 파일 내 <Context> 설정을 따른다.
  • http://localhost:[*PORT번호*]/[*프로젝트 별칭*]/[*Servlet 명*]
  • 예시: http://localhost:8080/first/test1.do

 

3. Servlet의 LifeCycle과 구동

1. Servlet LifeCycle

Servlet 사진 4

 

  1. 첫 요청이면, 객체를 생성하며 init( ) 메소드를 호출한다.
    1. init( ) : 서블릿 컨테이너에 의해 호출되며 최초 요청 시에만 실행하고 두 번째 요청부터는 호출하지 않는 메소드이다.
    2. load-on-startup 속성값을 설정할 경우, 서버가 구동할 때 객체를 생성하며 init( ) 메소드를 호출한다.
    3. 서블릿도 클래스이므로 객체를 생성해 작동한다. 따라서 서버 구동 시 서블릿을 생성하면 톰캣 최초 수행 시에는 시간이 좀 걸리지만, 클라이언트 요청에는 더 빠르게 응답할 수 있다.
  2. 이후 작업이 실행 될 때마다 service() 메소드가 요청한 HTTP Type에 따라 doGet(), doPost() method를 호출한다.
    1. service() : 서블릿 컨테이너에 의해 호출되며 최초 요청 시에는 init() 메소드 동작 이후에 동작하고, 두 번째 요청부터는 init() 메소드 호출 없이 바로 동작한다.
  3. 최종적으로 Servlet이 서비스 되지 않을 때 destroy() 메소드가 호출된다.
    1. destroy() : 컨테이너, 즉 서버가 종료될 때 또는 서블릿의 내용이 변경되어 재컴파일 될 때 호출되는 메소드로 주로 자원을 반납하는 용도로 사용한다.
Servlet의 주요 메소드는 Servlet의 Life cycle과 유사하다.

 

2. Servlet 구동

Servlet 사진 5

728x90
반응형
728x90
반응형

[Servlet] 초보 개발자를 위한 Servlet 이해하기 | 웹 서버와 클라이언트 사이

 

[Servlet] 초보 개발자를 위한 Servlet 이해하기 | 웹 서버와 클라이언트 사이

1. Servlet1. Network 통신1. Server-client Model서버는 특정 서비스를 제공하는 컴퓨터를 말하며, 클라이언트는 해당 서비스를 이용하는 사용자를 의미한다. 2. Servlet의 종류Web Server : 웹 브라우저와 HTTP 프

crushed-taro.tistory.com

 

1. Servlet

1. Servlet 개요

1. Servlet이란

  • Server + Applet의 합성어로, JAVA 언어를 이용하여 사용자의 요청을 받아 처리하고 처리 결과를 다시 사용자에게 전송하는 역할의 Class 파일을 말한다.
    • Applet = Application + let (작은) = 작은 애플리케이션
  • 웹에서 동적인 페이지를 java로 구현한 서버측 프로그램으로 보면 된다.
  • 관련 패키지와 클래스는 tomcat에서 제공하는 API문서에서 확인 가능하다.
 

Overview (Servlet 5.0 API Documentation - Apache Tomcat 10.0.27)

The jakarta.servlet.http package contains a number of classes and interfaces that describe and define the contracts between a servlet class running under the HTTP protocol and the runtime environment provided for an instance of such a class by a conforming

tomcat.apache.org

 

2. Servlet 역사

  • Java 언어의 창시자인 제임스 고슬링(James Gosling)은 1995년 자바를 발표하며 자바로 구현할 수 있는 서버 프로그래밍 기술에 대해서도 염두에 두고 있었지만, 해당 개념이 실제 구현이 가능한 정도로 제품화 되지 않은 상태였다.
  • 당시 Sun사에서는 이를 서버로 구현할 수 있는 제품이 없어 잠시 미룰 수 밖에 없었다. 즉, Java EE Platform이 제품화 되어 있지 않은 시기의 이야기인 것이다.
  • 얼마 뒤, .Java 팀의 일원이었던 파바니 디완지(Pavni Diwanji)는 자바 서버 기술에 대한 필요성을 느껴 Servlet 개념을 고안하였고, 이 개념을 토대로 프로젝트를 진행하여 Servlet 구현 및 제품화에 성공하였다.
  • 그리고 이 기술은 1997년 6월에 Servlet 1.0을 공식 발표하면서 Java EE의 제품화에 포함되었다.

 

3. Servlet 버전 변천사

Servlet 사진 1

 

4. Servlet 설계 규약

  • 모든 Servlet은 jakarta.servlet.Servlet interface를 상속 받아 구현한다.
  • Servlet 구현 시 Servlet interface와 ServletConfig interface를 jakarta.servlet.GenericServlet에 구현한다.
  • HTTP 프로토콜을 사용하는 Servlet은 HttpServlet Class를 상속 받는다.
  • (jakarta.servlet.http.HttpServlet Class는  jakarta.servlet.GenericServlet를 상속받은 Class이다.)
  • Servlet의 Exception을 처리하기 위해서는 jakarta.servlet.ServletException을 상속 받아야 한다.

 

2. Servlet 동작 구조

1. Servlet의 동작 구조

Setvlet 사진 2

 

2. Servlet Container란

  • 웹 서버 또는 응용 프로그램 서버의 일부로, 웹 서버에서 온 요청을 받아 Servlet class를 관리하는 역할(= 생명 주기 관리)을 한다.
  • Servlet에 대한 Container 설정은 Deployment Descriptor(web.xml) 파일을 이용한다.
    • 쉽게 말해 Servlet을 포함하고 있는 Container가 Servlet Container 이다.
    • Tomcat의 핵심이 바로 이 Servlet Container이다.
    • 작성한 Servlet class를 보관하고, 특정 요청에 따라 Servlet을 결정해서 객체를 생성하거나 이미 생성된 경우 service() method를 호출하여 Servlet이라는 작은 프로그램을 실행한다.
    • Tomcat을 종료하면 Servlet이 전부 소멸하기 때문에 자동으로 destroy() method를 호출한다.

 

3. Deployment Descriptor(DD)

1. 배포서술자

  • Application에 대한 전체 설정 정보를 가지고 있는 파일로, XML 형식 파일이며 요소(= 태그)로 이루어져 있다.
  • 파일 내 설정 정보를 가지고 웹 컨테이너가 Servlet을 구동한다.
    • 설정 정보
      • Servlet 정의 및 Servlet 초기화 파라미터
      • Session 설정 파라미터
      • Servlet-jsp mapping 및 MIME type mapping
      • 보안 설정
      • Welcome file list 설정
      • Error page list, resources, 환경변수
    • 파일 위치: Application 폴더 > webapp 폴더 > WEB-INF 폴더 > web.xml 파일 → MyWebApp/src/main/webapp/WEB-INF/web.xml

 

2. DD 파일 세부 내용

  • <web-app> : 루트 속성, 문법 식별자 및 버전 정보를 속성 값으로 설정
  • <context-param> : 웹 어플리케이션에서 공유하기 위한 파라미터 설정
  • <mime-mapping> : 특정 파일 다운로드 시 파일이 깨지는 현상 방지
  • <servlet>~<servlet-class> / <servlet-mapping> : Servlet mapping
  • <servlet>~<servlet-class> : 컨테이너에 Servlet 설정
    • 예시) default : 공유자 원 제공 및 디렉토리 목록 제공,
    • jsp : jsp 컴파일과 실행 담당
  • <welcome-file-list> : 시작 페이지 설정
  • <filter> : 필터 정보 등록
  • <error-page> : 에러 발생 시 안내 페이지 설정
  • <session-config> : session 기간 설정
  • <listener> : 이벤트 처리 설정 (6가지)
728x90
반응형

+ Recent posts