Servlet & JSP

VenusIM·2022년 2월 4일
0

BitCamp 수료

목록 보기
2/4

Servlet & JSP를 접하기 전에

JAVA WEB 개발 환경 구축에 대해 먼저 살펴보겠다.

WEB이란 가장 많이 사용하는 Client/Sever Program의 일종이다.

⇒ Client/Server는 누가 요구하고 응답을 주냐 에 따라 용도 상으로 결정된다.

  • Client : Request하는 쪽 ex) JDBC Client
  • Sever : Request에 대한 Response하는 쪽 ex) DBMS Server

💡 Client Sever의 개수에 따른 명칭
2개 ⇒ Two tier Architecture
3개 ⇒ Three tier Architecture
4개 이상 ⇒ n tier Architecture

Client / Server Program의 3가지 요소

  • Unique한 Identifier ex) IP , 우리 집에 택배가 왔다.
  • 어떤 Application으로 갈 것인지 ex) Port 누구의 택배인지 확인 후 당사자에게
  • Protocol 통신 규약

Client : Request를 하는 Application
Browser (다양한 제품)

  • WEB이라는 C/S에서 URL을 통해 Request해 주는 Client APP
  • HTML을 Parsing해서 내용을 Display해 주는 역할

Server : Response를 하는 Application

  • Web Server (다양한 Web Sever중 무료로 제공해 주는 Apache 사용)
  • WEB 이라는 C/S에서 resource를 관리해주고 response해 주는 Server App

[Apache의 htdocs Directory에서 Resource 관리]

💡 Apache License의 기본

  • Open Source이다.
  • 기능을 추가하여 상용화 해도 좋지만, 참조 문헌 작성 필히 해라.

JAVA CLASS의 분류

APP / BEAN /

APLETSERVLET[Aplet을 보완한 기술]← JSP [Servlet을 Extends한 기술]

Web Server ⇒ Apache 이용
웹 브라우저와 같은 클라이언트로부터 HTTP 요청을 받아들이고, HTML 문서와 같은 웹 페이지를 반환하는 컴퓨터 프로그램

URL을 통해 화면을 제공해 주며, 80번 port를 사용한다.

Servlet

Java class의 일종으로, java.io.* API를 이용하여 Browser에게 html을 주는 기술

  • Servlet Container[=Engine] ⇒ Servlet이라는 Bean을 구동 시키기 위한 App

JSP [Java Server Page]

Servlet을 Extends한 것

  • JSP Container[=Engine] ⇒ JSP라는 Bean을 구동 시키기 위한 APP

WAS [Web Application Server]

WAS는 WebServer, Web Container[Servlet Container, JSP Container 등]을 기본적으로

제공해주는 Program의 일종이다.

  • 우리가 Web Container의 Spec을 알고 있다면 WAS의 종류와 상관없이 해당 Spec을 지원하는 버전 어떤 것이라도 사용 가능하다는 Polymorphism이 적용된다.

  • 추가적으로 JRE를 자체적으로 가지고 있는 WAS가 있는 반면, 우리가 사용하는 WAS인 TOMCAT은 JRE를 제공하지 않아 JRE Platform을 따로 설치해 줘야 한다. 긍정적인 시점에서 본다면 JRE가 없기 때문에 프로그램이 가볍다고 볼 수 있다.


WAS마다 resource의 위치가 다르면 종속적이기 때문에 각종 resource의 위치를 폴더로서 표준화

  • Servlet Directory = Web Application = Servlet Context라고 명칭한다.


위와 같은 표준화 된 폴더 구조는 .war[Web Archaive]라는 확장자로 압축하여 동일한 spec을 지원하는 WAS라면 copy&paste로 WAS에서 ~.war의 내용을 읽어올 수 있다.

또한 표준화 된 폴더 구조의 ClassPath Root는 Classes이다. 이러한 Classes 내에서 package로서의 구조로 구성할 수 있다.

💡 Enterprise Edition의 설치 없이 어떻게 우리가 Servlet과 JSP API를 이용 가능한 것일까?

  • Java 진영에서 Standard Edition에 추가적인 기능이 더해진 Enterprise Edition의 버전에 따라 Servlet과 JSP의 spec이 결정되며, was에서 필요로 하는 spec만 알고 있다면 was에 의존적이지 않고 어떤 제조사의 WAS던지 사용할 수 있다는 polymorphism을 지원한다.
  • 우리가 이용하는 TOMCAT의 경우 spec에 맞는 servlet. jar를 제공해 준다.

