포스트

Day64 실습프로젝트(Web Componet)

Web Component

Web Component의 정의

  • 웹 애플리케이션 개발에 사용되는 특정 서버 측 기술들을 말한다.
  • 클라이언트의 요청을 받아 이를 처리하고 동적인 콘텐츠를 생성하여 응답을 돌려준다.

    image

Web Component의 종류

리스너

리스너의 정의와 종류

  • 리스너는 는 자바 웹 애플리케이션에서 특정 이벤트가 발생할 때 자동으로 실행되는 객체이다.
  • 리스너는 서블릿 컨테이너(Servlet Container)에서 발생하는 이벤트에 반응한다.
  • 주로 애플리케이션, 세션, 또는 요청 수준의 이벤트를 처리하는 데 사용

    image

리스너의 역할

  • 리소스 초기화 및 해제: 애플리케이션이 시작되거나 종료될 때, 데이터베이스 연결 풀을 설정하거나 해제할 때 사용된다.
  • 요청 로깅 및 감사: 들어오는 요청을 기록하거나, 요청이 처리되는 동안 발생하는 이벤트를 감시하는 데 사용된다.
  • 세션 추적: 사용자 세션의 수를 추적하거나 세션이 종료되었을 때 로그를 기록하는 용도로 사용된다.

필터

필터의 정의

  • 클라이언트의 요청이 서블릿에 도달하기 전이나 응답이 클라이언트에 전달되기 전에 특정 작업을 수행할 수 있게 해주는 컴포넌트이다.
  • 필터는 요청과 응답을 변환하거나 로깅, 인증, 인코딩 처리와 같은 전처리/후처리 작업을 담당한다.

    image

필터의 역할

  • 요청/응답 변환: 요청 객체나 응답 객체의 내용을 수정하거나 데이터 가공.
  • 인증 및 권한 확인: 사용자 인증이나 접근 권한 확인.
  • 로깅 및 감사: 요청 정보나 처리 시간 등의 기록.
  • 데이터 압축 및 인코딩: 응답 데이터를 압축하거나 인코딩 처리.

서블릿

서블릿의 정의

  • 웹 애플리케이션을 만들 때 서버 측에서 동작하는 자바 코드이다.
  • HTTP 요청을 처리하고 동적인 웹 콘텐츠를 생성하는 역할한다.
  • 웹 서버 내에서 실행되며 클라이언트의 요청을 받아 그에 대한 적절한 응답을 생성하여 반환하는 일을 한다. image

서블릿의 역할

  • HTTP 요청 처리: 클라이언트(주로 브라우저)에서 서버로 전송된 HTTP 요청을 처리한다. 주로 GET, POST, PUT, DELETE 등의 HTTP 메서드를 지원한다.
  • 동적 콘텐츠 생성: 요청에 맞춰 동적인 콘텐츠(HTML, JSON, XML 등)를 생성하고 이를 클라이언트에게 응답한다.
  • 비즈니스 로직 처리: 데이터베이스 조회, 파일 처리 등과 같은 비즈니스 로직을 수행한다.
  • 요청/응답 관리: 클라이언트의 요청 정보와 상태를 관리하고, 적절한 응답을 생성하여 클라이언트에게 전송한다.

Web Component의 활용

ServletContextListener

  • ServletContextListener는 웹 애플리케이션의 ServletContext 라이프사이클 이벤트를 감지하고 처리하는 리스너이다 .
  • ServletContext는 웹 애플리케이션 전체에 걸쳐 공유되는 설정과 리소스를 관리하는 객체로, 애플리케이션이 시작될 때 생성되고 종료될 때 소멸된다.

