공부기록/Study

[자바 웹개발 워크북] 1장 웹 프로그래밍의 시작

메델 2023. 2. 2. 17:16

1. 웹 프로젝트의 기본 구조

 

대부분의 웹 프로젝트는 여러 프로그램이 같은 네트워크를 통해 연결되는 구조 

 

브라우저/ 클라이언트 프로그램

서버에서 전송한 결과를 화면에 보여주고

(관련 기술: HTML/CSS/자바스크립트 등등)

 

웹 서버 / WAS(Web Application Server)

웹 서버 → 이미지와 같은 고정된 데이터를 제공 

WAS → 동적으로 매번 새로운 데이터를 만들어 낼 수 있음

(관련 기술: 서블릿/JSP, 각종 프레임워크와 언어)

 

 

데이터베이스

영구적으로 데이터를 보관하고 운영하기 위한 프로그램

기본적으로 관계형 패러다임을 이용해 관계형 데이터베이스 사용

(관련 기술: SQL, DB 설계/구현)

 

 

2. Servlet 코드 작성

 

톰캣에서 작성하는 자바 코드는 HttpServlet 클래스 상속해서 작성 → 서블릿 클래스 생성 

@WebServlet → 브라우저의 경로, 해당 서블릿을 연결하는 설정을 위해 사용

doGet() → 브라우저의 주소를 직접 변경해서 접근하는 경우에 호출되는 메서드

PrintWriter → Servlet에서는 PrinteWriter이라는 객체를 사용하여 브라우저에 출력

 

package org.zerock.ww11;


import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name= "myServlet", urlPatterns = "/my")
public class MyServlet extends HttpServlet {


    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        out.println("<html><body>");
        out.println("<h1>MyServlet</h1>");
        out.println("</body></html>");

    }
}

 

3. JSP 코드 작성

 

webapp 폴더에 jsp 파일 생성

 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
  <h1>Test JSP PAGE</h1>

</body>
</html>

 

4. Request (요청) / Response (응답)

브라우저에서 서버에 GET/POST 방식으로 데이터를 요구하는 것을 'Request'라 한다. 

서버가 이에 대한 'Response' 데이터를 만들어서 브라우저로 보낸다.

 

브라우저는 자신이 원하는 정보를 전달하기 위해 GET/POST 방식 사용

GET 방식 POST 방식
주소창에 직접 원하는 데이터를 적거나 링크를 클릭해서 호출

원하는 웹의 주소를 호출할 때 필요한 데이터를 '?'와'&=(쿼리 스트링)'을 이용해서 같이 전송하는 방식

주소와 필요한 데이터를 한번에 같이 보내기 때문에 단순 링크 처리  → 다른 사람들에게 메신저나 SNS를 통해서 쉽게 공유 가능
GET 방식은 주로 특정한 정보를 조회하는 용도로 사용

브라우저에 따라 길이의 제한
URL 뒤의 쿼리 스트링으로 모든 정보가 전달되는 단점
퀴리 스트링 길이에 대한 제한

입력 화면에서 필요한 내용을 작성한 후에 '전송'과 같은 버튼 등을 클릭해서 호출

등록/수정/삭제와 같이 처리에 사용

주소와 데이터를 따로 보내는 방식(URL 전달 후 HTTP Body로 쿼리 스트링)

(ex. 회원 가입, 로그인 등의 처리)

POST 방식은 웹 화면을 통해서 실제 처리가 필요한 작업을 하기 위해서 사용

단순 조회가 아니라 원하는 작업 처리 가능
 
GET 방식에 비해 많은 양의 데이터를 전송
주소창만으로는 테스트가 어려움 


 

서버에서 브라우저로 응답을 보내는데 서버에서는 정적/동적 데이터 다르게 처리

정적 데이터 동적 데이터
항상 동일하게 고정된 데이터를 전송하는 방식
주로 파일, 고정된 HTML, CSS, 이미지 등의 데이터
매번 필요할 때마다 다른 데이터를 동적으로  구성해서 전송하는 방식

 

웹 서버  → 정적 데이터를 보내는 역할만을 수행하는 서버

웹 애플리케이션 서버(WAS)  → 동적 데이터를 만들어 보내는 경우

 