XML [EXtensible Markup Language]

  • server.xml 이름 그대로 server에 대한 설정하는 XML 형식의 파일이다.
  • web.xml
    • Web Application의 Deployment Descriptor(배포서술자, DD파일)로서 XML 형식의 파일
    • 모든 Web application은 반드시 하나의 web.xm l파일을 가져야 함
    • 위치 : WEB-INF 폴더 아래
    • web.xml 파일의 설정들은 Web Application 시작시 메모리에 로딩됨. (수정을 할 경우 web application을 재시작 해야함.)

    <servlet> //==> 서블릿 객체 설정
    	<servlet-name>  객체의 이름  </servlet-name>
    	<servlet-class> 객체를 생성할 클래스 </servlet-class>
    </servlet>
    
    <servlet-mapping>
    	<servlet-name> 이름 </servlet-name> //==> 일할 서블릿 객체의 이름
    	<url-pattern>패턴</url-pattern> //==> 클라이언트가 요청할 url 패턴
    </servlet-mapping>

TOMCAT

TOMCAT에서는 exe파일, window의 비트 별 zip file을 제공한다.

exe파일을 이용한 wizard 세팅도 가능하지만,

zip파일로서 제공하는 tomcat_home의 bin folder 하위에 있는 startup.dat와 shutdown.dat로 웹 서버 구동과 멈춤이 가능하다.

또한 startup.dat가 실행되면서 많은 개발자들이 설정하는 java_home을 찾아 JRE path를 자동 인식한다. 그러나 지원하는 JRE 버전과 java_home의 path의 버전이 다르다면 Error가 발생한다.

💡 apache-tomcat.exe로 설치 시

  • ORACLE과 TOMCAT을 함께 사용할 때 PORT의 충돌에 유의하자!
    Oracle을 설치하면 8080 port를 사용하는 web server가 설치된다.
  • TOMCAT 또한 web server를 포함하고 있고 8080 port를 이용하기 때문에 그대로 설치를 한다면 충돌의 오류가 발생한다.
  • Oracle DBMS나 Tomcat의 web server port를 변경해 주어야 한다.
    Tomcat의 port 변경은 간단하지만, Oracle의 경우 아래와 같은 명령어로 변경해 준다.
    EXEC DBMS_XDB.SETHTTPPORT(포트번호)
  • 추가적으로 JRE의 PATH를 설정해 주어야 한다.

Container의 역할

servlet을 instance 생성하여 method()를 실행해 주는 역할을 한다.

모든 method를 인식할 수 있는 것은 아니다. 우리가 직접 생성한 instance의 내용을 알고 우리가 호출 하는 것이 아닌 Container라는 App에서 처리하는 것이기 때문에Container가 인식할 수 있는 약속에 의한 method()를 정의해 주어야 한다.

약속에 의한 method()의 구조는 아래와 같다.

  • init() ⇒instance 생성을 생각하면 되고, 단 한번 호출되며, 초기화 작업을 해주며 instance null처리를 하지 않는다. Client 요청에 따라 Servlet 생성되고, Sevlet이 memory로 load될 때 실행 (web.xml 기준)
  • service() ⇒ init()에서 instance 생성해 주었으니, method()만 계속해서 호출 후 response해 준다. Servlet이 수신한 모든 요청에 대해 실행 (각 Thread 당 실행)
  • destroy() ⇒ Servlet class 수정 보완 후 compile을 할 경우 호출되며, init이 소멸한다.

여기서 Java의 장점 몇 가지를 살펴볼 수 있다.

  1. client로 부터 request가 들어오면 process로 매번 대응하는 것이 아닌, thread가 호출된다.

  2. thread로 대응하기 때문에 start()로 인하여 run()이 호출되며 init() runnable에 올라간다.

    모든 작업이 끝나면 소멸하기 때문에 위와 같이 단 한번 호출되어 효율적이다.

    Thread의 동작 방식은 절차 은닉이다.

  1. Web Server는 HTTP 요청을 Web Container(Servlet Container)에게 위임
    • web.xml ⇒ 어떤 URL과 Mapping되어 있는지 확인
    • Client(browser)의 요청 URL을 보고 해당 Servlet을 실행(Thread 생성)
  2. Web Container는 service() method 호출 전에 Servlet 객체 메모리 적재
    • Web Container는 Servlet 찾고 컴파일(.class 파일)
    • 컴파일(.class)된 파일을 메모리에 적재 (Servlet 객체 생성)
    • 메모리 적재 시, init() 메소드 실행
  3. Web Container는 요청이 올 때마다 Thread 생성
    • 각 Thread는 단일 객체에 대해 service() method 호출