ServletContextListener의 메서드

  • 애플리케이션 초기화:
    • contextInitialized(ServletContextEvent sce) 메서드는 웹 애플리케이션이 시작될 때 호출되며, 애플리케이션이 실행될 때 필요한 리소스나 데이터를 초기화할 수 있다.
    • 예를 들어, 데이터베이스 연결 풀을 설정하거나 초기 설정값을 로드할 때 사용된다.
  • 애플리케이션 종료 처리:
    • contextDestroyed(ServletContextEvent sce) 메서드는 웹 애플리케이션이 종료될 때 호출되며, 이 메서드를 통해 애플리케이션 종료 시 필요한 정리 작업을 수행할 수 있다.
    • 예를 들어, 열려 있는 데이터베이스 연결을 닫거나, 로깅을 남길 때 사용된다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
          @WebListener
          public class ContextLoaderListener implements ServletContextListener {
          @Override
          public void contextInitialized(ServletContextEvent sce) {
          try {
          InputStream inputStream = Resources.getResourceAsStream("config/mybatis-config.xml");
          SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
          SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
          SqlSessionFactoryProxy sqlSessionFactoryProxy = new SqlSessionFactoryProxy(sqlSessionFactory);
            
                DaoFactory daoFactory = new DaoFactory(sqlSessionFactoryProxy);
            
                UserDao userDao = daoFactory.createObject(UserDao.class);
                BoardDao boardDao = daoFactory.createObject(BoardDao.class);
                ProjectDao projectDao = daoFactory.createObject(ProjectDao.class);
            
                ServletContext ctx = sce.getServletContext();
                ctx.setAttribute("userDao", userDao);
                ctx.setAttribute("boardDao", boardDao);
                ctx.setAttribute("projectDao", projectDao);
                ctx.setAttribute("sqlSessionFactory", sqlSessionFactoryProxy);
            
              } catch (Exception e) {
                e.printStackTrace();
              }
            
          }
          }
    

    image

리스너의 구동원리

  1. Tomcat.start() 호출 및 ServletContainer 실행:
    • Tomcat이 시작되면 내부적으로 서블릿 컨테이너가 실행된다. 이 컨테이너는 서블릿, JSP, 필터, 리스너 같은 웹 애플리케이션 구성 요소들을 관리하는 역할을 한다.
  2. 애플리케이션 초기화 및 리스너 탐색:
    • 서블릿 컨테이너는 web.xml이나 @WebListener 어노테이션을 통해 등록된 리스너들을 탐색한다.
    • @WebListener 어노테이션이 붙어 있거나 web.xml에 등록된 리스너들은 애플리케이션이 시작할 때 서블릿 컨테이너가 자동으로 인식한다.
  3. 리스너 인스턴스화 및 contextInitialized 호출:
    • 서블릿 컨테이너가 리스너 클래스의 인스턴스를 생성하고, 애플리케이션이 시작될 때 ServletContextListenercontextInitialized(ServletContextEvent sce) 메서드를 호출한다.
  4. ServletContextEvent의 생성 및 전달:
    • contextInitialized() 메서드가 호출될 때, ServletContextEvent 객체가 생성되어 전달된다. 이 객체 안에는 애플리케이션의 ServletContext가 포함되어 있다.
  5. 초기 설정 완료:
    • contextInitialized() 메서드 안에서 애플리케이션의 초기 설정 작업을 완료한다. 예를 들어, 데이터베이스 연결 풀을 설정하거나 전역 리소스를 초기화하는 작업을 수행한다.
  6. 애플리케이션 정상 실행:
    • contextInitialized() 메서드가 완료되면 애플리케이션이 정상적으로 실행을 시작한다. 이후 서블릿이나 JSP가 클라이언트 요청을 처리할 준비가 완료된다. image

서블릿 컨테이너(Servlet Container)

정의

  • 서블릿 컨테이너(Servlet Container) 는 자바 웹 애플리케이션을 실행하고 관리하는 서버 측 환경이다.
  • 서블릿 컨테이너는 서블릿, JSP, 필터 등의 웹 컴포넌트를 실행할 수 있도록 지원하며, 클라이언트의 요청을 받아 적절히 처리한 후 응답을 반환하는 역할을 한다.
  • 서블릿 컨테이너는 웹 서버와 애플리케이션 서버의 역할을 동시에 수행할 수 있으며, 클라이언트(주로 브라우저)와 서버 간의 상호작용을 관리하는 핵심적인 컴포넌트이다.