BUT 대부분의 WAS는  웹 서버 기능도 같이 포함  → 정적인 자원들과 Servlet/JSP 같은 동적인 자원 모두 처리

 

5. HTTP

 

프로토콜

  • 브라우저의 요청과 서버의 응답 사이에는 데이터 교환 약속을 통해서 처리되는데 여기서 데이터 교환약속을 프로토콜이라고 함
  • 웹에서는 HTTP(Hyper Text Transfer Protocol) 방식으로 데이터를 주고 받음
  • HTTPS는 HTTP에 보안이 더 강화된 프로토콜

 

HTTP 메시지 

  • 헤더(Headers), 몸체(Body)
  • Request, Response 모두 사용 하지만 메시지의 내용과 구성이 다름
  • 브라우저에서 특정한 URL을 호출하면 '요청', '응답'이 하나의 쌍으로 묶여서 처리 → 개발자 도구 [Network → Headers] 항목에서 'Request Headers'와 'Response Headers' 항목이 같이 보여지게 처리되어 있음

 

비연결성(Connectionless)

하나의 요청과 응답을 처리한 후에 종료한다는 의미

서버에서 하나의 Request를 빨리 처리하고 연결을 종료해서 다음 Request을 받을 수 있다면 적은 리소스를 이용해서 많은 Request를 처리할 수 있다

 

 

6. 자바 서버 사이드 프로그래밍

서버 사이드 프로그래밍

서버 쪽에서 프로그래밍을 통해 데이터를 처리할 수 있도록 구성하는 것을 의미

 

  • 동시에 여러 Request가 들어온다면 어떻게 처리할 것인가
  • 서버에서 문제가 생기면 어떻게 처리할 것인가
  • 어떤  방법으로 데이터 전송을 최적화할 수 있을까
  • 분산 환경이나 분산 처리와 같은 문제는?

새로운 서비스를 개발할 때마다 위와 같은 고민을 새로 한다면 많은 비용과 시간이 소모된다 자바의 경우 이러한 처리를 JavaEE라는 기술스펙으로 정리, Servlet과 JSP는 JavaEE의 여러 기술 중 하나

 

서블릿(Servlet) 기술 

서버에서 동적으로 요청과 응답을 처리할 수 있는 API들을 정의한 것

 

JSP는 Servlet과 같은 원리지만 더 쉽게 HTML을 이용할 수있는 방식으로 코드를 작성할 수 있기 때문에 '서블릿으로는 코드를 이용한 처리, JSP로는 화면 개발'같은 역할을 분담해서 개발하는 것이 일반적 

 

서블릿 컨테이너

서블릿을 실행할 수 있는 환경, 과거에는 서블릿 엔진이라고는 용어 사용

 

자바 프로그램과 비교 했을 때 달라진점

  • 객체를 생성하거나 호출하는 주체는 사용자가 아닌 서블릿 컨테이너가 함
  • 서블릿 클래스에서 생성하는 객체의 관리 자체가 서블릿 컨테이너에 의해서 관리
  • 서블릿/JSP의 코드 개발은 자바 API와 더불어 서불릿 API도 같이 사용 

import의 경우 javax로 시작하는 서블릿 관련 API를 사용하고 있는 것을 볼 수있다.

 

서블릿 API에 지정된 메소드인 init(), doGet(), destroy()는 서블릿의 라이프 사이클이라고 한다.

이 메소드들의  호출의 주체는 개발자가 아닌 서블릿 컨테이너가 서블릿들을 관리하면서 호출

 

JSP 기술 

JSP(Java Server Pages) 서버에서 동적으로 데이터를 구성하는 기술

HTML 데이터를 만들어내는데 서블릿보다 더 특화된 기술

 

JSP/ Servlet

JSP는 HTML 코드를 그대로 이용하고 필요할 때 약간의 자바 코드를 넣지만 서블릿의 경우 자바 코드를 이용하여 HTML 문자열을 만들어낸다. JSP 파일의 경우 서블릿 코드로 변환되어서 컴파일되고 실행되기 문에 자바 코드가 아님에도 불구하고 서블릿과 동일하게 처리된다.

 