할당된 Thread는 doGet() 혹은 doPost() method를 실행한다.

해당 method의 값이 Return되면 destroy() method를 실행한다.

Client의 매 요청 마다 doGet() 혹은 doPost() method를 실행한다는 것은 시스템의 overhead가 발생 가능성이 있음을 의미한다. overhead 발생을 방지하기 위해 Thread Pool을 이용한다.

HTTP Protocol의 이해

우선 HTTP와 HTTPS의 차이점을 알아보자.

  • HTTP : Hyper Text Transfer Protocol, 주로 html의 문서를 주고 받는 역할을 한다.
  • HTTPS : HTTP Security, HTTPS가 처리해준 Security된 data를 주고 받는다.

Client가 서버로 request하는 방식에는 크게 두 가지가 있다.

  1. GET 방식

    client가 get방식의 QueryString으로 request 할 경우 Server에서 header에서 encoding된 정보를 URI 후위에 붙어가기 때문에 주소 창에서 있는 그대로 확인 할 수 있다.

Server로 reqeust하는 default방식은 get방식이다.(주소창 입력으로 접속)
  1. POST 방식

    client가 post방식으로 request할 경우 Server에서 header에는 URI에 대한 정보 만을 인식하고, body에서 encoding된 정보를 처리해 주기 때문에 주소 창에서는 URI에 대한 정보만을 확인할 수 있다. 즉, 가시적인 보안을 지원한다.

Header에는 data의 limit이 있지만, body에는 limit이 없어 data량이 많은 경우 post방식을 사용하는 것이 유리하다. 
또한 대량 트래픽으로 인한 서버 다운의 우려가 있어 한계를 지정해 주어야 한다.

 

Servlet API

servlet class는 servlet container에서 실행해 주기 때문에 약속된 method name인 init(), service(), destroy()와 동일한 naming을 해주어야 하지만, 확장된 class와 interface를 hierarchy를 타고 올라가면서 해당 method를 호출할 수 있게 된다.

Overriding을 하여 우리가 원하는 방식으로 재정의 가능하나 service의 경우 재정의를 하지 않으면 아래의 방식으로 동작을 한다.

  • doGet(HttpServletRequest req, HttpServletResponse resp) html의 form이 "GET"일 경우 action과 mapping되는 servlet class에 doGet() method를 호출하기 위에 찾는데, servlet class에 overriding을 하지 않았을 경우 확장하고 있는 HttpServlet class의 doGet() method를 호출하는데, 이 method는 항상 Error를 발생 시켜 overriding을 강제적이게 한다.
  • doPost(HttpServletRequest req, HttpServletResponse resp) html의 form이 "Post"일 경우 action과 mapping되는 servlet class에 doPost() method를 호출하기 위에 찾는데, servlet class에 overriding을 하지 않았을 경우 확장하고 있는 HttpServlet class의 doPost() method를 호출하는데, 이 method는 항상 Error를 발생 시켜 overriding을 강제적이게 한다.

HttpServlet

Http에 특화된 abstract class으로,

  • GenericServlet
    init() method, destroy() method를 지원하는 abstract class이고, HttpServlet에서 abstract service method를 overriding하여 지원하고 있기 때문에 protocol과 무관하다.
    또한 새로운 기술이 나오면 init,service,destory naiming rule에 의거하여 java진영에서 GenericServlet class를 확장하여 작성 할 수 있으므로 다형성, 재사용성을 확인 할 수 있다.
  • Servlet
    servlet spec

HttpServletResponse

  • PrintWriter [ServletResponse]
    OutputStream os = res.getOutputStream();
    => HttpServletResponse의 method인 getOutputStream()return type이 
    ServletOutputStream인데, 상위 클래스인 OutputStream으로 묵시적 형변환이 일어나 가능
    
    response쪽으로 값을 처리해 주지만, 한글이 깨진다는 단점이 존재한다.
    
    ============================개선===========================
    Writer wr = new OutputStreamWriter(res.getOutputStream());
    한글은 사용 가능하지만,  한글자 씩 처리하기 때문에 비효율 적이다.
    
    ============================개선===========================
    PrintWriter pw 
    = new PrintWriter(new OutputStreamWriter(res.getOutputStream()));
    
    => PrintWriter pw = res.getWriter();
    getWriter()이 client에 문자 text를 전송해 주는 PrintWriter object를 return해 주고,
    PrintWritersetCharacterEncoding()을 통해 encoding된 문자를 
    getCharacterEncoding()return해 준다. 