서블릿 컨테이너의 역할

  • 서블릿 관리:
    • 서블릿 컨테이너는 서블릿 클래스를 로드하고 인스턴스화한 후, 해당 서블릿의 라이프사이클(생성, 요청 처리, 종료)을 관리한다.
    • init(), service(), destroy()와 같은 서블릿의 생명주기 메서드를 호출하여 서블릿의 실행을 제어한다.
  • HTTP 요청 및 응답 처리:
    • 클라이언트로부터 들어오는 HTTP 요청을 받아 해당 요청에 맞는 서블릿을 찾아 호출한다.
    • 요청에 대한 응답을 생성하고 클라이언트에게 반환한다. 이 과정에서 요청 정보를 파싱하고, 응답을 직렬화하여 전송한다.
  • 애플리케이션 보안 관리:
    • 서블릿 컨테이너는 웹 애플리케이션의 보안을 관리한다.
  • 멀티스레드 처리:
    • 서블릿 컨테이너는 여러 클라이언트의 요청을 동시에 처리하기 위해 멀티스레드 방식으로 서블릿을 관리한다.
    • 각 요청은 개별 스레드에서 처리되며, 이를 통해 효율적으로 대규모 요청을 처리할 수 있다.
  • 필터와 리스너 관리:
    • 컨테이너는 웹 애플리케이션의 필터리스너도 관리한다. 요청 및 응답의 전처리 및 후처리를 필터로 처리하며, 애플리케이션의 라이프사이클 이벤트를 리스너로 감지하고 처리한다.

서블릿 컨테이너의 동작 원리

  1. 서블릿 로딩: 웹 애플리케이션이 시작되면 서블릿 컨테이너는 서블릿을 로드하고 인스턴스화한다. @WebServlet 어노테이션이나 web.xml에서 정의된 서블릿이 메모리에 로드된다.
  2. 요청-응답 처리: 클라이언트로부터 HTTP 요청이 오면 서블릿 컨테이너가 해당 요청을 분석하여 올바른 서블릿으로 라우팅한다. 서블릿의 service() 메서드가 호출되며, 요청에 따라 doGet(), doPost() 등의 메서드가 실행된다.
  3. 응답 전송: 서블릿이 요청을 처리하고, 생성된 응답 데이터를 클라이언트에게 반환한다. 이 과정에서 HTTP 헤더와 바디가 함께 전송된다.
  4. 서블릿 종료: 웹 애플리케이션이 종료되거나 서블릿 컨테이너가 중지되면 서블릿의 destroy() 메서드가 호출되어 서블릿 인스턴스가 메모리에서 해제된다.

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 톰캣 서버를 구동시키는 객체 준비
    Tomcat tomcat = new Tomcat();

    // 서버의 포트 번호 설정
    tomcat.setPort(8888);

    // 톰캣 서버를 실행하는 동안 사용할 임시 폴더 지정
    tomcat.setBaseDir("temp");

    // 톰캣 서버의 연결 정보를 설정
    Connector connector = tomcat.getConnector();
    connector.setURIEncoding("UTF-8");

    // 톰캣 서버에 배포할 웹 애플리케이션의 환경 정보 준비
    // => 정적 웹 자원의 경로
    StandardContext ctx = (StandardContext) tomcat.addWebapp(
        "/", // 컨텍스트 경로(웹 애플리케이션 경로)
        new File("src/main/webapp").getAbsolutePath() // 웹 애플리케이션 파일이 있는 실제 경로
    );
    ctx.setReloadable(true);

    // 웹 애플리케이션 기타 정보 설정
    WebResourceRoot resources = new StandardRoot(ctx);

    // 웹 애플리케이션의 서블릿 클래스 등록
    // => 동적 웹 자원의 경로
    resources.addPreResources(new DirResourceSet(
        resources, // 루트 웹 애플리케이션 정보
        "/WEB-INF/classes", // 서블릿 클래스 파일의 위치 정보
        new File("build/classes/java/main").getAbsolutePath(), // 서블릿 클래스 파일이 있는 실제 경로
        "/" // 웹 애플리케이션 내부 경로
    ));

    // 웹 애플리케이션 설정 정보를 웹 애플리케이션 환경 정보에 등록
    ctx.setResources(resources);

    // 톰캣 서버 구동
    tomcat.start();

    // 톰캣 서버를 구동한 후 종료될 때까지 JVM을 끝내지 말고 기다린다.
    tomcat.getServer().await();

    System.out.println("서버 종료!");