서블릿/JSP 정리

  • 서블릿/JSP 모두 JAVA EE 스펙의 일부
  • 서블릿/JSP를 실행하기 위해서는 서블릿 컨테이너가 필요
  • 서블릿 컨테이너가 서블릿/JSP 객체를 생성하고 생명 주기를 관리
  • JSP는 내부적으로 서블릿과 같은 방식으로 코드가 변환
  • JSP는 HTML 내에 자바 코드를 추가하는 방식, 서블릿은 자바 코드 안에 HTML 코드를 추가하는 방식 

7. JSP를 이용해서 GET / POST 처리하기

 

GET 방식

send 창 누르기 전 후 주소 

[SEND] 버튼은 'type=submit'으로 지정되어 있어 버튼을 클릭하면 <form> 태그 내에서 사용자가 입력한 값을 <input>태그의 name 속성값과 함께 전송

 

퀴리 스트링(query string)과 파라미터(parameter)

 

퀴리 스트링(query string)

  • 웹에서 주소창 뒤에 '?'로 시작하는 내용물은 퀴리 스트링
  • 무언가를 요구하거나 물어보는 용도로 데이터를 전달하기 위해 사용

 

파라미터(parameter)

  • 퀴링 스트링은 '키=값'의 형태로 데이터를 전달하는데 여러 개의 데이터가 필요한 경우 '&'를 이용해 연결
  • '키=값'의 형태를 '파라미터 이름과 값'이라고 말함

 

POST 방식

 

  • GET 방식과는 달리 POST 방식은 num1과 num2가 보이지 않는다.
  • POST 방식은 주소와 전달하고자 하는 데이터를 분리해서 전송하는 방식이므로 브라우저를 통해서 확일할 수 없고 개발자 도구를 이용해야만 확인가능
  • POST 방식은 '등록/수정/삭제'와 같은 작업을 수행하기 위해서 사용
  • GET 방식과 달리 정보의 확산이 목적이 아니므로 하나의 문자열로 모든 정보로 표현하지 않고 URL과 정보를 따로 구분해서 전달 

 

 

 

calcResult.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>NUM1 ${param.num1}</h1>
    <h1>NUM2 ${param.num2}</h1>
    <h1> SUM ${Integer.parseInt(param.num1) + Integer.parseInt(param.num2)}</h1>


</body>
</html>

'${}'는 JSP에서 사용한는 EL(Expression Language)로' 서버에서 데이터를 출력하는 용도

EL을 이용할 때는 param이라는 이름의 지정된 객체를 이용해서 현재 요청에 전달된 파라미터를 쉽게 추출

 

웹의 파라미터는 모두 문자열

 

jsp에서 모든 데이터는 문자열로 처리

결과 데이터를 처리하기 위해서는 Integer.parseInt()를 적용해서 '${}'로 감싸서 처리 

 

JSP의 올바른 사용법

 

JSP의 문제점

  • GET/POST 방식의 호출을 구분하지 않기 때문에 POST 방식으로 접근해야 하는 경우 GET 방식으로도 접근 가능하다
  • 다른 JSP 파일로 변경했을 때 과거 jsp를 알고 있는 사용자들에게 다시 주소가 변경 되었다는 사실을 알려 줘야한다.

 

따라서 최근에는 JSP를 아래와 같이 제한적인 용도로 사용

 

  • JSP에서 쿼리 스트링이나 파라미터를 처리하지 않는다 - JSP 대신에 서블릿을 통해서 처리
  • JSP는 입력 화면을 구성하거나 처리 결과를 보여주는 용도로 사용
  • 브라우저는 직접 JSP 경로를 호출하지 않고 서블릿 경로를 통해서 JSP를 보는 방식으로 사용

 

8.  웹 MVC 방식

  1. 브라우저의 요청은 해당 주소를 처리하는 서블릿에 전달
  2. 서블릿 내부에서 응답에 필요한 재료 데이터 준비
  3. 서블릿은 준비한 데이터를 JSP에  전달
  4. JSP에서는 EL을 이용해서 최종적인 결과 데이터를 생성 
  5. JSP를 이용해서 생성된 결과 화면은 톰캣을 통해서 브라우저로 전송

 

