Backend

[Backend]sevlet, jsp, session, cookie, mvc 등 정리

Fenderblue 2023. 10. 3. 23:02

서블릿 url 매핑

servlet에서 url 매칭은 클라이언트의 요청이 어떤 서블릿 클래스에 대응되어야 하는지를 결정하는 과정을 나타낸다.

uri 매핑을 설정하면 서블릿 컨테이너는 클라이언트의 http요청 url를 분석해 해당 url에 대한 서블릿을 호출한다.

매핑에는 두 방법이 있는데

 

1. 어노테이션을 통한 설정

서블릿 3.0부터는 java 어노테이션을 사용해 url 매핑을 설정할수 있다.

예시
@WebServlet("/exam")
@WebServlet(value="/exam")

-> 위 두개는 같은 기능이지만 위에가 좀더 간략하므로 주로 위의 방식을 이용해봤다.
@WebServlet(urlPatterns= {"/exam", "/testm"})

-> urlPatterns 속성에 배열로 여러개의 uri 패턴을 지정하고 싶다면 이렇게 하면 된다!

* "/myurl" -> 정확히 이 url에 해당하는 경로일 경우에만 매핑이 됨,

만약 이 뒤에 어떤 추가 경로가 붙더라도 매핑되도록 하고 싶다면 "/myurl/*"로 와일드카드를 써주면 된다.

2. web.xml 을 통한 설정

서블릿 2.5 이전 버전에서 사용되는 방식.

web.xml파일에서 서블릿 클래스와 해당 서블릿이 처리할 url 패턴을 명시해놓는다.