HttpServletRequest

  • setCharacterEncoding() body 영역의 16진수로 encoding된 내용만 decoding해 주고 body에 대한 내용만 읽어 오기 때문에, Post방식에서만 사용 가능하다.

💡 HTML에 대한 Java Servlet
1. URL로 사용을 하게 되면 IP에 종속적이게 되어 URI를 사용한다.
2. URI를 사용하면 FIX된 구조로 Context-Root에 종속적이게 된다.
3. Relative URI를 사용 하므로서 dynamic하게 사용한다.

Enumeration

  • hasMoreElements() 남아 있으면 true return, 없으면 false return
  • nextElements() Generic object return

Model one Web Architecture

2 Layered Architecture


  1. Login → Presentation / Business Logic

  2. Login Bean → View / Business Logic

  3. Login Bean (VO/DAO) → View / Model (Value Object/ Data Access Object)

  4. Login Bean Init Param → View/Model (VO/DAO/Web.xml)

  5. Login Bean Pool → View/Model (VO/DAO → connection pool)

    ⇒ Connection에 loading 시간이 오래 걸린다.

    ⇒ Connection instance 생성하는데 오래 걸린다.

    ⇒ Connection Pool에 Connection이 필요한 만큼 미리 할당하고 Close하지 않는다.

    ⇒ Java진영에서 Spec화 하여 제공하는 Interface인 Data Source를 WAS에 등록하여 사용

    [DBCP : Data Base Connection Pool]

Request 하고 Response하는 순간 연결이 끊어져 부하가 거의 없다는 장점이 있다.

시대가 변하면서 상태 유지하는 기술 즉, 일정 시간 동안 동작에 대한 유지 기술을 필요로 한다.

쿠키와 세션을 사용하는 이유

HTTP 프로토콜의 특징이자 약점을 보완하기 위해서 사용된다.

  1. Connectionless 프로토콜 (비연결지향)

    클라이언트가 서버에 요청(Request)을 했을 때,그 요청에 맞는 응답(Response)을 보낸 후 연결을 끊는 처리방식이다.

    • HTTP 1.1 버전에서 연결을 유지하고, 재활용 하는 기능이 Default 로 추가되었다.(keep-alive 값으로 변경 가능)
  2. Stateless 프로토콜 (상태정보 유지 안함)클라이언트와 첫번째 통신에서 데이터를 주고 받았다 해도,두번째 통신에서 이전 데이터를 유지하지 않는다.

    클라이언트의 상태 정보를 가지지 않는 서버 처리 방식이다.

  • But, 실제로는 데이터 유지가 필요한 경우가 많다.

HTTP의 일종으로 사용자가 어떠한 웹 사이트를 방문할 경우,그 사이트가 사용하고 있는 서버에서 사용자의 컴퓨터에 저장하는 작은 기록 정보 파일이다.

HTTP에서 클라이언트의 상태 정보를 클라이언트의 PC에 저장하였다가필요시 정보를 참조하거나 재사용할 수 있다.

  • 쿠키 특징
    1. 이름, 값, 만료일(저장 기간 설정), 경로 정보로 구성되어 있다.
    2. 클라이언트에 총 300개의 쿠키를 저장할 수 있다.
    3. 하나의 도메인 당 20개의 쿠키를 가질 수 있다
    4. 하나의 쿠키는 4KB(=4096byte)까지 저장 가능하다.
  • 쿠키의 동작 순서
    1. 클라이언트가 페이지를 요청한다. (사용자가 웹사이트 접근)
    2. 웹 서버는 쿠키를 생성한다.
    3. 생성한 쿠키에 정보를 담아 HTTP 화면을 돌려줄 때,같이 클라이언트에게 돌려준다.
    4. 넘겨 받은 쿠키는 클라이언트가 가지고 있다가(로컬 PC에 저장)다시 서버에 요청할 때 요청과 함께 쿠키를 전송한다.
    5. 동일 사이트 재방문시 클라이언트의 PC에 해당 쿠키가 있는 경우,요청 페이지와 함께 쿠키를 전송한다.
  • 사용 예시
    1. 방문했던 사이트에 다시 방문 하였을 때 아이디와 비밀번호 자동 입력
    2. 팝업창을 통해 "오늘 이 창을 다시 보지 않기" 체크