웹 MVC 구조 

'Model - View - Controller'의 역할을 분리해서 처리하는 구조

 

데이터는 Controller에서 결과는 View에서 처리 위의 설명에서 서블릿이 Controller 역할 JSP가 View 역할

 Controller 역할을 하는 서블릿은 JSP에 필요한 데이터를 가공하는 역할을 하는데 이때 필요한 데이터를 제공하는 객체를 Model이라한다.

MVC 구조에서 명심해야하는 원칙

 

브라우저의 호출은 반드시 컨트롤러 역할을 하는 서블릿을 호출하도록 구성

JSP는 브라우저에서 직접 호출하지 않도록하고 Controller를 통해서만 JSP에 접근하도록 구성

 

컨트롤러에서 뷰 호출

 

InputController.java

 

@WebServlet(name = "inputController", urlPatterns = "/calc/input")
public class InputController extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("InputController..doGet");
        RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/calc/input.jsp");

        dispatcher.forward(req, resp);
    }

}
  • @WebServlet으로 urlPatterns 속성을 지정해서 처리해야 하는 경로 지정
  • 부모 클래스인 HttpServlet의 doGet()을 재정의 (오버라이드, 부모 클래스의 메소드를 하위 클래스에서 다시 작성)
  • GET 방식으로 들어오는 Request에 대해서만 처리하도록 구성 

 

RequestDispatcher를 이용한 Request 배포 

 

RequestDispatcher = 서블릿에 전달된 Request를 다른 쪽으로 전달 혹은 배포하는 역할을 하는 객체

RequestDispatcher를 이용하면 InputController는 '/WEB-INF/calc/input.jsp'로 가는 중간 경유지가 된다.

 

WEB-INF

 

브라우저에서 직접 접근이 불가능한 경로

WEB-INF 밑에 jsp 파일을 둔다는 것은 브라우저에서 jsp로 직접 호출이 불가능하다는 것을 의미

 

POST 방식을 통한 처리 요청

 

서블릿은 doPost() 메서드를 오버라이드해서 POST 방식으로 들어오는 Request을 처리할 수 있음

→ 기존의 Controller에 doPost() 추가 또는 새로운 서블릿을 생성해 doPost() 작성

 

CalcController.java

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


@WebServlet(name = "calcController", urlPatterns = "/calc/makeResult")
public class CalcController extends HttpServlet {

    @Override
    protected  void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        String num1 = req.getParameter("num1");
        String num2 = req.getParameter("num2");

        System.out.printf(" num1: %s", num1);
        System.out.printf(" num2: %s", num2);
    }

}

 

주의점

  • urlPatterns 속성값이 '/calc/makeResult' 로 지정되어 있음 - 브라우저에서 <form> 태그의 submit 경로를 수정할 필요가 있다
  • doPost()를 오버라이드 - 브라우저에서 POST 방식으로 호출하는 경우에만 호출이 가능
  • req.getParameter() 라는 메서드를 이용해 쿼리 스트링으로 전달되는 num1, num2 파라미터를 처리하고 있으며 이때 숫자가 아닌 문자열로 처리, JSP에서는 $(param.num1)과 같이 단순하게 사용하지만 서블릿에서는 HttpServletRequest라는 API를 이용해야만 함

PRG 패턴(Post-Redirect-Get)

: POST 방식과 Redirect를 결합해서 사용, PRG 패턴은 POST 방식의 처리 후에 바로 다른 주소로 브라우저가 이동하기 때문에 반복적으로 POST가 호출되는 상황을 막을 수 있고 사용자의 입장에서도 처리가 끝나고 다시 처음 단계로  돌아간다는 느낌을 주게됨

 

  • 사용자는 컨트롤러에 원하는 작업을 POST 방식으로 처리하기를 요청
  • POST 방식을 컨트롤러에 처리하고 브라우저는 다른 경로로  이동(GET)하라는 응답(Redirect)
  • 브라우저는 GET 방식으로 이동

PRG 패턴의 대표적인 예 - 게시

  • 사용자가 새로운 게시글의 내용을 작성하고 POST 방식으로 전송
  • 서버에서 새로운 게시글을 처리한 후에 브라우저의 주소를 목록 화면 경로로 이동하도록 응답(Redirect)
  • 브라우저는 목록 화면을 보여주고 사용자는 자신이 추가한 게시글이 추가된 결과 확인 