서블릿으로 리스트 만들기

  • 서블릿의 구조는 다음과 같다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@WebServlet("/user/list")
public class UserListServlet implements Servlet {
  @Override
  public void init(ServletConfig config) throws ServletException {
    // 서블릿이 작업할 사용할 의존 객체를 준비하는 일을 이 메서드에서 수행한다.
  }

  @Override
  public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    // 웹브라우저에서 이 서블릿을 실행해달라고 요청이 들어오면 이 메서드가 호출된다.
  }

  @Override
  public ServletConfig getServletConfig() {
    // 서블릿의 정보를 조회할 때 사용할 ServletConfig 객체를 리턴해 준다.
    return this.config;
  }

  @Override
  public String getServletInfo() {
    // 서블릿 컨테이너 관리 화면에서 서블릿을 정보를 출력할 때 이 메서드가 호출된다.
    return "";
  }

  @Override
  public void destroy() {
    // 서블릿 컨테이너가 종료되기 전에 해제할 자원이 있다면 이 메서드에서 수행한다.
  }
}

image image

서블릿 구현체의 메서드

1. init(ServletConfig config)

  • 기능: 서블릿이 최초로 로드될 때 호출되는 초기화 메서드이다. 서블릿 인스턴스가 생성된 후 초기화 작업을 수행하는 데 사용된다.
  • 매개변수:
    • ServletConfig config: 서블릿의 초기화 파라미터와 서블릿 환경에 대한 정보를 담고 있는 객체. 이를 통해 서블릿 컨텍스트에 접근하거나 서블릿 초기화 파라미터를 읽을 수 있다.

2. service(ServletRequest req, ServletResponse res)

  • 기능: 클라이언트의 요청을 처리하고, 응답을 생성하는 메서드이다. 서블릿이 클라이언트로부터 요청을 받을 때마다 호출되며, GET, POST 등의 요청 방식에 따라 적절한 처리를 수행한다.
  • 매개변수:
    • ServletRequest req: 클라이언트로부터 전달된 요청 데이터를 담고 있는 객체. 요청 파라미터, 헤더 정보 등을 추출할 수 있다.
    • ServletResponse res: 서버에서 클라이언트로 보낼 응답 데이터를 담는 객체. 응답의 콘텐츠 타입, 출력 스트림 등을 설정할 수 있다.

3. ServletConfig getServletConfig()

  • 기능: 서블릿의 설정 정보를 담고 있는 ServletConfig 객체를 반환하는 메서드이다. 이를 통해 서블릿이 속한 컨텍스트나 초기화 파라미터에 접근할 수 있다.
  • 매개변수: 없음.

4. String getServletInfo()

  • 기능: 서블릿에 대한 정보를 반환하는 메서드이다. 이 메서드는 주로 서블릿의 설명, 버전 정보, 저작자 정보를 제공하는 데 사용된다.
  • 매개변수: 없음.

5. void destroy()

  • 기능: 서블릿이 종료되기 전에 호출되는 메서드이다. 서블릿이 제거되거나 서버가 종료될 때 리소스를 정리하거나, 열린 연결을 닫는 등의 작업을 수행한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@WebServlet("/user/list")
public class UserListServlet implements Servlet {
  private ServletConfig config;
  private UserDao userDao;

  public UserListServlet(UserDao userDao) {
    this.userDao = userDao;
  }

  @Override
  public void init(ServletConfig config) throws ServletException {
    this.config = config;
    userDao = (UserDao) config.getServletContext().getAttribute("userDao");
  }