<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.example.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/myurl/*</url-pattern>
</servlet-mapping>




HttpServlet 라이프 사이클

HttpServlet이란? 자바 servlet API의 일부로, http프로토콜을 기반으로 동작하는 웹 어플리케이션 개발 기본 클래스,

GenericServlet 클래스를 확장한것으로 http 요청/응답 처리에 특화되어 있다.

http 메서드 (get/post/put/delete)에 따라 서로 다른 동작을 수행, 사용자 요청 처리와 동적 웹 페이지 생성에 활용된다.

이 HttpServlet을 상속받아 직접 서블릿을 작성, doGet/doPost를 오버라이딩해 웹 애플리케이션의 동작을 구현한다.

 

HttpServlet의 라이프 사이클은 서블릿의 생성부터 제거까지의 과정이다. 이는 서블릿 컨테이너에 의해 관리되며,

서블릿이 특정 이벤트에 응답하고 초기화 및 종료 작업을 수행할 수 있도록 한다.

1. init(ServletConfig):

서블릿 컨테이너가 서블릿 인스턴스를 생성,초기화하기 위해 init 메서드를 호출한다.

보통 웹 어플리케이션이 처음 요청에 대한 응답을 준비하기 전에 초기화된다.

서블릿 인스턴스가 처음 생성될때 한번만 호출된다.

ServletConfig 매개변수를 통해 서블릿의 초기화 매개변수를 읽을수 있다.

초기화 매개변수는 web.xml파일에 설정되며 서블릿이 동작하는 동안 사용되는 설정정보를 제공한다.

public void init(ServletConfig config) throws ServletException {
    // 서블릿 초기화 로직
}


2. service(HttpServletRequest, HttpServletResponse)

service 메서드는 클라이언트의 http요청을 처리하는 핵심 메서드이다.

서블릿 컨테이너가 http 요청을 받을 때마다 service메서드를 자동으로 호출하고,

HttpServletRequest & HttpServletResponse매개변수를 통해 요청을 처리하고 응답을 생성한다.

http메서드 (get/post/put/delete)에 따른 적절한 doGet/doPost/doPut/doDelete등의 메서드를 내부적으로 호출,

이러한 메서드를 오버라이딩해 각각의 메서드에 대한 처리를 구현한다.


3. destroy()

서블릿 인스턴스가 종료되기 직전에 호출된다. 서블릿의 정리작업 또는 상태 저장 등을 수행하는데 사용된다.



서블릿 관련 객체, 주요 메서드

 

interface Servlet
abstract class GenericServlet implements Servlet  
abstract class HttpServlet extends GenericServlet 
: HTTP 프로토콜에 맞는 기능 추가.

Servlet > GenericServlet > HttpServlet

 

public void doGet(HttpServletRequest, HttpServletResponse) ->
HttpServletRequest: http요청에 관련된 정보를 담는 객체.

HttpServletResponse: http응답에 관련된 정보를 담는 객체.

 

객체 범위 종류, 이제는 좀 확실히 알자

1. page영역:

하나의 jsp 페이지 내에서만 객체를 공유하는 영역.

jsp파일에는 pageContext가 내장되어 있는데, 이 객체는 Page영역 내에서만 유효하다.

<%%>안에 변수를 할당해 사용

 

2. request 영역:

요청을 받아 응답하기까지 객체가 유효한 영역.

Http 요청 내에서만 데이터를 공유하는 범위이며

HttpServletRequest 객체의 속성으로 데이터를 저장하고 사용한다.

이는 하나의 http 요청에서만 사용되며, 해당 요청과 관련된 서블릿에서만 접근가능하다.

servlet에서 forward나 include를 사용해 request 요청객체를 공유

request.setAttribute("이름", 객체);로 전달

 

 

3. session 영역:

세션 범위는 하나의 세션 내에서 데이터가 공유되는 범위이며, 사용자 세션마다 별도의 HttpSession객체가 생성되며

이는 해당 세션에만 공유된다.

일반적으로 로그인정보, 사용자 설정, 장바구니 등의 사용자 개인 데이터를 저장하는데 사용된다.

하나의 브라우저당 하나의 세션 객체가 생성되므로 같은 브라우저 내에서라면 같은 세션 객체를 공유한다.

request.getSession()메서드를 통해 세션영역의 객체를 얻을수 있다.

세션이 종료되면 객체 반환됨

 

4. application 영역:

하나의 어플리케이션당 하나의 어플리케이션 객체가 생성됨.

같은 애플리케이션이라면 공유가능, 애플리케이션이 종료되면 객체 반환

request.getServletContext()메서드 호출을 통해 애플리케이션 영역 객체 얻을수 있다

* ServletContext
- 웹어플리케이션 전체를 가리키는것, 즉, 프로젝트 정보를 가지고 있음

 

<scope 범위>

application > session > request > page 순

만약 서로 다른 영역에 같은 이름을 갖는 속성이 있다면?더 좁은 범위부터 탐색.

 

만약

session.setAttribute("msg", "hello");
request.setAttribute("time", "10시");
response.sendRedirect("a.jsp");

a.jsp 페이지에서 msg 사용 가능할까?

가능함. session영역에 저장했으므로 공유된다
a.jsp 페이지에서 time 사용 가능한가? 

불가능. sendRedirect로 페이지 이동이 일어나며 해당 페이지에 대한 요청을 보내지만 이는 새로운 요청이기에

세션을 사용하거나 url 매개변수로 데이터를 전달하는 방법을 사용하지 않는 한

sendRedirect로 데이터를 직접 공유하기는 어렵다.

객체를 직접 공유하고 싶다면 밑에와 같이 forward 방식으로~(request 영역 해당)

RequestDispatcher dispatcher = request.getRequestDispatcher("/result.jsp");
rd.forward(request, response);



Object getAttribute(String) : 지정된 이름(String name)으로 저장된 데이터 가져올때 사용.
setAttribute(String, Object) :  데이터를 지정된 이름으로 저장할때 사용. (String name, Object data)

http://localhost:8080/trip/join?hobby=movie&hobby=music  
String hobby = request.getParameter("hobby");  // movie

-> url에서 파라미터 값을 얻으려는데 동일한 이름으로 여러개의 파라미터 값이 전달되는 위와 같은경우

첫번째 값인 movie만 hobby에 저장되게 된다.

만약 모든 hobby라는 이름에 대한 값들을 저장하고 싶다면

String[] hobbies = request.getParameterValues("hobby");

다음과 같이 getParameterValues로 배열에 값을 담으면 된다!

예제

<input type="checkbox" name="hobby" value="movie" /> 영화
<input type="checkbox" name="hobby" value="music" /> 음악
http://localhost:8080/trip/join?hobby=movie&hobby=music 
String[] hobbies = request.getParameterValues("hobby");
String[] getParameterValues(String paramName)

 


페이지 이동 관련 객체 및 메소드 정리

프로젝트 경로 : /exam 
호출할 페이지 : /board/list.jsp


forward 방식
RequestDispatcher rd = request.getRequestDispatcher("주소 - 프로젝트 경로 배제");
RequestDispatcher rd = servletContext.getRequestDispatcher("주소");

주소가 바뀌지 않음, 데이터 공유하기 용이함


ex) RequestDispatcher rd = request.getRequestDispatcher("/board/list.jsp");
rd.forward(request, response);

redirect 방식
response.sendRedirect("주소 - 프로젝트 경로 포함");

주소가 변경되며 request의 데이터를 공유할 수 없다.


ex) response.sendRedirect("/exam/board/list.jsp");

클라이언트 요청방식 / 서블릿에서의 처리방법 / 에러 응답 코드

- GET  : 파라미터 정보가 URL 에 붙어서 전송, 데이터 전송에 한계를 가지고 있음(4K), 보안 좋지 않다.
- POST : 파라미터 정보가 BODY 에 붙어서 전송, 데이터 전송에 한계를 가지고 있지 않다, GET 방식 보다는 보안이 좋다.

서블릿에서의 처리방법
- get 요청 : doGet
- post 요청 : doPost

에러 응답 코드
- 404 : 페이지를 못찾는 경우
- 405 : 요청 방식에 대한 지원이 없는경우
      : 사용자가 get 방식 요청이었는데 서블릿에 doPost가 있는 경우
      : 사용자가 post 방식 요청이었는데 서블릿에 doGet가 있는 경우
- 500 : 서버 처리 에러

JSP 구성요소별 기능 및 사용법

a.jsp
<body>
<%
out.println("hello");
int i = 100;
%>
</body>

a_jsp.java 변환

<%!
public void call() {}
int cnt = 100;  
%>
public void call() {}
int cnt = 100;  

public void _jspService(HttpServletRequest req, HttpServletResponse res) {
out.print("<body>\r\n");
out.println("hello");
public void call() {}
int i = 100;
out.print("</body>\r\n");
}

- <%      %> : 스크립트릿. 자바코드 작성(변수선언, 조건문, 반복문 등)
- <%!     %> : 선언 블록. 메서드 선언, 멤버변수 선언, 주로 전역변수 선언 
- <%=     %>: 표현식. 변수 값 출력하거나 메서드 호출결과 표시할때 사용, 
- <%--  --%> : 주석문
- <%@     %> 
  : page     <%@ page import="" contentType="" %>
  : include  <%@ include file="" %>
  : taglib   <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

 


JSP구문 EL로 변환하기

<%
User user = (User)request.getAttribute("userInfo");
%>
<%= user.getId() %>

위 코드를

${userInfo.id} 이렇게 간단히 표현가능

${pageContext.request.contextPath}

 

JSTL의 다양한 태그

- <c:set var="cnt" value="1" scope="session" />

-> 변수의 이름을 cnt로 설정, 초기값을 1로 설정, 변수 스코프를 session으로 설정.
  session.setAttribute("cnt", "1"); 이것과 동일한 의미
  
- <c:if test="${5 > 3}">
  </c:if>

-> 조건문. test에 조건이 들어감, 이는 el을 사용하여 표현
  
- <c:choose>
 <c:when test="">
 
 </c:when>
 <c:when test="">
 
 </c:when>
 <c:otherwise>
 
 </c:otherwise>
  </c:choose>

->위와같이 choose를 통해 if-else문처럼 사용도 가능
  
- <c:forEach var="i" begin="1" end="10" step="1">
  </c:forEach> 

-> 1~10까지의 수를 1씩 증가하며 반복 수행


  <c:forEach var="board" items="${list}" varStatus="loop">
${loop.first}
${loop.last}
${loop.count}
${loop.index}
  </c:forEach>    
-> forEach의 varStatus 속성을 통해 반복문의 상태를 저장해 접근할수 있음.

여기서 loop는 반복문 상태정보에 접근할 변수명

반복횟수/현재 인덱스/첫번째 반복여부/마지막 반복여부 등을 확인할때 유용함.

${loop.first} <!-- 첫 번째 반복인지 여부 (true 또는 false값) -->
${loop.last} <!-- 마지막번째 반복인지 여부 (true 또는 false값) -->
${loop.count} <!-- 현재까지의 반복 횟수(index보다 1 큼) -->
${loop.index} <!-- 현재 반복의 인덱스 (0부터 시작) -->


Scope 관련 객체들..이제는 숙지하자

pageContext : PageContext

request : HttpServletRequest

session : HttpSession

application : ServletContext

 


쿠키의 개념 / 특징 / 설정 / 전송

- 정보의 저장이 클라이언트
- 저장되는 데이터 타입이 문자열
- 유지시간 : 사용자의 설정이 가능(브라우져가 종료된 다음에도 유지된다. 40년... 400일...)
- 쿠키를 설정한 사이트로만 전송한다.(네이버에서 설정한 쿠키는 카카오로 전송되지 않는다.)
- 서버의 부하는 적음
- Cookie cookie = new Cookie("이름", "값");
  cookie.setMaxAge(10); 초단위 설정
  response.addCookie(cookie); 사용자에게 전송

 

세션의 개념 / 특징 / 객체 타입 / 메소드

- 정보의 저장이 서버
- 저장되는 데이터 타입이 객체
- 유지시간 : 최대 유지시간은 브라우져가 켜져있는 동안
- 서버의 부하가 발생할수도
HttpSession session = request.getSession();
session.setAttribute("문자열", 객체);
객체 = session.getAttribute("문자열");

세션 로그아웃은 session.invalidate(); !

- HTTP 프로토콜의 특징과 함께 상태정보를 기억하지 않는다.(stateless)???

 

MVC 패턴 이해 및 동작

 MVC(Model-View-Controller) 패턴은 소프트웨어 디자인 패턴 중 하나로, 소프트웨어 애플리케이션을 설계하고 구성하는 데 사용되는 아키텍처 패턴입니다. MVC 패턴은 애플리케이션을 세 가지 주요 부분으로 분리하고 각 부분이 특정 역할을 수행하도록 하는 방식으로 동작합니다. 아래에서 MVC 패턴의 각 구성 요소와 동작 방식을 자세히 설명하겠습니다:

모델(Model):

모델은 애플리케이션의 핵심 로직과 데이터를 나타냅니다.
데이터의 상태를 관리하고 조작하는 역할을 담당합니다.
데이터의 변경을 감지하고 뷰와 컨트롤러에 변경 사항을 알립니다.
일반적으로 데이터베이스, 파일 시스템, 외부 서비스와 같은 데이터 소스와 상호작용합니다.


뷰(View):

뷰는 사용자 인터페이스를 나타내며 모델의 데이터를 시각적으로 표현합니다.
사용자가 데이터를 볼 수 있도록 데이터를 표시하고 사용자 입력을 받습니다.
뷰는 모델의 데이터를 직접 조작하지 않으며, 모델의 상태를 표시하기만 합니다.
여러 뷰가 동일한 모델을 기반으로 데이터를 다른 방식으로 표현할 수 있습니다.


컨트롤러(Controller):

컨트롤러는 사용자의 입력을 받아 모델과 뷰 사이의 상호작용을 관리합니다.
사용자의 요청을 해석하고 모델에 데이터 처리를 요청합니다.
모델의 상태 변경을 감지하고, 변경된 데이터를 적절한 뷰에 업데이트 요청을 보냅니다.
웹 애플리케이션의 경우, URL 라우팅과 HTTP 요청을 처리하며, 요청을 처리할 뷰를 선택합니다.


MVC 패턴의 동작 방식은 다음과 같습니다:
사용자가 뷰를 통해 애플리케이션에 요청을 보냅니다.
컨트롤러는 사용자의 요청을 수신하고, 해당 요청을 어떤 모델 메서드를 호출해야 하는지 결정합니다.
모델은 요청을 처리하고 필요한 데이터를 업데이트합니다.
모델의 변경 사항은 컨트롤러에 알려지고, 컨트롤러는 변경된 데이터를 관련된 뷰에 전달합니다.
뷰는 받은 데이터를 사용하여 사용자에게 정보를 표시합니다.
MVC 패턴은 소프트웨어의 구조화와 유지보수를 개선하며, 여러 개발자가 협업하여 대규모 애플리케이션을 개발하는 데 도움이 됩니다. 각 부분이 분리되어 있으므로 모델, 뷰, 컨트롤러를 독립적으로 개발하고 테스트할 수 있으며, 변경 사항을 쉽게 적용할 수 있습니다. 이러한 이점으로 인해 MVC 패턴은 웹 개발 및 응용 프로그램 개발에서 매우 널리 사용됩니다.