9. HttpServlet

HttpServlet 특징

 

  • HttpServlet은 GET/POST 등에 맞게 doGet(), doPost() 등을 제공하므로, 개발자들은 본인에게 필요한 메소드를 오버라이드하는 것만으로 GET/POST 방식 처리를 나누어서 처리할 수 있다.
  • HttpServlet은 상속받은 클래스 객체는 톰캣과 같은 WAS의 내부에서 자동으로 객체를 생성하고 관리하기 때문에 객체 관리에 신경 쓸 필요 X
  • HttpServlet은 멀티 스레드에 의해서 동시에 실행될 수 있도록 처리되기 때문에 개발자는 동시에 많은 사용자들을 어떻게 처리해야하는지에 대한 고민을 줄일 수 있다. 
  • HttpServlet은 상위 클래스로 GenericServle이라는 추상클래스 상속 GenericServlet는 HttpServlet과 달리 HTTP 프로토콜에 특화되지 않은 요청과 응답에 대한 기능을 정의 

 

HttpServlet의 라이프사이클

 

개발자가 작성하는 서블릿 클래스들은 다음과 같은 과정을 통해 처리

 

  1. 브라우저가 톰캣에 서블릿이 처리해야하는 특정한 경로를 호출
  2. 톰캣은 해당 경로에 맞는 서블릿 클래스를 로딩하고 객체를 생성. 이 과정에서 init()라는 이름의 메소드를 실행해서 서블릿 객체가 동작하기 전에 수행해야하는 일들을 처리할 수 있다
  3. 생성된 서블릿 객체는 브라우저의 요청에 대한 정보를 분석해서 GET/POST 등의 정보와 함께 같이 전달되는 파라미터(쿼리 스트링의 내용)들을 HttpServletRequest라는 타입의 파라미터로 전달 받음. 이 과정에서 응답을 처리하는데 필요한 기능들은 HttpServletResponse라는 타입의 객체로 전달 받음
  4. 서블릿 내부에서 GET/POST에 맞게 doGet()/doPost()등의 메소드를 실행. 이후 동일한 주소의 호출이 있을 때 서블릿은 동일한 객체 하나만을 이용하여 이를 처리
  5. 톰캣이 종료될 때는 서블릿의 destory()라는 메서드를 실행 

서블릿의 객체는 경로에 맞게 하나만 만들어짐, 매번 호출 시에는 자동으로 doGet()/doPost() 를 이용해서 처리

init()와 destroy()는 한번씩만 호출되고  doGet()/doPost()는 동일한 객체를 이용해서 여러 번 호출

 

HttpServletRequest의 주요기능

 

HttpServletRequest는 HTTP 메시지 형태로 들어오는 요청에 대한 정보를 파악하기 위해 제공되는 주요 기능

기능 메서드 설명
HTTP 헤더 관련 getHeaderNames()
getHeader(이름)
HTTP 헤더 내용들을 찾아내는 기능
사용자 관련 getRemoteAddress() 접속한 사용자의 IP 주소
요청 관련 getMethod()
getRequestURL()
getRequestURI()
getServletPath()
GET/POST 정보, 사용자가 호출에 사용한 URL 정보 등 
쿼리 스트링 관련 getParameter()
getParameterValues()
getParameterNames()
퀴리 스트링 등으로 전달되는 데이터를 수출하는 용도
쿠키 관련 getCookies 브라우저가 전송한 쿠키 정보
전달 관련 getRequestDispatcher()  
데이터 저장 setAttribute() 전달하기 전에 필요한 데이터를 저장하는 경우에 사용

 

getParameter()

  • HttpServletRequest에서 가장 자주 사용되는 메소드
  • '?name=AAA&age=20'과 같은 쿼리 스트링에서 'name'이나 'age'라는 키(key)를 이용해서 값(value)을 얻는 역할 
  • 결과는 항상 String 따라서 숫자를 처리할 때는 예외가 발생할 수 있음
  • 해당 파라미터가 존재하지  않는다면 null 반환

