html부터 웹사이트 개발까지! - JSP편

Coosla·2022년 10월 9일
1

✏️ URL

URL이란

  • 웹 브라우저의 주소줄에 표시되는 것
  • Uniform Resource Locator의 약자, 일종의 주소와 같은 역할

URL의 구성요소

  • 프로토콜
    • 웹 브라우저와 서버가 데이터를 주고받을 때 사용하는 규약
    • 웹페이지 주소를 표현할 때는 http 사용
  • 서버이름
    • 웹 페이지를 요청할 서버의 이름 지정
    • 도메인 이름이나 IP 주소로 입력
  • 경로
    • 웹페이지의 상세 주소
  • 쿼리 문자열
    • 추가로 서버에 보내는 데이터

✏️ JSP 페이지의 구성 요소

디렉티브(Directive)

  • jsp 페이지에 대한 설정 정보를 지정할 때 사용
  • 형태
    <%@ 디렉티브이름 속성1="값1", 속성2="값2", ... %>
  • 디렉티브 종류
    • page : JSP 페이지에 대한 정보 지정
    • taglib : JSP 페이지에서 사용할 대그 라이브러리 지정
    • include : JSP 페이지의 특정 영역에 다른 문서를 포함

  • page 디렉티브 세부 설명

    • JSP 페이지에 대한 정보를 입력
    • 주요 속성
      • contentType : JSP가 생성할 문서의 MIME타입(프로토콜에서 응답 데이터 내용을 설명하기 위해 사용)과 캐릭터 인코딩을 지정
      • import : JSP페이지에서 사용할 자바 클래스를 지정
      • session : JSP 페이지에서 세션을 사용할지 여부 지정, true(세션 사용), false(세션 사용X)
      • buffer : JSP 페이지의 출력 버퍼 크기를 지정, 최소 8kb
      • autoFlush : 출력 버퍼가 다 찼을 경우 자동으로 버퍼에 있는 데이터를 출력 스트림에 보내고 비울지 여부를 나타냄. true(데이터를 웹 브라우저에 보낸 후 버퍼를 비움), false(에러 발생)
      • info : JSP 페이지에 대한 설명
      • errorPage : JSP 페이지를 실행하는 도중에 에러가 발생할 때 보여줄 페이지 지정
      • isErrorPage : 현재 페이지가 에러가 발생될 때 보여주는 페이지인지 여부 설정
      • pageEncoding : JSP 페이지 소스 코드의 문자 인코딩을 지정
      • isELignored : true(표현언어 무시, 문자열 처리), false(표현언어 지원)
      • deferredSyntaxAllowedAsLiteral : #{ 문자가 문자열 값으로 사용되는 것을 허용할지 여부 설정
      • trimDirectiveWhitespaces : 출력 결과에서 텍스트의 공백 문자를 제거할지 여부 설정
  • include 디렉티브 세부 설명

    • 지정한 페이지를 현재 위치에 포함시키는 기능

    • <jsp:include> 액션 태그와 달리 다른 파일의 내용을 현재 위치에 삽입한 후 JSP파일을 자바 파일로 변환하고 컴파일하는 방식

    • include 디렉티브로 포함된 변수나 메소드를 JSP페이지에서 사용할 수 있음.

    • 형태

      <%@ include file="포함할파일경로" %>
    • 사용 목적

      • 모든 JSP 페이지에서 사용하는 변수 지정
      • 모든 페이지에서 중복되는 간단한 문장을 추가
    • 코드 조각 자동 포함 기능

      <jsp-config>
      	<jsp-property-group>
      		<url-pattern>/view/*</url-pattern>
      		<include-prelude>/common/variable.jspf</include-prelude>
      		<include-coda>/common/footer.jspf</include-coda>
      	</jsp-property-group>
      </jsp-config>
    • <jsp-property-group> : JSP의 프로퍼티를 포함

    • <url-pattern> : 프로퍼티를 적용할 JSP 파일의 URL 패턴을 지정

    • <include-prelude> : url-pattern 태그에 지정한 패턴에 해당하는 JSP 파일의 앞에 삽입할 파일을 지정

    • <include-coda> : url-pattern 태그에 지정한 패턴에 해당하는 JSP 파일의 뒤에 삽입할 파일을 지정

스크립트 요소

  • JSP에서 문서의 내용을 동적으로 생성하기 위해 사용되는 것

  • 스크립트 요소 종류

    • 표현식(Expression) : 값을 출력
    • 스크립트릿(Scriptlet) : 자바 코드를 실행
    • 선언부(Declaration) : 자바 메소드 생성
  • 장점

    • 자바 문법을 그대로 사용할 수 있어 자바 언어의 특징을 그대로 이용할 수 있음.
  • 단점

    • 스크립트 요소로 인해 JSP 코드가 복잡해짐.
  • 스크립트릿(Scriptlet) 세부 설명

    • JSP 페이지에서 자보 코드를 실행할 때 사용하는 코드 블록
    • 스크립트릿 내부에서 메소드 선언 불가(_jspService메소드 내부에 자바 코드가 추가되는 것이기 때문.)
    • 형태
      <%
      	자바 코드1;
      	자바 코드2;
      %>
  • 표현식(Expression) 세부 설명

    • 어떤 값을 출력 결과에 포함시키고자 할 때 사용
    • 변수 뿐만아니라 숫자, 문자열 등의 값을 표현할 때도 사용
    • 형태
      <%= 출력값%>
  • 선언부(Declaration) 세부 설명

    • 스크립트릿이나 표현식에서 사용할 수 있는 메소드를 작성할 때 사용
    • 선언부에 선언된 자바 메소드 및 변수들은 전부 전역으로 생각.
    • 형태
      <%! 
      	자바 변수;
      	자바 메소드;
      %>

기본 객체

  • 웹 어플리케이션 프로그래밍을 하는 데 필요한 기능을 기본적으로 제공

  • 기본 객체는 request, response, session, application, page 등 많은 기본 객체 존재

  • request 기본 객체 세부 설명

    • 웹 브라우저의 요청과 관련있음
    • 제공 기능
      • 클라이언트와 관련된 정보 읽기
      • 서버와 관련된 정보 읽기
      • 클라이언트가 전송한 요청 파라미터 읽기
      • 클라이언트가 전송한 요청 헤더 읽기
      • 클라이언트가 전송한 쿠키 읽기
      • 속성 처리
    • 클라이언트 및 서버 정보 관련 메소드
      • getRemoteAddr() : 웹서버에 연결한 클라이언트 IP 주소 가져옴.
      • getContentLength() : 클라이언트가 전송한 요청 정보의 길이를 구함. 길이를 알수 없는 경우 -1 반환
      • getCharacterEncoding() : 클라이언트가 요청 정보를 전송할 때 사용한 문자 인코딩을 가져옴.
      • getContentType() : 클라이언트가 요청 정보를 전송할 때 사용한 컨텐츠의 타입을 가져옴.
      • getProtocol() : 클라이언트가 요청한 프로토콜을 가져옴.
      • getMethod() : 웹 브라우저가 정보를 전송할 때 사용한 방식 반환
      • getRequestURI() : 웹 브라우저가 요청한 URL에서 경로를 구함.
      • getContextPath() : JSP 페이지가 속한 웹 어플리케이션의 컨텍스트 경로를 구함.
      • getServerName() : 연결할 때 사용한 서버이름을 구함.
      • getServerPort() : 서버가 실행중인 포트 번호를 구함.
    • 요청 파라미터 관련 메소드
      • getParameter(name속성값) : name 속성값인 파라미터의 값을 구함. 없을 경우 NULL 반환
      • getParameterValues(name속성값) : name 속성값인 모든 파라미터의 값을 배열로 구함. 없을 경우 NULL 반환
      • getParameterNames() : 웹 브라우저가 전송한 파라미터의 이름 목록을 구함.
      • getParameterMap() : 웹 브라우저가 전송한 파라미터의 맵을 구함. 키와 값으로 구성
    • 헤더 관련 메소드
      • getHeader(name) : 지정한 이름의 헤더 값을 구함.
      • getHeaders(name) : 지정한 이름의 헤더 목록을 구함.
      • getHeaderNames() : 모든 헤더의 이름을 구함.
      • getIntHeader(name) : 지정한 헤더의 값을 정수 값으로 읽어옴.
      • getDateHeader(name) : 지정한 헤더의 값을 시간 값으로 읽어옴.
    • 속성 처리 메서드
      • setAttribute(name, value) : 이름이 name, 속성의 값을 value로 지정
      • getAttribute(name) : 이름이 name인 속성의 값을 반환, 없으면 null 반환.
      • removeAttribute(name) : 이름이 name인 속성을 삭제
      • getAttributeNames() : 속성 이름 목록을 반환
  • response 기본 객체 세부 설명

    • 웹 브라우저에 보내는 응답 정보를 가지고 있음.
    • 제공 기능
      • 헤더 정보 입력
      • 리다이렉트 하기
    • 헤더 추가 관련 메소드
      • addDateHeader(name,date) : name 헤더에 date를 추가
      • addHeader(name, value) : name 헤더에 value값을 추가
      • addIntHeader(name, intvalue) : name 헤더에 정수 값 추가
      • setDateHeader(name, date) : name 헤더값을 date로 지정
      • setHeader(name, value) : name 헤더값을 value로 지정
      • setIntHeader(name, intvalue) : name 헤더값을 정수 값으로 지정
      • containsHeader(name) : 이름이 name인 해더를 포함하고 있는지 체크
    • 캐시 관련 헤더
      • Cache-Control
        • HTTP 1.1 버전에서 지원하는 헤더
        • no-cache로 지정하면 웹 브라우저는 응답 결과를 캐시하지 않지만 응답 내용을 캐시 저장소에 보관할 수 있음.
        • no-store를 추가하면 응답 결과를 캐시 저장소에 보관하지 않음.
      • Pragma
        • HTTP 1.0 버전에서 지원하는 헤더
        • no-chache로 지정하면 웹 브라이저는 응답 결과를 캐시에 저장하지 않음.
      • Expires
        • HTTP 1.0 버전에서 지원하는 헤더
        • 응답 결과의 만료일을 지정, 현재 시간보다 이전으로 설정하여 캐시에 저장하지 않음.
    • 리다이렉트 기능
      • 웹 서버 측에서 웹 브라우저에게 어떤 페이지로 이동하라고 지정하는 것
      • 형태 : response.sendRedirect(경로)
  • out 기본 객체 세부 설명

    • 웹 브라우저에 데이터를 전송하는 출력 스트림으로 JSP 페이지가 생성한 데이터를 출력
    • 출력 메소드
      • print(데이터) : 데이터를 출력
      • println(데이터) : 데이터를 출력하고 줄바꿈 문자를 출력
      • newLine() : 줄바꿈 문자 출력
    • out 기본 객체와 버퍼의 관계
      • JSP 페이지가 실제로 사용하는 버퍼는 out 기본 객체가 내부적으로 사용함.
    • 버퍼 관련 메소드
      • getBufferSize() : 버퍼 크기를 반환.
      • getRemaining() : 현재 남은 버퍼 크기 반환.
      • clear() : 버퍼를 비움, 이미 버퍼를 플러시했으면 IOException 발생.
      • clearBuffer() : 버퍼를 비움, clear() 메소드와 다르게 이미 버퍼를 플러시했어도 IOException을 발생하지 않음.
      • flush() : 버퍼에 있는 출력 데이터를 클라이언트에게 전송.
      • isAutoFlush() : Page 디렉티브의 autoFlush 속성값을 리턴
  • pageContext 기본 객체 세부 설명

    • JSP 페이지에 대해 1:1로 연결된 객체이며 JSP페이지당 하나의 pageContext객체가 생성
    • pageContext 기본 객체의 기능
      • 기본 객체 구하기
      • 속성 처리
      • 페이지의 흐름 제어
      • 에러 데이터 구하기
    • 접근 메소드
      • getRequest() : request 기본 객체 반환
      • getResponse() : response 기본 객체 반환
      • getSession() : session 기본 객체 반환
      • getServletContext() : application 기본 객체 반환
      • getServletConfig() : config 기본 객체 반환
      • getOut() : out 기본 객체 반환
      • getException() : exception 기본 객체 반환
      • getPage() : page 기본 객체 반환
    • 속성 처리 메서드
      • setAttribute(name, value) : 이름이 name, 속성의 값을 value로 지정
      • getAttribute(name) : 이름이 name인 속성의 값을 반환, 없으면 null 반환.
      • removeAttribute(name) : 이름이 name인 속성을 삭제
      • getAttributeNames() : 속성 이름 목록을 반환
  • application 기본 객체 세부 설명

    • 웹 어플리케이션 전반에 걸쳐서 사용되는 정보를 담고있음.
    • 웹 어플리케이션 초기화 파라미터 관련 메소드
      • 우선적으로 web.xml 파일에 초기화할 파라미터를 <context-param> 태그를 사용하여 추가.
      • web.xml 파일은 웹 어플리케이션을 위한 설정 정보를 담고 있는 파일, WEB-INF폴더에 위치.
      • getInitParameter(name) : 이름이 name인 웹 어플리케이션 초기화 파라미터의 값 반환, 없으면 null 반환.
      • getInitParameterNames() : 웹 어플리케이션 초기화 파라미터의 이름 목록을 반환.
    • 서버 정보 관련 메소드
      • getServerInfo() : 서버 정보를 반환
      • getMajorVersion() : 서버가 지원하는 서블릿 규약의 메이저 버전 반환.
      • getMinorVertion() : 서버가 지원하는 서블릿 규약의 마이너 버전 반환.
    • 로그 기록 관련 메소드
      • log(msg) : msg를 로그로 남김.
      • log(msg, 예외) : 예외 정보와 msg를 로그로 남김.
    • 자원 접근 관련 메소드
      • getRealPath(path) : 웹 어플리케이션 내에서 지정한 경로에 해당하는 자원의 시스템상에서의 결로 반환
      • getResource(path) : 웹 어플리케이션 내에서 지정한 경로에 해당하는 자원에 접근할 수 있는 URL 객체 반환
      • getResourceAsStream(path) : 웹 어플리케이션 내에서 지정한 경로에 해당하는 자원으로부터 데이터를 읽어올 수 있는 InputStream을 반환
    • 속성 처리 메서드
      • setAttribute(name, value) : 이름이 name, 속성의 값을 value로 지정
      • getAttribute(name) : 이름이 name인 속성의 값을 반환, 없으면 null 반환
      • removeAttribute(name) : 이름이 name인 속성을 삭제
      • getAttributeNames() : 속성 이름 목록을 반환
  • session 기본 객체 세부 설명

    • 웹 브라우저의 여러 요청을 처리하는 JSP 페이지 사이 에서 공유해준다.
    • 속성 처리 메서드
      • setAttribute(name, value) : 이름이 name, 속성의 값을 value로 지정
      • getAttribute(name) : 이름이 name인 속성의 값을 반환, 없으면 null 반환.
      • removeAttribute(name) : 이름이 name인 속성을 삭제
      • getAttributeNames() : 속성 이름 목록을 반환
    • 세션 정보 관련 메서드
      • getId() : 세션의 고유 ID를 반환
      • getCreationTime() : 세션이 생성된 시간을 반환
      • getLastAccessedTime() : 웹 브라우저가 가장 마지막에 세션에 접근한 시간을 반환
  • JSP 기본 객체와 영역

    • PAGE 영역
      • 하나의 JSP 페이지를 처리할 때 사용되는 영역
      • 오직 하나의 JSP 페이지만 포함
      • pageContext 기본 객체
    • REQUEST 영역
      • 하나의 HTTP 요청을 처리할 때 사용되는 영역
      • 웹 브라우저가 요청을 보낼 때마다 새로운 REQUEST영역이 생성
      • PAGE 영역과 다르게 REQUEST영역은 하나의 요청을 처리하는 데 사용되는 모든 JSP 페이지를 포함함.
      • request 기본 객체
    • SESSION 영역
      • 하나의 웹 브라우저와 관련된 영역
      • session 기본 객체
    • APPLICATION 영역
      • 하나의 웹 어플리케이션과 관련된 전체 영역
      • 모든 요청과 세션을 포함
      • application 기본 객체

표현 언어

  • 값을 표현하는 데 사용하는 스크립트 언어, JSP 스크립트 요소를 보완하는 역활
  • 표현언어의 기능
    • JSP의 네가지 기본 객체가 제공하는 영역(PAGE, REQUEST, SESSION, APPLICATION)의 속성 사용
    • 수치 연산, 관계 연산, 논리 연산자 제공
    • 자바 클래스 메소드 호출 기능 제공
    • 쿠키, 기본 객체의 속성 등 JSP를 위한 표현 언어의 기본 객체 제공
    • 람다식을 이용한 함수 정의와 실행 (표현언어 3.0버전부터 가능)
    • 스트림 API를 이용한 컬렉션 처리 (표현언어 3.0버전부터 가능)
    • 정적 메소드 실행 (표현언어 3.0버전부터 가능)
  • 표현언어의 장점
    • 스크립트 요소를 표현 언어를 통해 코드를 간결하고 이해하기 좋게 만듬
    • 액션 태그의 속성값, 비스크립트 요소 부분에서도 사용 가능
  • 표현언어 형태
    // 아래 두 표현식의 차이점은 실제 표현언어의 값을 생성 시간이 차이남.
    // $와 {}를 이용
    // ${표현식}을 분석할 때 곧바로 값을 계산
    ${표현식}
    // #과 {}를 이용
    // #{표현식}은 실제로 값을 사용할 때 값을 계산
    #{표현식}
  • 표현언어 기초
    • 데이터 타입과 리터럴
      • 불리언 타입(true/false), 정수 타입, 실수 타입(소수점, 지수형 표현 가능), 문자열 타입(), null 타입을 제공
    • 사용할 수 있는 기본 객체
      • pageContext : JSP의 pageContext 기본 객체와 동일
      • pageScope : pageContext 기본 객체에 저장된 속성을 매핑한 Map 객체
      • requestScope : request 기본 객체에 저장된 속성을 매핑한 Map 객체
      • sessionScope : session 기본 객체에 저장된 속성을 매핑한 Map 객체
      • applicationScope : application 기본 객체에 저장된 속성을 매핑한 Map 객체
      • param : 요청 파라미터를 매핑한 Map 객체, request.getParameter(키)와 동일
      • paramValues : 요청 파라미터를 매핑한 Map 객체, request.getParameterValues(키)와 동일
      • header : 요청 정보의 헤더이름과 값을 매핑한 Map 객체, request.getHeader(키)와 동일
      • headerValues : 요청 정보의 헤더 이름과 값 배열을 매핑한 Map 객체, request.getHeaders(키)와 동일
      • cookie : 쿠키를 매핑한 Map 객체, request.getCookies()와 동일
      • initParam : 초기화 파라미터를 매핑한 Map 객체, application.getInitParameter(키)와 동일
      • 객체 접근 방법
        • 객체에 저장된 값에 접근할 때 점이나 대괄호를 사용
          // 접근 방법 1
          ${표현1.표현2}
          // 접근 방법 2
          ${표현1[표현2]}
    • 객체 탐색
      • pageScope 기본 객체 (PAGE 영역), requestScope 기본 객체(REQUEST 영역), sessionScope 기본 객체 (SESSION 영역), applicationScope 기본 객체 (APPLICATION 영역)
      • 이름만 지정할 경우 위 4개의 영역을 차례대로 검색해서 속성이 존재하는 지 확인
    • 수치 연산자
      • 종류 : + 연산자, - 연산자, * 연산자, /(div) 연산자, %(mod) 연산자, - 단항 연산자
      • 수치 연산자 규칙(+, -, *, %)
        1. ${A+B} 형태의 연산일 때
        2. A와 B가 null이면, Long 타입 0 반환
        3. 둘 중 하나가 BigDecimal이면 다른 하나도 BigDecimal로 변환 후 연산
        4. 둘 중 하나가 실수형일 때
          3-1. 다른 하나가 BigInteger이면 BigDecimal로 변환 후 연산
          3-2. 다른 하나가 BigInteger가 아니면 모두 실수형으로 변환 후 연산
        5. 둘중 하나가 BigInteger이면 둘다 BigInteger로 변환 후 연산
        6. 1~4번 규칙에 해당하지 않으면 Long으로 변환 후 연산
        7. 변환/연산에 실패하면 오류 발생
          ※ 나누기 연산(/)은 1,2,3,6번 규칙이 해당됨.
      • 단항 연산자 규칙
        1. ${-value} 형태의 연산일 때
        2. value가 null이면 Long 타입 0 반환
        3. value가 BigDecimal/BigInteger이면 A.negate() 리턴
        4. value가 문자열, 점이나 e, E를 포함하면 실수형으로 변환 후 연산
        5. value가 문자열이면 Long 타입으로 변환 후 연산
        6. value가 Byte, Short, Integer, Long, Float, Double 타입이면 그대로 유지하고 연산
        7. 위 규칙이 모두 아니면 에러 발생
      • 주의사항
        • 문자열 + 숫자 형식으로 왔을 때 문자열이 정수나 실수일 경우 숫자로 변환 후 계산 진행, 숫자로 변환할 수 없는 문자열이 오면 오류 발생
    • 비교 연산자
      • 자바 연산자와 동일한 방법으로 사용
      • 종류 : ==(eq), !=(ne), <(lt), >(gt), <=(le), >=(ge)
      • 형태
        // String.compareTo() 메소드를 사용하는 것과 동일
        ${someValue == value}
    • 논리 연산자
      • 종류 : &&(and), ||(or), !(not)
    • empty 연산자
      • 검사할 객체가 텅 빈 객체인지를 검사하기 위해 사용
      • 형태
        // null, 빈 문자열, 길이가 0인 배열, 빈 Map, 빈 Collection 이면 true 반환
        // 이외의 경우에는 false 반환
        ${empty 값}
    • 비교 선택 연산자
      • 삼항 연산자와 비슷
      • 형태
        // true이면 값1 반환, false이면 값2 반환
        ${조건 ? 값1 : 값2}
    • 문자열 연결
      • 표현언어 3.0 버전부터 +=(문자열 연결)연산자 추가
      • 형태
        ${문자열 += 문자열}
    • 컬렉션
      • <c:set> 태그는 JSTL 라이브러리이다.
      • 표현언어로 List 객체 생성
        1. List 생성 방법
          // 대괄호를 이용해 리스트를 생성, 접근할 때는 변수명[인덱스]
          // <c:set> 태그를 사용해서 생성
          <c:set var="변수명" values"${[1,2,3,4]}" />
          ${myfunc:sum(vals)}
          
          // 표현언어 변수가 필요없으면
          ${myfunc:sum([1,2,3,4])}
        2. Map 생성 방법
          // 키:값 형태로 저장
          <c:set var="변수명" value="${ {키1:값1, 키2:값2} }"
          ${변수명.키1}
        3. Set 생성 방법
          // {원소1, 원소2, ...}
          <c:set var="변수명" value="${ {값1, 값2, 값3} }"
          ${변수명}
    • 세미콜론 연산자
      • ${A;B}일 때 A값은 출력되지 않고 B값만 출력
    • 할당 연산자
      • 표현언어 3.0에서 제공
      • 할당 연산자 자체도 출력 결과를 생성하는 점 주의
    • 특수 문자 처리
      • 역슬래시를 이용
  • 표현언어에서 객체 메소드 호출
    • 표현언어 2.2 부터 메소드를 호출 가능
    • 정적 메소드 호출하기 (표현언어 2.2이상)
      • 정적 메소드 작성 -> TLD 파일 작성 -> web.xml 파일에 TLD파일 설정 추가 -> 표현언어에서 함수 사용
    • 정적 메소드 호출하기 (표현언어 3.0이상)
      • 정적 메소드 작성 -> JSP 코드 작성
  • 람다식
    • 함수처럼 파라미터를 가진 코드 블록
    • 재귀호출도 가능
    • 형식
      ${(파라미터1, 파라미터2) -> 표현언어식}
      ${함수명 = (파라미터1, 파라미터2) -> 표현언어식 ; ''}
  • 스트림 API 사용
    • stream()
      • 표현언어에서 제공하는 메소드
      • 스트림 객체를 생성하여 중간 변환과 최종 연산을 통해 새로운 결과 생성
      • Map 값에 대해서는 스트림을 지원하지 않음. Map.entrySet()을 통해 stream을 생성해야함
    • filter()
      • 값을 걸러낼 때 사용
      • 람다식을 파라미터로 가짐
      • 스트림의 각 원소에 대해 람다식을 실행하고 결과가 true인 원소를 제공하는 새로운 스트림을 생성
    • map()
      • 람다식을 파라미터로 가짐
      • 스트림의 각 원소에 대해 람다식을 실행하고 람다식의 결과로 구성된 새로운 스트림 생성
      • 컬랙션에 포함된 원소에서 특정 값을 추출하는 용도로 적합
    • sort()
      • 오름차순으로 정렬한 결과를 구하는 표현언어 메소드
      • 원소를 정렬할 때 Comparable 인터페이스로 구현되지 않은 타입의 원소는 정렬할 수 없음.
      • Comparable 인터페이스로 구현되지 않은 원소는 람다식을 통해 따로 정렬 알고리즘을 작성해야함.
    • limit()
      • 지정한 개수를 갖는 새로운 스트림을 생성
    • toList()와 toArray()
      • toList()는 자바 리스트 객체를 생성, toArray()는 자바 배열 객체를 생성
      • toList()는 리스트에 존재하는 각 원소의 값을 문자열로 변환해서 출력, toArray()는 배열 객체를 문자열로 변환하여 출력
    • count()
      • 스트림의 원소 개수를 리턴
    • Optional 타입
      • 원소가 하나도 없는 스트림에서 연산을 진행했을 때 결과값이 존재하거나 존재하지 않는 경우가 있을 때 사용하는 타입
      • 제공 메소드
        • get() : 값이 존재할 경우 해당 값 반환, 없으면 ELException 발생
        • orElse(value) : 값이 존재하면 해당 값 반환, 없으면 value 반환
        • orElseGet(람다식) : 값이 존재하면 해당 값 반환, 없으면 람다식을 실행한 결과 반환
        • ifPresent(람다식) : 값이 존재하면 람다식 실행
    • sum(), average(), min(), max()
      • sum() : 원소들의 합을 구함
      • average() : 원소들의 평균을 구함
      • min() : 최소값
      • max() : 최대값
    • anyMatch(), allMatch(), noneMatch()
      • anyMatch(람다식) : 스트림에 조건을 충족하는 요소가 존재하는지 검사
      • allMatch(람다식) : 스트림의 모든 원소가 조건을 충족하는지 검사
      • noneMatch(람다식) : 스트림의 모든 원소가 조건에 충족하지 않는지 검사

표준 액션 태그와 태그 라이브러리

  • 액션 태그
    • JSP 페이지에 특별한 기능을 제공
    • 형태 : <JSP:액션태그이름>
    • 액션 태그 종류에 따라 서로 다른 속성과 값을 가짐
  • 커스텀 태그
    • JSP를 확장시켜주는 기능
    • 개발자가 직접 개발
    • JSP코드 에서 중복되는 것을 모듈화하거나 스크립트 코드를 사용할 때 발생하는 소스 코드의 복잡함을 없애기 위해 사용
  • 태그 라이브러리 JSTL(JavaServer Pages Standard Tag Library)
    • 커스텀 태그 중 자주 사용하는 것들을 별도로 표준화한 태그 라이브러리
    • 종류 : 코어 라이브러리, XML 라이브러리, 국제화 라이브러리, 데이터베이스 라이브러리, 함수 라이브러리
    • 사용 시 추가 코드
      <%@ taglib prefix="라이브러리명" uri="http://java.sun.com/jsp/jstl/라이브러리명" %>
  • 코어 태그 라이브러리
    • 변수 설정이나 논리 처리에 사용되는 스크립트 코드를 대체하는 태그 제공
    • 변수 지원 태그
      • JSTL이 지원하는 태그에서 사용할 수 있는 변수를 설정하기 위해 사용
      • <c:set> 태그
        • 표현언어 변수의 값이나 표현언어 변수의 프로퍼티 값을 지정
        • 표현언어 변수 생성
          <c:set>의 속성
          - var : 값을 저장할 표현언어 변수의 이름 지정
          - value : 표현식, 표현언어, 텍스트를 이용해 변수의 값을 지정
          - scope : 변수를 저장할 영역 지정, 지정하지 않으면 page가 기본값으로 지정
                 (page, request, session, application 중 하나가옴)
          
          <c:set var="변수명" value="" [scope="영역"]/>
          <c:set var="변수명" [scope="영역"]></c:set>
        • 객체의 프로퍼티 값을 설정
          <c:set>의 속성
          - target : 프로퍼티 값을 설정할 대상 객체를 지정, 표현식이나 표현언어 사용 가능
                    대상 객체는 자바빈 객체나 Map에 있어야함
          - property : 설정할 프로퍼티 이름 지정
                     자바빈 객체인 경우 프로퍼티 이름에 해당하는 set 메소드를 제공해야함
          - value : 프로퍼티의 값을 지정
          
          주의사항
          - target 속성을 설정할 때 표현언어 변수의 이름만 지정하는 실수 주의
            (${표현언어 이름} 형태로 설정)
          
          <c:set target="대상객체" property="프로퍼티이름" value="" />
          <c:set var="대상객체" property="프로퍼티이름"></c:set>
      • <c:remove> 태그
        • set 태그로 지정한 변수를 삭제
        • 형태
          주의사항
           - scope를 지정하지 않으면 동일한 이름으로 저장된 모든 영역의 변수를 삭제
          
          <c:remove var="변수이름" [scope="영역"] />
    • 흐름 제어 태그
      • JSTL에서 많이 사용되는 태그로 코드 복잡함을 없애기 위해 사용
      • <c:if> 태그
        • 자바의 if문과 비슷한 기능 제공
        • 형태
          <c:if>의 속성
          - test : 조건을 판별하여 참이면 태그의 내부 코드를 실행
                    표현식, 표현언어, 정적 문자열을 사용 가능
          
          <c:if test="조건">
          	내부 코드
          </c:if>
      • <c:choose>, <c:when>, <c:otherwise> 태그
        • <c:choose> 태그는 자바의 switch 구문과 if-else 블록을 혼합한 형태, 다수의 조건문을 하나의 블록에서 수행할 때 사용
        • <c:when> 태그는 조건이 참인 해당 몸체 내용만 실행한 이후 <c:when>태그는 실행되지 않음
        • <c:otherwise> 태그는 모든 <c:when>태그가 false일 때 실행
        • 형태
          <c:choose>
          	<c:when test="조건1">
          		내부 코드1
          	</c:when>
          	<c:when test="조건2">
          		내부 코드2
          	</c:when>
          	<c:otherwise>
          		내부 코드3
          	</c:otherwise>
          </c:choose>
      • <c:forEach> 태그
        • 배열, Collection, Map에 저장되어 있는 값들을 순차적으로 처리할 때 사용
        • 형태
          <c:forEach> 태그의 속성
          - index : 루프 실행에서 현재 인덱스
          - count : 루프 실행 횟수
          - begin : 시작인덱스 설정
          - end : 끝 인덱스 설정
          - step : 증가 숫자 설정
          - first : 현재 실행이 첫 번째 이면 true
          - last : 현재 실행이 루프의 마지막 실행인 경우 true
          - current : 컬렉션 중 현재 루프에서 사용할 객체 
          
          // Map, 배열, Collection일 경우
          // begin과 end로 범위를 설정해 줄수 있음.
          // varStatus : 루프 정보를 담은 객체를 저장할 변수명
          <c:forEach var="변수" items="Map/배열/Collection" varStatus="인덱스명">
          	내부 코드
          </c:forEach>
          
          // for문처럼 사용
          <c:forEach var="변수" begin="시작숫자" end="끝숫자" step="증가숫자">
          	내부 코드
          </c:forEach>
      • <c:forTokens> 태그
        • StringTokenizer 클래스와 같은 기능을 제공
        • 형태
          <c:forTokens>의 속성
          - items : 구분자를 통해 분리할 문자열을 입력
          - delims : 분리할 때 사용할 구분자
          - 그외 나머지 속성은 <c:forEach>와 동일
          
          <c:forTokens var="변수명" items="분리할 문자열" delims="구분자">
          	${item}
          </c:forTokens>
    • URL 처리 태그
      • URL 관련 처리를 해줌
      • <c:url> 태그
        • URL을 생성해주는 기능 제공
        • 형태
          <c:url>의 속성
          - value : 읽어올 URL, 절대 URL과 상대 URL로 지정 가능
          - var : 읽어론 결과를 저장할 변수, 지정 않하면 현재 위치에 생성한 URL 출력
          - scope : 변수를 저장할 영역
          
          <c:url value="URL" var="변수명" scope="영역">
          	내부 코드
          </c:url>
      • <c:redirect> 태그
        • responese.sendRedirect() 메소드처럼 지정한 페이지로 리다이렉트 시켜주는 기능 제공
        • 형태
          <c:redirect>의 속성
          - url : 리다이렉트할 URL
          - context : 컨텍스트 경로
          
          <c:redirect url="URL" context="컨텍스트 경로">
          	내부 코드
          </c:redirect>
    • 기타 코어 태그
      • <c:out> 태그
        • JspWriter에 데이터를 출력할 때 사용되는 태그
        • 형태
          <c:out>의 속성
          - value : JspWriter에 출력할 값을 나타냄.
          		  값이 java.io.Reader의 한 종류면 Reader로부터 데이터를 읽어와 출력.
          - escapeXml : true이면 <,>,&,',"와 같은 문자를 &li;와 같은 형태로 변경
          - default : value 속성에서 지정한 값이 없으면 사용될 값을 지정
          
          <c:out value="출력할 값" escapeXml="참/거짓">
          	기본값
          </c:out>
          
          <c:out value="출력할 값" escapeXml="참/거짓" default="기본값"/>
      • <c:catch> 태그
        • 발생한 예외를 EL변수에 저장할 때 사용되는 태그
        • 형태
          <c:catch var="설정할이름">
          	예외가 발생할 수 있는 코드
          </c:catch>
  • 국제화 태그
    • 로케일 지정 태그
      • <fmt:setLocale>
        • 국제화 태그들이 사용할 로케일을 지정
        • Accept-Language 헤더에서 지정한 언어가 아닌 다른 언어를 사용하도록 지정할 때 사용
        • 형태
          <fmt:setLocale value="설정할 언어" scope="지정한 Locale이 영향을 비치는 범위" />
      • <fmt:requestEncoding>
        • 요청 파아미터의 캐릭터 인코딩을 지정
        • 형태
          <fmt:requestEncoding value="인코딩방식" />
    • 메시지 처리 태그
      • <fmt:bundle> 태그
        • 태그 몸체에서 사용할 리소스 번들을 지정
        • 형태
          <fmt:bundle>의 속성
          - basename : 사용할 리소스 번들의 이름
          - prefix : bundle 태그의 내부에서 사용되는 message 태그의 key 속성의 값 앞에 자동으로 붙게 될 문자열
          
          <fmt:bundle value="인코딩방식" prefix="message 태그 key값 앞에 붙는 문자열"/>
      • <fmt:message> 태그
        • 지정한 리소스 번들로부터 메시지를 읽어와 출력
        • 형태
          <fmt:message>의 속성
          - key : 읽어올 메시지의 키 값
          - var : 메시지를 저장할 변수 명
          - scope : 변수가 저장되는 영역
          - bundle : <fmt:setBundle> 태그를 사용해서 로딩한 번들로부터 메시지를 읽어올때 사용
          <fmt:message value="인코딩방식" prefix="message 태그 key값 앞에 붙는 문자열"/>
      • <fmt:setBundle> 태그
        • 특정 메시지 번들을 사용할 수 있도록 로딩
        • 리소스 번들을 변수로 저장, 어디서나 사용할수 있음
        • 형태
          <fmt:setBundle>의 속성
          - basename : 읽어올 리소스 번들의 이름
          - var : 메시지를 저장할 변수 명
          - scope : 변수가 저장되는 영역
          
          <fmt:setBundle var="저장할 변수" basename="번들이름" scope="저장할 영역"/>
    • 숫자 및 날짜 포맷팅 처리 태그
      • <fmt:formatNumber> 태그
        • 숫자를 양식에 맞춰 출력
        • 형태
          <fmt:formatNumber>의 속성
          - value : 양식에 맞춰 출력할 숫자 지정
          - type : 출력할 양식 설정 (number-숫자, percent-%, currency-통화)
          - pattern : 직접 숫자가 풀력되는 양식 설정(java.text.DecimalFormat에 정의된 패턴 사용)
          - currenctCode : 통화 코드 지정
          - currentSymbol : 통화를 표현할 때 사용할 기호 표시
          - groupingUsed : 단위를 구분할 때 사용되는 기호를 사용할 지의 여부 결정
          - var : 포맷팅한 결과를 저장할 변수 지정
          - scope : 변수를 저장할 영역 지정
          
          <fmt:formatNumber value="숫자" type="출력양식" ... />
      • <fmt:parseNumber> 태그
        • 문자열을 숫자로 변환해주는 기능 제공
        • 형태
          <fmt:parseNumber>의 속성
          - value : 파싱할 문자열 지정
          - type : 출력할 양식 설정
          - pattern : 직접 파싱할 때 사용할 양식 지정
          - parseLocale : 파싱할 때 사용할 로케일 지정
          - integerOnly : 정수만 파싱할지의 여부 지정
          - var : 파싱한 결과를 저장할 변수 지정
          - scope : 변수를 저장할 영역 지정
          
          <fmt:parseNumber value="숫자" type="출력양식" ... />
      • <fmt:formatDate>태그
        • 날짜 정보를 담고 있는 객체를 포맷팅하여 출력할 때 사용
        • 형태
          <fmt:formatDate>의 속성
          - value : 포매팅할 시간 값을 지정
          - type : 날짜, 시간 또는 둘 다 포맷팅할지 여부 지정
          - dateStyle : 날짜에 대해 미리 정의된 포맷팅 스타일 지정
          - timeStyle : 시간에 대해 미리 정의된 포맷팅 스타일 지정
          - pattern : 직접 파싱할 때 사용할 양식을 지정
          - timeZone : 시간대를 변경하고 싶을 때 사용
          - var : 파싱한 결과를 저장할 변수명을 지정
          - scope : 변수를 저장할 영역 지정
          
          <fmt:formatDate value="숫자" type="출력양식" ... />
      • <fmt:parseDate> 태그
        • 문자열로 표시된 날짜와 시간을 Date타입으로 파싱
        • 형태
          <fmt:parseDate>의 속성
          - value : 포매팅할 시간 값을 지정
          - type : 날짜, 시간 또는 둘 다 포맷팅할지 여부 지정
          - dateStyle : 날짜에 대해 미리 정의된 포맷팅 스타일 지정
          - timeStyle : 시간에 대해 미리 정의된 포맷팅 스타일 지정
          - pattern : 직접 파싱할 때 사용할 양식을 지정
          - timeZone : 시간대를 변경하고 싶을 때 사용
          - parseLocale : 파싱할 때 사용할 로케일을 지정
          - var : 파싱한 결과를 저장할 변수명을 지정
          - scope : 변수를 저장할 영역 지정
          
          <fmt:parseDate value="숫자" type="출력양식" ... />
      • <fmt:timeZone> 태그
        • value 속성을 통해 해당 시간대를 출력
        • 형태
          <fmt:timeZone>의 속성
          - value : 포매팅할 시간 값을 지정
          
          <fmt:timeZone value="지역"/>
      • <fmt:setTimeZone> 태그
        • 시간대를 설정
  • JSTL에서 지원하는 EL 함수
    • length(객체) : Collection인 경우 저장된 항목의 개수 리턴
    • toUpperCase(문자열) : 문자열을 대문자로 변환
    • toLowerCase(문자열) : 문자열을 소문자로 변환
    • substring(문자열, 시작위치, 끝위치) : substring(시작위치, 끝위치)와 동일
    • substringAfter(문자열1, 문자열2) : 문자열1에서 문자열1에 포함되어 있는 문자열2 이후의 문자열을 구함
    • substringBefore(문자열1, 문자열2) : 문자열1에서 문자열1에 포함되어 있는 문자열2 이후의 문자열을 구함
    • trim(문자열) : 문자열의 좌우 공백문자 제거
    • replace(문자열, 변경전문자, 변경후문자) : 문자열에 있는 변경 전 문자를 변경 후 문자로 변환
    • indexOf(문자열, 찾을 문자) : 문자열에서 찾을 문자가 위치한 인덱스 반환
    • startsWith(문자열1, 문자열2) : 문자열1이 문자열2로 시작할 경우 참 반환, 아닐 경우 거짓 반환
    • endsWith(문자열1, 문자열2) : 문자열1이 문자열2로 끝날 경우 참 반환, 아닐경우 거짓 반환
    • contains(문자열1, 문자열2) : 문자열1이 문자열2를 포함하고 있는 경우 true반환
    • containsIgnoreCase(문자열1, 문자열2) : 대소문자 구분 없이 문자열1이 문자열2를 포함하고 있을 때 true 반환
    • split(문자열, 구분자) : 문자열을 구분자를 기준으로 문자열을 분리해서 배열로 반환
    • join(array, 문자열) : array에 자장된 문자열을 함침
    • escapeXml(문자열) : XML의 객체 참조에 해당하는 특수 문자를 처리

✏️ 출력 버퍼

출력 버퍼란?

  • 출력 버퍼에 출력 내용을 저장하여 출력 버퍼가 가득차면 한꺼번에 웹 브라우저에 전송

출력 버퍼의 장점

  • 결과 도출 시 마다 데이터를 전송하는 것이 아닌 한 번에 모아서 데이터를 전송하기 때문에 전송시 소모되는 비용이 줄어 데이터 전송 성능이 향상
  • 버퍼를 이용해 <jsp:forward> 기능과 에러 페이지 처리 가능
  • 버퍼가 처음 전송되기 전까지 HTTP 헤더 정보를 변경 가능

출력 버퍼 설정

  • page 디렉티브의 buffer 속성
    • 버퍼의 크기를 지정
  • page 디렉티브의 autoFlush 속성
    • 버퍼가 다 찼을 때 처리 방법 설정
    • true일 때 버퍼를 플러시하고 계속 작업 진행
    • false일 때 익셉션을 발생시키고 작업 중지

✏️ 웹 어플리케이션 폴더 구성과 URL 매핑

웹 어플리케이션 폴더 구조

  • Tomcat에서의 웹 어플리케이션 폴더 구조

    tomcat
    └ webapps
       └ 웹어플리케이션
           └ WEB-INF → 웹 어플리케이션 설정 정보를 담고 있는 web.xml파일 위치
               └ classes → 웹 어플리케이션에서 사용하는 클래스 파일 위치
               └ lib       → 웹 어플리케이션에서 사용하는 jar 파일 위치

  • 웹 어플리케이션 폴더와 URL

      웹 어플리케이션 내 경로               웹 상 경로
    [톰캣]/webapps/[파일경로] -> http :// host:port[/웹경로]

    • '/웹경로'를 컨텍스트 경로(context path)라고 함.
    • request 기본 객체에 getContextPath()메소드를 통해 컨텍스트 경로를 가져올 수 있음.
  • 참고 사이트

✏️ 웹 어플리케이션 배포

대상 폴더에 파일을 직접 복사

  • 톰캣 서버의 특정 폴더에 파일을 직접 복사하는 방식

톰캣에 war 파일 배포

  • war(Web Application Archive)는 웹 어플리케이션의 구성 요소를 하나로 묶어 놓은 파일
  • cmd 명령어 : jar cvf 이름.war *

✏️ 페이지 모듈화와 요청 흐름

<jsp:include> 액션태그

  • 해당 태그가 위치한 부분에 지정한 페이지를 포함
  • 형태
    // include 디렉티브를 이용
    //  - 지정한 페이지가 현재 페이지에 포함되어 하나로 합쳐저 컴파일되서 변수를 서로 공유 가능
    <%@ include file="포함할 페이지 경로" %\>
    
    // 액션태그를 이용
    //  - 두 페이지가 합쳐지는게 아니라 포함할 페이지의 제어권을 넘겼다가 다시 되돌아오는 개념
    //  - 두 페이지가 서로 독립적으로 컴파일되어 변수를 공유 못함.
    <jsp:include page="포함할 페이지 경로" flush="참/거짓">
  • <jsp:include> 액션태그의 속성
    • page : 포함할 JSP 페이지의 경로를 지정
    • flush : 지정한 JSP 페이지를 실행하기전 출력 버퍼를 플러시할지 여부를 지정true이면 출력 버퍼 플러시, flase이면 플러시 하지 않음. 기본값은 false

<jsp:param> 액션태그

  • <jsp:include> 액션 태그의 자식 태그로 추가하여 파라미터를 추가 할 수 있다.
  • 이미 동일한 이름의 파라미터가 존재하면 기존 파라미터 값을 유지하면서 새로운 값을 추가함.
  • 추가한 파라미터는 기존 파라미터보다 우선시 됨.
  • getParameterValues(name)을 사용하면 추가한 파라미터 값과 기존 파라미터 값을 모두 반환.
  • <jsp:param> 액션태그로 추가된 파라미터는 <jsp:include> 액션 태그로 포함하는 페이지에만 유효.
  • <jsp:param> 액션태그는 String 타입의 값만 전달 가능
  • <jsp:param> 액션태그의 속성
    • name : 추가할 파라미터의 이름 설정
    • value : 추가할 파라미터의 값 설정, 직접 지정하거나 표현식을 사용해서 지정 가능

<jsp:forward> 액션태그

  • 하나의 JSP 페이지에서 다른 JSP 페이지로 요청 처리를 전달할 때 사용
  • <jsp:forward> 액션 태그가 실행되기전 작업하던 내용은 출력 버퍼에서 비우고 이동한 JSP 페이지를 출력함.
  • 파라미터에 따라 이동할 페이지가 다를때 많이 사용
  • 형태
    <jsp:forward page="이동할 페이지" />

<jsp:useBean> 액션태그

  • JSP 페이지에서 사용할 자바빈 객체를 지전할 때 사용
  • 객체를 생성하고 지정한 영역에 저장, 이미 존재하면 그 객체를 사용
  • 영역별로 공유할 데이터를 쉽게 자장 가능
  • 형태
    <jsp:useBean id="클래스 객체" class="클래스 경로" scope="request"/>
  • 속성
    • id : 클래스 객체 이름, 없으면 생성 이미 존재하면 해당 객체 사용
    • class : 클래스 경로
    • type : 클래스 경로, 해당 영역에 이미 객체가 존재하다고 가정
    • scope : 저장할 영역

<jsp:setProperty> 액션태그

  • 생성한 자바빈 객체의 프로퍼티 값을 변경
  • 형태
    <jsp:setProperty name="자바빈이름" property="프로퍼티이름" value=""/>
  • 속성
    • name : 사용할 자바빈 객체 이름 지정
    • property : 값을 지정할 프로퍼티의 이름 지정 , '*'로 지정하면 프러퍼티의 값과 같은 이름을 갖는 파라미터로 설정
    • value : 프로퍼티의 값을 지정
    • param : 파라미터 값을 프로퍼티 값으로 지정할 때 사용

<jsp:getProperty> 액션태그

  • 자바빈 객체의 프로퍼티 값을 출력할 때 사용
  • 형태
    <jsp:getProperty name="자바빈이름" property="프로퍼티이름" />
  • 속성
    • name : 사용할 자바빈 객체 이름 지정
    • property : 출력할 프로퍼티 이름 지정

<jsp:attribute> 액션 태그

  • 태그 파일에 선언된 attribute 디렉티브의 fragment 속성값이 true일 경우, JSP 페이지에서 해당 속성값을 전달할 때 <jsp:attribute>를 사용해야함.
  • 형태
    // 태그 파일
    <%@ attribute name="속성명" fragment="true" %>
    
    // jsp
    <%@ taglib prefix-"tf" tagdir="해당 태그 파일이 저장된 폴더명" %>
    <tf:태그파일명>
    	<jsp:attribute name="속성명" /> 일반 템플릿 텍스트/EL/<jsp:include> 액션태그</jsp:attribute>
    </tf:태그파일명>
  • 속성
    • name : 속성의 이름 지정
    • trim : 속성값 좌우의 공백문자들을 제거할지 여부 지정

✏️ 쿠키

쿠키란?

  • 웹 브라우저가 보관하는 데이터
  • 쿠키는 웹 서버와 웹 브라우저 양쪽에서 생성 가능

쿠키 동작 방식

  • 쿠키 생성 단계 -> 쿠키 저장 단계 -> 쿠키 전송 단계로 동작됨.
  • 쿠키 생성 단계 : 쿠키 생성한 후 응답 데이터의 헤더에 저장해서 웹 브라우저에 전송
  • 쿠키 저장 단계 : 웹 브라우저는 응답 데이터에 포함된 쿠키를 쿠키 저장소에 보관
  • 쿠키 전송 단계 : 요청이 있을 때마다 웹서버에 전송

쿠키 구성

  • 이름 : 각 쿠키를 구별하는데 사용되는 이름
  • 값 : 쿠키의 이름과 관련된 값
  • 유효시간 : 쿠키 유지 시간
  • 도메인 : 쿠키를 전송할 도메인
  • 경로 : 쿠키를 전송할 요청 경로

쿠키 다루기

  • 쿠키 생성

    • Cookie 클래스를 이용해 쿠키 생성
    • 쿠키 생성 코드
      <%
      	// 쿠키 객체 생성
      	Cookie cookie = new Cookie("cookieName", "cookieValue");
      	// response 기본 객체를 통해 웹 브라우저에 쿠키 정보 전송
      	response.addCookie(cookie);
      %>
    • Cookie 클래스가 제공하는 메소드
      • getName() : 쿠키 이름 반환
      • getValue() : 쿠키 값 반환
      • setValue(값) : 쿠키 값을 지정
      • setDomain(도메인) : 쿠키가 전송될 서버의 도메인을 지정
      • getDomain() : 쿠키 도메인 반환
      • setPath(URL) : 쿠키를 전송할 경로 지정
      • getPath() : 쿠키의 전송 경로 반환
      • setMaxAge(값) : 쿠키의 유효시간을 초 단위로 지정, 음수이면 웹브라우저를 닫을 때 쿠키 삭제
      • getMaxAge() : 쿠키 유효시간 반환
  • 쿠키 값 읽기

    • request를 통해 쿠키 값을 읽을 수 있음.
    • 쿠키 읽기 코드
      <%
      	// getCookies() 메소드는 Cookie배열로 리턴, 없으면 NULL리턴
      	Cookie[] cookie = request.getCookies();
      %>
  • 쿠키 값 변경

    • 쿠키 값을 변경하려면 같은 이름의 쿠키를 새로 생성해서 응답 데이터로 보내면 됨.
  • 쿠키 삭제

    • setMaxAge() 메소드를 이용해 값을 0이하로 할당해주면 웹브라우저가 종료될 때 같이 삭제됨.
  • 쿠키의 도메인

    • 쿠키는 생성한 서버에만 전송이 가능
    • setDomain() 메소드를 이용해 현재 서버 도메인 및 상위 도메인로 쿠키 전달 가능.
  • 쿠키의 경로

    • 쿠키를 공유할 기준 경로를 지정
    • setPath() 메소드를 이용해 경로를 지정하면 웹 브라우저는 지정한 경로 및 하위 경로에 대해서만 쿠키 전송
    • 경로를 지정하지 않으면 실행한 URL 경로를 사용
    • 일반 적으로 웹 어플리케이션에 포함된 다수의 JSP와 서블릿에서 사용되기 때문에 쿠키경로는 '/'로 지정함.
  • 쿠키의 유효시간

    • 쿠키의 유효시간을 설정해놓으면 웹 브라우저를 종료해도 유효시간이 지나지 않은 쿠키는 삭제되지 않는다.
    • 유효시간을 설정하지 않았거나 0, 음수로 설정해 놓았을 경우 웹 브라우저를 종료할 때 쿠키를 함께 삭제한다.
    • setMaxAge() 메소드를 통해 초 단위로 유효 시간을 지정할 수 있음.
  • 쿠키와 헤더

    • response.addCookie()로 쿠키를 추가하면 Set-Cookie헤더를 통해 전달
    • Set-Cookie 헤더 형태
      쿠키이름=쿠키값:Domain=도메인값:Path=경로값:Expires=만료시간

✏️ 세션

세션이란?

  • 웹 컨테이너 정보를 서버에 보관
  • 웹 컨테이너 : 웹 브라우저마다 하나의 세션을 생성, 같은 JSP 페이지라도 웹브라우저에 따라 서로 다른 세션을 사용

쿠키보다 세션을 사용하는 이유

  • 쿠키의 데이터는 로컬에 저장되고, 세션의 값은 서버에 저장되기 때문에 세션이 쿠키보다 보안이 좋음
  • 쿠키를 지원하지 않는 웹브라우저이거나 쿠키사용을 막았을 때 쿠키는 사용할수 없지만, 세션은 쿠키 설정 여부에 상관없이 사용가능함.

세션 다루기

  • 세션 생성

    • JSP페이지에서 page 디렉티브의 session 속성을 true로 지정.
    • request.getSession() 메소드를 이용해 세션 생성 가능
  • 세션 종료

    • session.invalidate() 메소드를 이용해 세션을 종료
    • 현재 사용 중인 session 기본 객체를 삭제하고 session 기본 객체에 저장했던 속성 목록도 함께 삭제
  • 세션 유효 시간

    • session 객체를 사용할 때마다 세션의 접근 시간이 갱신됨.

서블릿과 세션

  • 서로 다른 경로인 페이지 A와 B를 실행했을 때 서로 다른 쿠키 값을 가지게 된다. 서로 다른 쿠키값을 가지게 되는 이유는 두 경로가 서로 다른 웹 어플리케이션이기 때문이다. 그리고 그렇게 생성된 쿠키는 해당 페이지에서만 사용됨.

✏️ JSP에서 JDBC다루기

JDBC 란?

  • 자바 프로그램에서 다른 기종 간의 데이터 베이스를 표준화된 방법으로 접속할 수 있도록 만든 API규격
  • 데이터베이스 업체들이 JDBC 드라이버 제공
  • JDBC API를 사용하면 모든 데이터베이스에서 동작하는 어플리케이션 개발 가능

JDBC 구조

JDBC 구조

JDBC 드라이버 설정

  • 우선 사용하고자 하는 JDBC 드아리버를 해당 사이트에서 다운로드
  • JDBC 드라이버 설정 방법 1
    • 웹 어플리케이션 폴더의 WEB-INF/lib 폴더에 JDBC 드라이버 파일을 복사하면 JDBC 드라이버를 사용할 수 있음
  • JDBC 드라이버 설정 방법 2
    • 이클립스 프로젝트에서 마우스 오른쪽 클릭 -> Build Path -> Configure Build Path로 접속
    • Classpath 선택 후 오른쪽 메뉴 중 Add External JARs... 메뉴 선택
    • JDBC 드라이버 파일 추가
    • Deployment Assembly 메뉴로 이동 후 Add.. 메뉴 선택
    • Java Build Path Entries 선택 후 next
    • Classpath에 추가한 JDBC 드라이버 선택 후 finish
    • Apply and Close 클릭

JDBC 프로그래밍 과정

  • JDBC 드라이버 로딩
    // MySQL : com.mysql.jdbc.Driver
    // 오라클 : oracle.jdbc.driver.OracleDriver
    Class.forName("해당 드라이버 라이브러리 경로");
  • 데이터베이스 연결
    String url = "데이터베이스 URL 경로"; // jdbc:[DBMS]:[데이터베이스식별자]
    String userid = "데이터베이스 ID";
    String password = "데이터베이스 비밀번호";
    
    Connection conn = DriverManager.getConnection(url, userid, password);
  • 쿼리 실행 및 실행 결과 데이터 저장
    // 쿼리 실행 전 SQL문 설정
    String SQL = "select * from table where id=? ";
    preparedStatement pstmt = conn.prepareStatement(SQL);
    pstmt.setString(1, id); // 첫번째 '?' 부분에 들어갈 데이터 설정
    
    // 쿼리 실행 및 결과 데이터 저장
    ResultSet rs = pstmt.executeQuery(SQL); // 거의 select문일 경우에만 executeQuery 사용
    int result = pstmt.executeUpdate(); // insert, update, delete의 성공 여부 반환
  • 쿼리 실행 데이터 확인
    while(rs.next()){
    	String id = rs.getString("fid");
    	int idx = rs.getInt("fidx"); 
    }
  • JDBC 종료
    rs.close(); // ResultSet 종료
    pstmt.close(); // preparedStatement 종료
    conn.close(); // Connection 종료
  • ResultSet 클래스 메소드
    • getString(str|idx) : 지정한 칼럼 값을 String 타입으로 읽어옴
    • getCharacterStream(str|idx) : 지정한 칼럼 값을 스트림 형태로 가져옴. LONG VARCHAR 타입을 읽어올 때 사용

      getCharacterStream 사용 방법

      Reader reader = null;
      try{
      	reader = rs.getCharacterStream("가져올 칼럼명");
      	if(reader != null){
      		StringBuilder buff = new StringBuilder();
      		char[] ch = new char[512];
      		int len = -1;
      		while((len = reader.read(ch) != -1)){
      			buff.append(ch,0,len);
      		}
      		data = buff.toString();
      	}
      }catch(Exception ex){
      	예외처리
      }finally{
      	// Reader 종료
      	if(reader != null) try{reader.close();} catch(IOExeption ex){}
      }
    • getInt(str|idx) : 지정한 칼럼 값을 int 타입으로 읽어옴
    • getLong(str|idx) : 지정한 칼럼 값을 long 타입으로 읽어옴
    • getDouble(str|idx) : 지정한 칼럼 값을 double 타입으로 읽어옴
    • getFloat(str||idx) : 지정한 칼럼 값을 float 타입으로 읽어옴
    • getTimestamp(str||idx) : 지정한 칼럼 값을 Timestamp 타입으로 읽어옴
    • getDate(str||idx) : 지정한 칼럼 값을 Date 타입으로 읽어옴
    • getTime(str||idx) : 지정한 칼럼 값을 Time 타입으로 읽어옴

  • PreparedStatement 클래스에서 제공하는 set 메소드
    • setString(idx, str) : 지정한 idx 위치의 파리미터 값을 str으로 지정
    • setCharacterStream(idx, reader, length) : 지정한 idx 위치의 파리미터 값을 LONG VARCHAR 타입의 값으로 지정할 때 사용, reader는 읽어올 스트림, length는 지정한 문자열 길이
    • setInt(idx, int) : 지정한 idx 위치의 파리미터 값을 int으로 지정
    • setLong(idx, long) : 지정한 idx 위치의 파리미터 값을 long으로 지정
    • setDouble(idx, double) : 지정한 idx 위치의 파리미터 값을 double으로 지정
    • setFloat(idx, float) : 지정한 idx 위치의 파리미터 값을 float으로 지정
    • setTimestamp(idx, timestamp) : 지정한 idx 위치의 파리미터 값을 timestamp으로 지정
    • setDate(idx, date) : 지정한 idx 위치의 파리미터 값을 date로 지정
    • setTime(idx, time) : 지정한 idx 위치의 파리미터 값을 time으로 지정
    • 위 메소드들을 사용하면 SQL문에서 '?'로 작성된 부분에 값들이 들어감.

JDBC 트랜잭션 처리

  • 트랜잭션이란?
    • 두 개 이상의 쿼리를 모두 성공적으로 실행해야 데이터가 정상적으로 처리되는 경우 트랜잭션을 이용해 두개 이상의 쿼리를 마치 한개의 쿼리처럼 처리
    • 트랜잭션이 시작 이후에 실행된 쿼리 결과는 DBMS에 바로 반영하지 않고 입시로 보관, 이후 트랜잭션을 Commit하면 임시 보관한 모든 쿼리 결과를 실제 데이터에 반영
    • 트랜잭션 커밋 전에 에러가 발생하면 Rollback을 통해 임시 보관한 모든 쿼리 결과를 취소
  • JDBC의 오토 커밋 모드를 통해 트랜잭션 제어
    • setAutoCommit 메소드의 매개변수값을 false로 전달하여 두 개 이상의 트랜잭션을 묶어 처리 한 후 commit() 메소드를 이용해 DB에 반영, 실패시 rollback() 메소드를 이용해 취소
    • 형태
      Reader reader = null;
      try{
      	conn = DriverManager.getConnection(...);
      	conn.setAutoCommit(false);
      	
      	쿼리문1 실행
      
      	쿼리문2 실행
      	
      	conn.commit(); // 트랜잭션 커밋
      }catch(Exception ex){
      	if(conn != null){ conn.rollback() } // 트랜잭션 롤백
      }finally{
      	...
      }

JDBC 커넥션 풀

  • 커넥션 풀이란?
    • 데이터베이스와 연결된 커넥션을 미리 만들어서 풀 속에 저장해 두고 있다가 필요할 때 커넥션을 풀에서 가져다 쓰고 다시 풀에 반환하는 기법
  • 커넥션 풀의 특징
    • 커넥션을 생성하는 시간을 줄임
    • 커넥션을 계속해서 재사용하기 때문에 생성되는 커넥션 수가 일정하게 유지됨
  • DBCP로 커넥션 풀 사용하기
    • 필요한 jar 파일 복사
      • Commons DBCP API 관련 jar 파일(commons-dbcp2-버전-bin.zip)
      • Commons DBCP API 가 사용하는 Commons Pool API의 jar 파일(commons-pool2-버전-bin.zip)
      • 로그 기록에 사ㅣ용하는 Commons Logging API 관련 jar 파일(commons-logging-버전-bin.zip)
    • 커넥션 풀 초기화 서블릿 코드
      try{
      	String jdbcUrl = "DB경로";
      	String username = "DB아이디";
      	String pw = "DB아이디";
      	
      	ConnectionFactory connFactory = new DriverManagerConnectioinFactory(jdbcUrl, username, pw);
      
      	PoolableConnectionFactory poolableConnFactory = new PoolableConnectionFactory(connFactory, null);
      	poolableConnFactory.setValidationQuery("select 1");
      
      	// 커넥션 풀 설정 세팅
      	GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
      	poolConfig.setTimeBetweenEvictionRunsMillis(1000L * 60L * 5L);
      	poolConfig.setTestWhileIdle(true);
      	poolConfig.setMinIdle(4);
      	poolConfig.setMaxTotal(50);
      	
      	GenericObjectPool<poolableConnection>connectionPool = new GenericObjectPool<>(poolableConnFactory, poolConfig);
      	poolableConnFactory.setPool(connectionPool);
      
      	Class.forName("org.apache.commons.dbcp2.PoolingDriver");
      	PoolingDriver driver = (PoolingDriver)DriverManager.getDriver("jdbc:apache:commons:dbcp:");
      	driver.registerPool("커넥션풀명", connectionPool);
      }
      catch(Exception e){
      	throw new RuntimeException(e);
      }
    • 커넥션 풀 초기화 서블릿 설정
      • web.cml에서 커넥션풀 서블릿 코드를 실행되도록 설정
        <servlet>
        	<servlet-name>DBCPInit</servlet-name>
        	<servlet-class>jdbc.DBCPInit</servlet-class>
        	<load-on-startup>1</load-on-startup>
        </servlet>
    • 커넥션 풀로부터 커넥션 사용하기
      • 커넥션 풀 서블릿 코드 중 PoolingDriver에서 설정한 커넥션 풀 이름을 이용
      • 형태
        jdbc:apache:commons:dbcp:풀이름
      • 코드
        Connection conn = null
        try{
        	String jdbcUrl = "jdbc:apache:commons:dbcp:풀이름";
        	conn = DriverManager.getConnection(jdbcUrl);
        } 
        ...
        finally{
        	if(conn != null) try{conn.close();} catch(SQLException ex){예외처리}
        }
  • GenericObjectPoolConfig 클래스의 커낵션 개수와 대기 관련 설정 메소드
    • setMaxTotal(int) : 풀이 관리하는 커넥션의 최대 개수 설정, 음수면 제한X
    • setMaxIdle(int) : 커넥션 풀이 보관할 수 있는 최대 유휴 개수 지정, 음수면 제한X
    • setMinIdle(int) : 커넥션 풀이 유지할 최소 유휴 커넥션 개수 지정, maxidle보다 크면 maxidle을 minidle 값으로 사용
    • setBlockWhenExhausted(bool) : 풀이 관리하는 커넥션이 모두 사용중인 상태에서 커넥션을 요청할 때 풀에 커넥션이 반환될 때까지 대기할지 여부를 지정
    • setMaxWaitMillis(long) : blockWhenExhausted가 true이면 최대 대기 시간을 설정, 음수면 풀에서 커넥션을 구할 수 있을 때까지 대기
  • GenericObjectPoolConfig 클래스의 유휴 커넥션 제거 및 검사 관련 설정 메소드
    • setTimeBetweenEvictionRunsMillis(long) : 풀에 있는 유휴 커넥션 검사 주기를 설정, 음수면 검사X
    • setNumTestsPerEvictionRun(int) : 각 주기 때마다 검사할 커넥션의 개수를 설정, 음수명 유휴 커넥션 개수를 검사 개수의 절대값으로 나눈값을 사용
    • setMinEvictableIdleTimeMillies(long) : 풀에 머물 수 있는 최소 유휴시간을 설정, 검사할 때 이 시간을 초과한 커넥션이 제거 대상이 됨. 음수면 유휴 시간 검사X
    • setTestWhileIdle(bool) : true면 유휴 커넥션이 유효한지 검사
    • setTestOnBorrow(bool) : true면 커넥션 풀에서 커넥션을 가져올 때 유효한지 검사
    • setTestOnReturn(bool) : true면 커넥션을 풀에 반환할 때 유효한지 검사
  • PoolableConnectionFactory 커넥션 검사 및 설정 메소드
    • setMaxConnLifetimeMillies(long) : 커넥션의 최대 사용 시간을 설정, 양수가 아니면 적용이 안됨.
    • setValidationQuery(Str) : 커넥션을 검사할 때 사용할 쿼리를 설정

✏️ 커스텀 태그 만들기

커스텀 태그

  • 커스텀 태그란?
    • 개발자가 특정 기능을 수행하는 액션태그를 직접 만든 것
  • 커스텀 태그의 장점
    • 재사용 : 한 번 작성한 커스텀 태그는 어떤 JSP 컨테이너에서도 사용 가능
    • 쉽고 단순한 JSP 코드 작성
    • 코드 가독성 향상 : 커스텀 태그를 사용하면 스크립트 코드를 줄일 수 있어 JSP 코드의 가독성을 높임

커스텀 태그 구현

  • 태그 파일을 이용한 커스텀 태그 구현
    • 태그 파일
      • JSP 문법을 사용해서 커스텀 태그로 동작할 수 있도록 만들어진 소스 코드
      • 웹 컨테이너가 자동으로 태그파일을 커스텀 태그 클래스로 변환
    • 태그 파일 위치와 참조 방법
      • 태그 파일은 WEB-INF/tags 폴더나 하위 폴더에 위치
      • .tag/.tagx 확장자를 가진 파일만 태그 파일로 인식
      • 참조 방법
        <%@ taglib prefix="tf" tagdir="WEB-INF/tags/해당 커스텀 태그가 있는 폴더명" %>
        ...
        <tf:사용할태그파일명> ... </tf:사용할태그파일명>
      • 태그 파일에서 사용 가능한 기본 객체
        • jspContext
          • pageContext가 제공하는 setAttribute(), getAttribute() 메소드를 그대로 제공, 각 속성과 관련된 작업 처리
        • request, response, session, application, out
    • 태그 파일에서 사용가능한 디렉티브
      • tag
        • JSP 페이지의 page 디렉티브와 동일
        • 태그 파일의 정보를 명시
      • taglib
        • 태그 파일에서 사용할 태그 라이브러리 명시
      • include
        • 태그 파일에 특정 파일을 포함시킬 때 사용
        • 태그 파일에 포함되는 파일은 태그 파일에 맞는 문법으로 작성되야함.
      • attribute
        • 태그 파일을 커스텀 태그로 사용할 때 입력받을 속성을 명시
      • variable
        • EL 변수로 사용할 변수에 대한 정보를 지정
    • tag 디렉티브 속성
      • display-name
        • 태그 파일을 도구에서 보여줄 때 사용될 이름을 지정
      • body-content
        • 몸체 내용의 종류를 입력
        • empty : 몸체가 비어있음
        • scriptless : 텍스트, EL, JSP 액션 태그는 가능, 스트립트 요소는 불가능 (기본)
        • tagdependent : 몸체의 내용을 문자열로 인식시킬 때 사용
      • dynamic-attributes
        • 동적 속성을 사용할 때 속성의 이름/값을 저장하는 Map 객체를 page범위의 속성에 저장할 때 사용할 이름을 지정
      • description
        • 태그에 대한 설명을 입력
      • import, pageEncoding, isELIgnored, deferredSyntaxAllowedAsLiteral, trimDirectiveWhitespaces
    • attribute 디렉티브 속성
      • description
        • 속성에 대한 설명
      • name
        • 속성 이름 입력
        • attribute 디렉티브의 name속성값은 서로 달라야함.
        • tag 디렉티브의 dynamic-attributes 속성과 variable 디렉티브의 name-given 속성과 동일하면 에러 발생
      • required
        • 속성의 필수 여부 지정
      • rtexprrvalue
        • 속성값으로 표현식을 사용할 수 있는지 여부 지정
      • type
        • 속성값의 타입 설정
        • java.lang.Interger와 같이 래퍼 타입을 사용해야함
      • fragment
        • <jsp:attribute> 액션 태그로 속성값을 전달할 때 이 값을 true로 지정
        • 속성값이 true이면 rtexprvalue 속성은 true, type 속성은 javax.servlet.jsp.tagext.JspFragment로 설정됨.
        • 속성값이 true이면 JSP 페이지에서 속성에 값을 전달할 때 <jsp:attribute> 액션 태그를 사용해야함

몸체 내용 처리

  • EL과 태그를 처리한 몸체 내용 사용
    • 태그 파일의 tag 디렉티브의 body-content 속성값을 scriptless로 지정
    • <jsp:doBody> 액션 태그를 이용해서 몸체 내용을 출력하거나 EL변수로 저장
    • 형태
      <!-- 몸체 내용 처리 방법 1 -->
      <%@ tag body-content="scriptless" %>
      몸체로 전달 받은 내용을 사용
      <!-- 몸체로 전달받은 내용을 그대로 출력 -->
      <jsp:doBody />
      
      <!-- 몸체 내용 처리 방법 2 -->
      <%@ tag body-content="scriptless" %>
      몸체로 전달 받은 내용을 사용
      <!-- 몸체로 전달받은 내용을 var속성으로 지정한 EL 변수에 저장 -->
      <!-- scope 속성을 이용해서 EL 변수를 저장할 영역을 지정 -->
      <jsp:doBody var="변수명" scope="영역" />
  • 몸체 내용 자체를 데이터로 사용
    • 태그 파일의 tag 디렉티브의 body-content 속성값을 tagdependent로 지정
    • 몸체 내용에 포함된 EL이나 액션태그를 처리하지 않고 몸체 내용 자체를 텍스트 값으로 사용

변수 생성

  • variable 디렉티브와 name-given을 이용한 변수 추가
    • 태그 파일에서 variable 디렉티브를 이용해 EL변수를 추가
    • 형태
      <%@ variable name-given="EL변수" variable-class="변수타입" scope="변수범위" %>
    • variable 디렉티브 속성
      • name-given : 이 태그를 호출한 페이지에 추가할 변수 이름을 정의
      • variable-class : 추가될 변수의 타입을 지정
      • scope : 변수의 범위 지정, AT_BEGIN, NESTED, AT_END
  • variable 디렉티브와 name-from-attribute 속성을 이용한 변수 생성
    • 태그 파일에서 variable디렉트브의 name-from-attribute 속성을 이용해 사용자가 원하는 이름을 갖는 변수를 추가
    • 형태
      <%@ attribute name="속성명" rtexprvalue="false" required="true" type="java.lang.String" %>
      <%@ variable alias="사용자가 지정한 변수명" name-from-attribute="사용할 속성명" scope="변수범위" %>
      ...
      <c:set var="사용자가 지정한 변수명" value="..." />
  • 변수의 동기화 처리
    • AT_BEGIN
      • 커스텀 태그 시작 시점부터 태그 파일에서 추가한 변수 사용 가능
    • NESTED
      • 커스텀 태그 시작과 끝 사이, 태그 파일에서 추가한 변수 사용 가능
    • AT_END
      • 태그 파일의 끝 태그 이후부터 태그 파일에서 추가한 변수 사용 가능

✏️ 서블릿 기초

서블릿 구현

  • 서블릿 클래스는 HttpServlet 클래스를 상속받고, HTTP 방식에 따라 알맞은 메소드(doGet(), doPost() 메소드 등)를 재정의해서 구현
  • doGet메소드와 doPost메소드는 파라미터로 HttpServletRequest(request 기본 객체에 해당)와 HttpServletResponse(response 기본 객체에 해당)를 가짐

서블릿 매핑하기

  • Web.xml로 매핑
    • WEB-INF 폴더의 web.xml 파일에 서블릿 클래스를 등록
    • 서블릿 클래스 등록 방법
      ... // xml 설정
      
      // 서블릿으로 사용할 클래스 지정
      <servlet>
      	<servlet-name>매핑할 서블릿 클래스에 지정할 이름</servlet-name>
      	<servlet-class>매핑할 서블릿 클래스 패키지 경로</servlet-class>
      </servlet>
      
      // 서블릿과 URL 간의 매핑
      <servlet-mapping>
      	<servlet-name>servlet태그 하위 태그인 servlet-name에서 지정한 이름</servlet-name>
      	<url-pattern>지정할 경로 패턴</url-pattern>
      </servlet-mapping>
  • 애노테이션으로 매핑
    • 서블릿 2.5 버전까지는 web.xml에 서블릿을 등록해서 매핑
    • 서블릿 3.0 버전부터는 @WebServlet 애노테이션을 사용하여 web.xml파일에 따로 등록하지 않아도 자동으로 등록되어 매핑 가능
    • 형태
      <!-- 경로를 하나만 설정할 때 -->
      @WebServlet("/경로");
      
      <!-- 경로를 여러개 설정할 때 -->
      @WebServlet(urlPatterns = {"/경로1", "/경로2"})
    • 고려사항
      • 서블릿이 범용적으로 사용되는 서블릿인지 여부를 확인하여 애노테이션을 사용할지 web.xml을 사용할지 결정

HTTP 각 방식별 구현 메솓

  • HTTP 종류
    • GET, POST, HEAD, PUT, DELETE 방식을 지원
    • 웹브라우저가 지원하는 방식은 GET과 POST
  • GET 방식은 doGet() 메소드 이용
  • POST 방식은 doPost() 메소드 이용

서블릿 로딩과 초기화

  • 웹 컨테이너가 서블릿 객체를 생성하고 init() 메소드를 호출하는 과정을 서블릿 로딩이라함.
  • init() 메소드를 이용해 필요한 초기화 작업 진행
  • 초기화 작업은 처음 서블릿을 사용하는 시점보다 웹 컨테이너를 처음 구동하는 시점에 초기화를 진행하는게 좋음, 태그를 이용

초기화 파라미터

  • 코드를 직접 변경하지 않고 사용할 값을 변경할 수 있음.
  • 설정 방법
    <init-param>
    	<param-name>파라미터 이름</param-name> // 초기화 파라미터 이름 지정
    	<param-value>파라미터 값</param-value> // 초기화 파라미터 값을 지정
    </init-param>
  • 서블릿에서 초기화 파라미터 접근 방식
    • 해당 초기화 파라미터가 존재하지 않으면 null을 리턴
      변수 = getInitParameter("초기화 파라미터 이름") // 초기화 파라미터에 접근

URL 패턴 매칭 규칙

  • 매핑 규칙
    • '/'로 시작, '/*'로 끝나는 url-pattern은 경로 매핑을 위해 사용
    • '*.'로 시작하는 url-pattern은 확장자에 대한 매핑을 할 때 사용
    • 오직 '/'만 포함하는 경우 어플리케이션의 기본 서블릿으로 매핑
    • 이 규칙 외, 나머지 다른 문자열은 정확한 매핑을 위해 사용

✏️ 모델1과 모델2 그리고 MVC 패턴

모델 1 구조


사진출처 : https://scshim.tistory.com/272

  • JSP(Controller + View)와 자바객체(Model)만 사용
  • 클라이언트의 요청을 JSP가 자바객체를 이용해 직접 처리하고 결과를 클라이언트에 출력
  • 자바객체를 이용해 데이터베이스 연동
  • Controller : JSP에서 사용자의 요청 처리와 관련된 코드를 의미
  • Model : 자바 객체
  • View : JSP에서 Model을 사용하여 검색한 데이터를 사용자가 원하는 화면으로 제공하는 기능
  • 모델 1 구조의 장점
    • 구조가 단순해 배우기 쉬움
    • 자바 언어를 몰라도 어느정도 구현 가능
    • 기능과 JSP가 직관적으로 연결
  • 모델 1 구조의 단점
    • 화면 출력을 위한 View 코드와 로직 처리를 위한 자바 코드가 혼합되어 JSP 코드가 복잡해짐
    • 코드 중복이 빈번하게 발생하여 유지보수가 어려움
    • JSP에 백엔드와 프론트앤드가 혼합되어 있어 분업이 어려움

모델 2 구조


사진출처 : https://velog.io/@jsj3282/MVC-%ED%8C%A8%ED%84%B4-%EA%B5%AC%ED%98%841-%EB%AA%A8%EB%8D%B8-2-%EA%B5%AC%EC%A1%B0%EC%99%80-MVC-%ED%8C%A8%ED%84%B4

  • 모델 1 구조의 단점을 극복하기 위해 고안됨
  • 웹 브라우저의 모든 요청을 하나의 서블릿에서 처리
  • 서블릿은 웹 브라우저의 요청을 알맞게 처리한 후, 결과를 보여줄 JSP 페이지를 선택하여 포워딩
  • 포워딩을 통해 요청 흐름을 받은 JSP 페이지를 클라이언트에 전송
  • 비지니스 로직을 담당하는 Controller가 도입됨.
  • 모델 1 구조의 JSP에서 Controller 로직이 빠지면서 View와 관련된 디자인만 남게됨.
  • Controller : 서블릿 클래스
  • Model : 자바 객체
  • View : JSP
  • 모델 2 구조의 장점
    • JSP코드에서 로직 코드가 분리되어 유지보수가 쉬워짐
    • 컨트롤러 서블릿에서 권함 검사나 인증과 같은 공통 기능 처리가 가능
    • 확장이 용이
  • 모델 2 구조의 단점
    • 자바 언어에 친숙하지 않으면 접근하기가 쉽지않음
    • 작업량이 많음

MVC 패턴


사진출처 : https://hyoje420.tistory.com/36

  • Model, View, Controller 세 부분으로 구성
    • Controller : 사용자의 입력처리와 흐름 제어 담당
    • Model : 비즈니스 영역의 로직을 처리 담당
    • View : 비즈니스 영역에 대한 뷰를 담당
  • 사용자의 요청은 모두 Controller로 보내지고 해당 요청에 알맞는 Model의 비즈니스 로직을 수행한 후 유저에게 보여줄 View를 보여줌. View에서 필요한 데이터는 Controller를 통해 전달
  • MVC 패턴의 중요 포인트
    • 비즈니스 로직을 처리하는 Model과 결과 화면을 보여주는 View를 분리
    • 어플리케이션의 흐름 제어나 사용자의 처리 요청은 컨트롤러에 집중
  • MVC 패턴 장점
    • 유연하고 확장하기 쉬움
    • 디자이너와 개발자의 협업이 용이
    • 유지보수 비용을 절검
  • MVC 패턴의 단점
    • 기본 기능 설계를 위해 클래스들이 많이 필요하기 때문에 복잡함
    • 설계시간이 오래 걸리고 술련된 개발자가 필요
    • Model과 View의 완벽한 분리가 어려움

MVC의 Controller - 서블릿

  • 웹 브라우저의 요청과 웹 어플리케이션의 전체적인 흐름을 제어
  • Controller 서블릿 내부 동작 방식
    1. 웹 브라우저에서 HTTP 요청
    2. 서블릿에서 HTTP 요청을 받음
    3. 클라이언트가 요구하는 기능을 분석
    4. 요청한 비즈니스로직을 처리하는 모델 사용
    5. 결과를 request 또는 session에 저장
    6. 알맞은 뷰를 선택한 후 해당 뷰로 포워딩
    7. 클라이언트에게 HTTP 응답

MVC의 뷰 - JSP

  • 컨트롤러에서 request 기본 객체나 session 기본 객체에 저장한 데이터를 사용하여 웹브라우저에 알맞은 결과를 출력
  • 웹 브라우저의 요청을 컨트롤러에 전달해주는 매개체

커맨드 패턴 기반 코드

  • 각 명령에 해당하는 로직 처리 코드를 별도 클래스로 작성
  • 사용자가 명령을 컨트롤러 서블릿으로 전송, 컨트롤러 서블릿은 사용자가 전송한 명령어에 해당하는 비즈니스 로직을 수행한 후 뷰를 통해 결과를 보여줌
  • 커맨드 패턴을 이용해 명령어 처리기의 분리
    • CommandHandler 인터페이스를 구현
    • CommandHandler 인터페이스를 상속받는 클래스에서 비즈니스 로직을 처리
      1. 명령어와 관련된 비즈니스 로직 처리
      2. 뷰 페이지에서 사용할 정보 저장
      3. 뷰 페이지의 URI 리턴
  • 설정 파일에 커맨드와 클래스의 관계 명시
    • 커맨드 패턴을 이용해 컨트롤러와 로직코드는 분리했지만 명령어를 구분하기 위해 if-else구문을 추가해야되므로 새로운 명령어가 추가되면 직접 변경을 해야함.
    • 위 단점을 해결하기 위해 "명령어, 핸들러 클래스"의 형태로 매핑 정보를 설정 파일에 저장
    • 컨트롤러 서블릿의 init() 메소드에서 명령어 설정 파일을 읽어와 해당하는 핸들러 클래스 객체를 미리 생성
    • Web.xml 파일에서 <init-param> 태그를 이용해 설정파일 경로를 지정
    • properties 파일에 설정 정보 저장
      • 프로퍼티들을 관리
      • 키와 키값으로 구성
      • properties 클래스를 이용해 프로퍼티 정보를 set/get할 수 있음
      • 형태
        프로퍼티이름1=프로퍼티값1
        프로퍼티이름2=프로퍼티값2
  • 요청 URI를 명령어로 사용
    • 쿼리스트링를 통해 커멘드 파라미터를 전달
    • 쿼리스트링으로 명령어를 전달하면 컨트롤러의 URL이 사용자에게 노출되는 단점이 있음
    • 사용자가 아무 커멘드 파라미터를 넣어볼수도 있음.
    • 위 사항들을 예방하기 위해 request.getParameter() 대신 request.getRequestURL() 메소드를 이용
      String command = request.getRequestURI();
      if(command.indexOf(request.getContextPath()) == 0) {
      	command = command.substring(request.getContextPath().length());
      }
    • web.xml 파일에 *.do로 오는 모든 요청을 컨트롤러 서블릿으로 전달

✏️ 필터

필터란?

  • HTTP 요청과 응답을 변경할 수 있는 재사용 가능한 클래스
  • 객체 형태로 존재
  • 클라이언트에서 오는 요청과 최종 자원 사이에 위치하여 클라이언트의 요청 정보를 알맞게 변경
  • 최종 자원과 클라이언트로 가는 응답 사이에 위치하여 최종 자원의 요청 결과를 알맞게 변경
  • 클라이언트와 자원(JSP, 서블릿 등)사이에 위치
  • 여러 개의 필터가 묘여 하나의 필터 체인으로 형성 가능
  • 클라이언트의 요청을 필터 체인의 다음 단계에 보내는 겅니 아니라 다른 자원의 결과를 클라이언트에 전송할 수 있고, 이 기능을 이용해 사용자 인증이나 권한 검사와 같은 기능을 구현할 때 용이

필터 구현

  • Filter 인터페이스
    • init() 메소드
      • 필터를 초기화할 때 호출
      • FilterConfig 파라미터는 초기화 파라미터를 읽어올 때 사용
      • FilterConfig가 제공하는 메소드
        • getFilterName() : 설정 파일에서 에 지정한 필터의 이름을 리턴
        • getInitParameter(name) : 설정 파일의 에서 지정한 초기화 파라미터의 값을 읽어옴, 없으면 null 반환
        • getInitParameterNames() : 초기화 파라미터의 이름 목록을 구함
        • getServletContext() : 서블릿 컨텍스트 객체를 구함
    • doFilter() 메소드
      • 필터 기능을 수행, chain을 이용해 체인의 다음 필터로 처리를 전달
      • 요청이 있을 때 실행, 요청에 대해서 필요한 작업 처리
      • 파라미터로 FilterChain 객체를 통해 다음 필터에게 변경한 요청과 응답을 전달 가능
      • 작업 종류
        1. request 파라미터를 이용하여 요청의 필터링 작업 수행 (ServletRequestWrapper클래스 사용)
        2. 체인의 다음필터 처리
        3. response를 이용해 응답의 필터링 작업수행(ServletResponseWrapper클래스 사용)
    • destroy() 메소드
      • 필터가 웹 컨테이너에서 삭제될 때 호출
  • ServletRequestWrapper 클래스
    • 필터가 요청을 변경한 결과를 저장하는 래퍼
  • ServletResponseWrapper 클래스
    • 필터가 응답을 변경하기 위해 사용하는 래퍼

필터 설정하기 - Web.xml

  • web.xml 파일에 관련 정보 추가
    • 형태
      ...
      // 웹 어플리케이션에서 사용할 필터 지정
      <filter>
      	<filter-name>FilterName</filter-name>
      	<filter-class>필터 클래스 패키지</filter-class>
      	<init-param>
      		파라미터 내용
      	</init-param>
      </filter>
      
      // 특정 자원에 대해 어떤 필터를 사용할지 지정
      <filter-mapping>
      	<filter-name>FilterName</filter-name>
      	<url-pattern>매핑주소</url-pattern> // <servlet-name> 태그를 사용하면 특정 서블릿에 대한 요청에 대해 필터를 적용
      	<dispatcher>REQUEST | FORWARD | INCLUDE</dispatcher>
      	// REQUEST : 클라이언트의 요청인 경우 필터를 적용
      	// FORWARD : forward()를 통해서 제어 흐름을 이동하는 경우에 필터를 적용
      	// INCLUDE : include()를 통해서 포함되는 경우에 필터를 적용
      </filter-mapping>
  • 필터 클래스에서 @WebFilter 애노테이션을 사용
    • Filter 클래스가 @WebFilter 애너테이션을 가지면 자동으로 필터로 등록
    • 형태
      @WebFilter(filterName = "필터명", urlPatterns = {"주소1", 주소2})
    • @WebFilter 애노테이션 속성
      • urlPatterns : 필터를 적용할 URL 패턴 목록을 지정
      • servletNames : 필터를 적용할 서블릿 이름 목록을 지정
      • filterName : 필터의 이름을 지정
      • initParams : 초기화 파라미터 목록을 지정
      • dispatcherTypes : 필터를 적용할 범위를 지정, 열거 타입인 DispatcherType에 정의된 값을 사용

요청 및 응답 래퍼 클래스

  • 요청과 응답을 변경할 때 ServletRequestWrapper 클래스와 ServletResponseWrapper 클래스를 사용
  • 요청 정보 변경하여 최종 자원인 서블릿/JSP/HTML/기타 자원에 전달
  • 최종 자원으로부터의 응답을 변경하여 새로운 응답 정보를 클라이언트에 보냄
  • 필터는 HTTP프로토콜에 대한 요청과 응답을 필터링하기 때문에 두 클래스를 상속받아 알맞게 구현하는게 좋음

필터 응용

  • 필터 응용 종류
    • 필터를 사용하는 방법에는 제한이 없고 필터의 특징을 잘활용하냐에 따라 필터의 응용범위가 달라짐
    • 사용자 인증
    • 캐시 필터
    • 자원 접근에 대한 로깅
    • 응답 데이터 변환(HTML 변환, 응답 헤더 변환, 데이터 암호화 등)
    • 공통 기능 실행

✏️ ServletContextListener 구현

ServletContextListener를 이용한 이벤트 처리

  • 웹 어플리케이션이 시작되거나 종료될 때 호출할 메소드를 정의한 인터페이스
  • contextInitialized(ServletContextEvent sce)
    • 웹 어플리케이션을 초기화할 때 호출
  • contextDestroyed(ServletContextEvent sce)
    • 웹 어플리케이션을 종료할 때 호출
  • 인터페이스를 구현한 클래스를 실행하려면 web.xml에 클래스 이름을 명시해줘야함
    • <listener> 태그
      • 반드시 하나의 <listener-class> 태그를 자식 태그로 가져야함
    • <listener-class> 태그
      • 웹 어플리케이션의 시작/종료 이벤트를 처리할 리스너 클래스의 완전한 이름을 값으로 가짐
    • 형태
      <web-app ...>
      	<listener>
      		<listener-class>ServletContextListener 클래스 패키지1</listener-class>
      	</listener>
      
      	<listener>
      		<listener-class>ServletContextListener 클래스 패키지2</listener-class>
      	</listener>
      </web-app>
  • ServletContextEvent 클래스
    • 웹 애플리케이션의 서블릿 컨텍스트에 대한 변경 사항에 대한 알림을 위한 이벤트 클래스
    • 제공 메소드
      • public ServletContext getServletContext()
        • ServletContext 객체를 반환
        • 반환받은 객체는 JSP의 application 기본 객체와 동일
        • 객체를 사용하려면 web.xml에 설정된 컨텍스트 초기화 파라미터를 사용할 수 있음
        • web.xml 설정 형태
          <web-app ...>
          	// 주로 웹 어플리케이션의 초기화 작업을 수행하는 데 필요한 값을 설정할 때 많이 사용
          	<context-param>
          		<param-name>파라미터 이름</param-name>
          		<param-value>파라미터 값</param-value>
          	</context-param>
          </web-app>
  • ServletContext 객체에서 제공하는 메소드
    • String getInitParameter(str)
      • 지정한 이름을 갖는 컨텍스트 초기화 파라미터의 값을 리턴, 없으면 null 리턴
    • Enumeration<String> getInitParameterNames()
      • 컨텍스트 초기화 파라미터의 이름 목록은 Enumeration 타입으로 리턴

리스너의 실행 순서

  • web.xml에 한 개 이상의 리스너가 등록되어 있을 경우, contextInitialized() 메소드는 순서대로 실행, contextDestroyed() 메소드는 반대로 실행

리스너에서 예외 처리

  • try-catch를 사용해 예외 처리 진행

애노테이션을 이용한 리스너 등록

  • @WebListener 애노테이션을 리스너 클래스에 적용하면 자동으로 리스너로 등록
  • 형태
    ...
    @WebListener
    public Class Listener implements ServletContextListener {
    	...
    }

  • 참고
    • 최범균의 JSP 2.3 웹프로그래밍 기초부터 중급까지
profile
프로그래밍 언어 공부 정리

0개의 댓글