  @Override
  public void service(ServletRequest req, ServletResponse res)
      throws ServletException, IOException {

    res.setContentType("text/html;charset=UTF-8");
    PrintWriter out = res.getWriter();
    out.println("<!DOCTYPE html>");
    out.println("<html>");
    out.println("<head>");
    out.println("    <meta charset='UTF-8'>");
    out.println("    <title>Title</title>");
    out.println("</head>");
    out.println("<body>");

    try {
      out.println("<h1>회원 목록</h1>");

      out.println("<table>");
      out.println("    <thead>");
      out.println("    <tr><th>번호</th><th>이름</th><th>이메일</th></tr>");
      out.println("    </thead>");
      out.println("    <tbody>");

      for (User user : userDao.list()) {
        out.printf("    <tr><td>%d</td><td>%s</td><td>%s</td></tr>", user.getNo(), user.getName(),
            user.getEmail());
      }
      out.println("    </tbody>");
      out.println("</table>");

    } catch (Exception e) {
      out.println("목록 조회 중 오류 발생!");
    }
    out.println("</body>");
    out.println("</html>");
  }

  @Override
  public ServletConfig getServletConfig() {
    return this.config;
  }

  @Override
  public String getServletInfo() {
    return "회원 목록조회";
  }

  @Override
  public void destroy() {

  }
}


문자열 출력시 글자 깨짐

서블릿에서 글자가 깨지는 이유

  • 서블릿은 기본적으로 UTF-16BE 인코딩을 사용한다.
  • 인코딩하게되면 ISO-8859-1(아스키코드)로 변환한다.
  • 한글은 없는 문자로 적용되어 ?로 출력된다.

    image

  • 서블릿에서 Response에 대한 인코딩 설정을 해야한다.
  • ServletResponse.setContentType를 통해 UTF-8로 변환해야한다.

    image

    1
    
    ServletResponse.setContentType("MIME타입;문자집합")
    

    image

웹브라우저에서 글자가 깨지는 이유

  • 브라우저에서도 문자인코딩을 설정하지 않으면, ISO-8859-1 인코딩 한다.
  • 서블릿과 동일하게 오류가 나오지만, 브라우저상에는 뷁?뷁?으로 표시 된다.

    image

인코딩설정 방법

  • 서블릿을 통해 동적으로 HTML을 생성하면, Res.setContentType으로 설정해준다.
  • 이 경우 HTML에 메타데이터를 입력하지 않아도 자동으로 메타데이터에 인코딩 설정이 된다.
  • 정적인 HTML의 경우는 meta데이터에서 인코딩을 설정한다. image

HTML 연결구조 만들기

HTML의 구동원리

image

GenericServlet 활용

GenericServlet이란?

정의

GenericServlet은 서블릿 API에서 제공하는 추상 클래스이다. 이 클래스는 Servlet 인터페이스를 구현하고, HTTP 외의 프로토콜을 사용하는 서블릿을 만들 때 사용된다. GenericServlet은 서블릿 프로토콜에 종속되지 않고, 다양한 프로토콜에 적용될 수 있도록 설계되어 있다.

역할

  1. Servlet 인터페이스 기본 구현 제공: GenericServletServlet 인터페이스의 기본적인 메서드를 구현하고, 개발자가 필요한 메서드만 오버라이드해서 사용할 수 있게 한다. 개발자는 service() 메서드를 구현하면 된다.
  2. 프로토콜 독립적 서블릿 지원: GenericServlet은 HTTP와 같은 특정 프로토콜에 종속되지 않고, 다양한 프로토콜에서 사용될 수 있는 서블릿을 작성하는 데 도움이 된다.

  3. 필수 메서드 구현: 개발자는 service() 메서드를 구현해서 클라이언트 요청을 처리하면 된다.

주요 메서드

  1. init(ServletConfig config): 서블릿이 초기화될 때 호출된다. 개발자가 서블릿 초기화 작업을 여기서 구현할 수 있다.

  2. service(ServletRequest req, ServletResponse res): 클라이언트의 요청을 처리하고 응답을 생성한다. 이 메서드를 오버라이드해서 개발자는 서블릿의 핵심 로직을 구현하면 된다.

  3. getServletConfig(): 서블릿의 설정 정보를 반환한다. 이 메서드를 사용해 ServletConfig 객체에 접근할 수 있다.

  4. getServletInfo(): 서블릿에 대한 정보를 반환한다. 서블릿에 대한 설명을 제공하는 데 사용된다.

  5. destroy(): 서블릿이 종료될 때 호출된다. 서블릿이 종료되기 전에 정리 작업을 수행하면 된다. image

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.