getParameterValues()

  • getParameterValues()는 동일한 이름의 파라미터가 여러개 있는 경우 사용 
  • name이라는 이름의 파라미터가 여러 개 존재한다면 getParameterValues()를 이용해서 String[] 타입으로 반환

setAttribute()

  • JSP로 전달할 데이터를 추가할 때 사용
  • '키', '값'의 형태로 데이터 저장 (키는 문자열로 지정하고, 값은 모든 객체 타입 이용 가능)
  • JSP에는 서블릿에서 SetAttribute()로 전달된 데이터를 화면에 출력

 

RequestDispatcher

  • 웹 MVC 구조에서 HttpServletRequest의 getRequestDispatcher()를 이용해서 RequestDispatcher 타입의 객체를 구할 수 있음
  • 현재의 요청을 다른 서버 자원(서블릿/JSP)에게 전달하는 용도로 사용
  • 2개의 메서드 존재 (실제 개발에서는 거의 forward()만 이용) 
    • forward(): 현재까지 모든 Response 내용을 무시하고 JSP가 작성하는 내용만을 브라우저로 전달
    • include(): 지금까지 만들어진 Response 내용 + JSP가 만든 내용을 브라우저로 전달

 

HttpServletResponse의 주요 기능

 

HttpServletRequest는 주로 읽는 기능 제공,  HttpServletResponse는 주로 쓰는 기능 담당

웹 MVC 구조에서 HttpServletResponse는 JSP에서 주로 처리되기 때문에 서블릿 내에서 직접 사용되는 일은 많지 않음

주로 sendRedirect()를 이용하는 경우가 많음

 

기능 메서드 설명
MIME 타입 setContentType() 응답 데이터의 종류를 지정(이미지/html/css 등)
헤더 관련 setHeader() 특정 이름의 Http 헤더 지정
상태 관련 setStatus() 404, 200, 500 등 응답 상태 코드 지정
출력 관련 getWriter() PrintWriter를 이용해서 응답 메시지 작성
쿠키 관련 addCookie() 응답 시에 특정 쿠키 추가
전달 관련 sendRedirect() 브라우저에서 이동 지시

 

sendRedirect()

 

 

  • 웹 MVC 구조에서 HttpServletResponse의 메서드들 중에서 가장 많이 사용되는 메서드
  • sendRedirect()는 브라우저에게 다른 곳으로 가라는 응답 메시지를 전달
  • HTTP에서 'Location' 이름의 HTTP 헤더로 전달 되는데 브라우저는 'Location' 이 있는 응답을 받으면 화면을 처리하는 대신에 주소창에 지정된 주소로 이동하고, 다시 호출
  • sendRedirect()를 사용하면 브라우저의 주소가 아예 변경되기 때문에 사용자의 '새로고침'과 같은 요청을 미리 방지하고 특정한 작업이 완전히 끝나고 새로 시작하는 흐름을 만들 수 있다.

10. Model

DTO(Data Transfer Object)

  • 여러개의 데이터를 묶어서 하나의 객체로 전달하는 것
  • 여러 개의 데이터를 묶어서 필요한 곳으로 전달하거나 호출을 결과로 받는 방식으로 사용하기 때문에 특별한 규격이나 제약은 없으나 대부분 Java Beans 형태로 구성
    • <Java Beans> 형태 
    • 생성자가 없거나 반드시 파라미터가 없는 생성자 함수를 가지는 형태
    • 속성(멤버 변수)는 private로 작성
    • getter/setter로 제공
  • 컨트롤러는 DTO를 구성해서 서비스 계층을 호출하기도 하고 반대로 서비스 계층에서 DTO를 받기도 하기 때문에 서비스 계층 구성 전에 DTO를 위한 클래스를 먼저 구성 

 

서비스 객체

 

'기능(로직)들의 묶음'

서비스 객체는 프로그램이 구현해야 하는 기능들의 실제 처리를 담당

ex) CRUD 기능들을 모두 서비스 객체에 모아서 구현 

 

TodoService.java 

public enum TodoService {
    INSTANCE;
}

enum 타입으로 클래스를 작성하는 경우 정해진 수만큼만 객체 생성할 수 있음