import javax.servlet.httml.Cookie;

Cookie cookie = new Cookie("name", URLEncoder.encode("홍길동",encoding);
cookie.setMaxAge(60); //cookie 유효기간(초)
cookie.setMaxAge(-1); //cookie memory 저장
cookie.setMaxAge(0); //cookie 삭제

resquest.addCookie(cookie); //Client response instance를 사용 cookie전송

Cookie[] cookies = request.getCookies(); //cookie의 name=value 처리 변수

Session

일정 시간동안 같은 사용자(브라우저)로부터 들어오는일련의 요구를 하나의 상태로 보고, 그 상태를 일정하게 유지시키는 기술이다.

여기서 일정 시간은 방문자가 웹 브라우저를 통해웹 서버에 접속한 시점으로부터 웹 브라우저를 종료하여 연결을 끝내는 시점을 말한다.즉, 방문자가 웹 서버에 접속해 있는 상태를 하나의 단위로 보고 그것을 세션이라고 한다.

  • 세션 특징
    1. 웹 서버에 웹 컨테이너의 상태를 유지하기 위한 정보를 저장한다.
    2. 웹 서버의 저장되는 쿠키(=세션 쿠키)
    3. 브라우저를 닫거나, 서버에서 세션을 삭제했을때만 삭제가 되므로,쿠키보다 비교적 보안이 좋다.
    4. 저장 데이터에 제한이 없다.(서버 용량이 허용하는 한...)
    5. 각 클라이언트 고유 Session ID를 부여한다.Session ID로 클라이언트를 구분하여 각 클라이언트 요구에 맞는 서비스 제공
  • 세션의 동작 순서
    1. 클라이언트가 페이지를 요청한다. (사용자가 웹사이트 접근)
    2. 서버는 접근한 클라이언트의 Request-Header 필드인 Cookie를 확인하여,클라이언트가 해당 session-id를 보냈는지 확인한다.
    3. session-id가 존재하지 않는다면,서버는 session-id를 생성해 클라이언트에게 돌려준다.
    4. 서버에서 클라이언트로 돌려준 session-id를 쿠키를 사용해 서버에 저장한다.쿠키 이름 : JSESSIONID
    5. 클라이언트는 재접속 시,이 쿠키(JSESSIONID)를 이용하여 session-id 값을 서버에 전달
  • 사용 예시
    • 화면이 이동해도 로그인이 풀리지 않고 로그아웃하기 전까지 유지

      import javax.servlet.http.HttpSession;
      
      HttpSession session = request.getSession(); // session 공간 생성
      session.setAttribute("name",value); // name=value 형식으로 저장
      session.getAttribute("name"); //저장된 name에 해당하는 value 가져옴

      Cookie & Session

💡 Q. 세션을 쓰면되는데 굳이 쿠키를 사용하는 이유?

  • A. 세션이 쿠키에 비해 보안도 높은 편이나 쿠키를 사용하는 이유는세션은 서버에 저장되고, 서버자원을 사용하기 때문에 사용자가 많을 경우 소모되는 자원이 상당하다.이러한 자원관리 차원에서 쿠키와 세션을 적절한 요소 및 기능에 병행 사용하여,서버 자원의 낭비를 방지하며 웹사이트의 속도를 높일 수 있다.

Servlet 동기화 문제

init() method가 한번 호출 되기 때문에 filed variable이 존재할 경우 Service에 해당 variable이 있을 경우 thread를 통해 계속해서 호출 될 때 동기화 문제가 발생한다.

  • SingleThreadModel [ Marker Interface / deprecated]
    동기화 문제가 발생할 것 같으면 instance를 하나 더 만들어 주어 해결 가능하지만, Java의 장점을 포기하는 방법이다.

  • Service에 synchronize를 거는 방법이 있으나, Synchronized pool의 overhead 발생 우려

  • filed를 작성하지 않는 방법이 있으나, service에 의존적인 개발

  • 결론적으로 해결 방법은 없으나, 방문자 수 카운트 등에 이용할 수 있다.

  • 그러나 서버 재 구동 시 초기화 되기 때문에 file system에 저장하여 사용해야 한다.

선언 적 예외 처리

bean에서 발생하는 exception은 was에서 구동하기 때문에 was container로 다 던지지만, was container에서는 처리를 하지 않는다. 따라서, web.xml에 선언 적으로 exception을 정의하여 해당 exception 발생 시, 화면을 출력하도록 구성 가능하다.

profile
주니어 개발자

0개의 댓글