INSTANCE 는 객체의 개수를 결정하는 부분으로 한 개만 지정되어 있으므로 하나의 객체만을 생성해서 사용

→ 싱글톤 패턴

 

컨트롤러에서 모델 처리하기

 

웹 MVC 구조에서는 화면에 필요한 데이터를 처리하고자 컨트롤러는 서비스 객체의 힘을 빌려서 처리 

(ex. 화면에서 목록 데이터들이 필요하다면 TodoService의 getList()의 결과를 받아서 JSP까지 전달하고 이를 JSP에서 보여주는 방식)

 

가장 중요한 메소드는 HttpServletRequest의 setAttribute()

 

setAttribute()는 키와 값의 형식으로 HttpServletRequest에 데이터를 보관하게 한다 

→ 보관된 데이터는 JSP에서 꺼내서 사용하게 되는 방식 

 

JSP - EL(Expression Langauge)

 

  • JSP 코드에서 사용한 '${}'는 EL의 표현식
  • EL을 이용하는 경우 자동으로 getter 호출
  • TodoDTO 클래스에서 tno, title은 private으로 처리되어 있으므로 자바 코드에서 외부에서 바로 접근이 블가능하지만 EL은 getTno(), getTitle()을 자동으로 호출 
  • EL는 표현식이므로 '${}' 내부에 표현식이 결과를 만들어 낼 수만 있다면 언제든 사용 가능
  • EL은 JSP에서 간단한 표현식을 이용해서 데이터를 출력하는 용도로 statement를 처리하기 위해서는 JSTL 라이브러리 필요 
//TodoDTO의 tno와 title을 출력할때 

${list[0].tno} --- ${list[0].title}

 

JSTL(JavaServer Pages Standard Tag Library)

 

  • JSP에서 동작하는 새로운 태그들의 묶음 
  • JSTL은 자바 문법보다 간결하게 제어문이나 반복문, 선언문 등을 처리할 수 있고 확장이 가능하게 설계

JSTL을 사용하기 위해서는 의존성 라이브러리 추가

 

dependencies {
    compileOnly('javax.servlet:javax.servlet-api:4.0.1')
    testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
    implementation group: 'jstl', name:'jstl', version:'1.2'//이거 추가
}

 

JSP에서 JSTL을 이용하기 위해서는 파일 상단에 태그 관련 설정 추가

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

 

<c:forEach>

 

JSTP에서 가장 많이 사용하는 반복문 처리에서 <c:forEach>를 이용해서 작성 <c:forEach>는 배열이라 리스트 등의 처리에 사용

속성명 속성값
var EL에서 사용될 변수 이름
items List, Set, Map, Enumeration, lterator 등의 컬렉션
begin/end 반복의 시작/ 끝 값 

 

반복문의 경우 begin/end를 이용

//1부터 10까지 숫자를 출력하는 경우
<ul>
       	<c:forEach var="num" begin="1" end="10">
            <li>${num}</li>
        </c:forEach>
</ul>

 

<c:if>, <c:choose>

 

  • JSTL 제어문은 <c:if>, <c:choose>가 존재
  • <c:if>의 경우 test라는 속성이 존재,  test 속성값으로 true/false로 나올 수 있는 식이나 변수 등이 들어갈 수 있다
  • <c:choose>는 자바의 switch와 비슷 
  • <c:choose>는 내부에서 <c:when test=...>, <c:otherwise>를 이용해서 'if~else if~else'의 처리가 가능
<c:if test="${list.size() %2 == 0}">
    짝수
</c:if>
<c:if test="${list.size() %2 != 0}">
    홀수
</c:if>

 

<c:if>의 경우 else에 대한 처리가 없으므로 앞의 코드를 <c:choose>로 변경하면 아래와 같다

    <c:choose>
        <c:when test="${list.size()%2 == 0}">
            짝수
        </c:when>
        <c:otherwise>
            홀수
        </c:otherwise>
    </c:choose>

 

<c:set>

 

  • 변수를 생성하고 사용할 수 있음
  • var 속성으로 변수명을 지정하고 value 속성으로 값을 지정
<c:set var="target" value="5"></c:set>

 

(참고: 자바 웹 개발 워크북)