8 분 소요

JSP 프로그래밍2

데이터베이스

JDBC

개요

  • 자바 언어로 다양한 종류의 관계형 데이터베이스에 접속하고 SQL 문을 수행하여 처리하고자 할 때 사용되는 표준 SQL 인터페이스 API
  • 접속하는 DBMS 서버에 따라 JDBC 드라이버가 필요
    • WAS 설치된 HOME 폴더 밑 lib 폴더 - 현재 WAS에서 실행되는 모든 웹 애플리케이션에서 사용 가능
    • 각 웹 애플리케이션의 /WEB-INF/lib - 해당 웹 애플리케이션에서만 사용

구현

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ page import="java.sql.*" %>
<%
	//1. JDBC Driver 로딩
	Class.forName("oracle.jdbc.driver.OracleDriver");
	//2. DB 서버 접속하기
	String url = "jdbc:oracle:thin:@localhost:1521:xe";
	Connection conn = DriverManager.getConnection(url, "scott", "tiger");
	//3. Statement or PreparedSttement 객체 생성
	Statement stmt = conn.createStatement();
	String id = request.getParameter("id");
	String pwd = request.getParameter("pwd");
	
	PreparedStatement pstmt = conn.prepareStatement("insert into test values(?,?)");
	pstmt.setString(1, id);
	pstmt.setString(2, pwd);
	pstmt.executeUpdate();
	//4. SQL 실행
	stmt.executeUpdate("create table test(id varchar2(5), pwd varchar2(5))");
	stmt.executeUpdate("insert into test values('aa', '11')");
	stmt.executeUpdate("insert into test values('bb', '22')");
	stmt.executeUpdate("insert into test values('cc', '33')");
	ResultSet rs = stmt.executeQuery("select * from test");
	while(rs.next()) {
		out.print("<br>" + rs.getString("id") + ":" + rs.getString(2));
	}
	
	//5. 자원해제
	rs.close();
	stmt.close();
	conn.close();
%>
  • Statement : 자바 프로그램과 DB가 연결된 길에서 서로에게 데이터를 전달해주는 객체
  • PreparedStatement : Statement 객체와 같은 기능. 객체 생성 시 실행할 SQL 문을 ?기호와 함께 작성할 수 있어 동적으로 값을 할당할 때 가독성과 유지 보수성 좋음

DataSource

  • 웹 클라이언트로부터 요청이 들어올 때마다 DB 서버와 연결하는 것이 아니라, 미리 서버에서 연결한 후 활용하는 방법

개요

  • 웹 프로그램은 동시에 여러 사용자에 의해 요청이 일어날 수 있는 특성이 있으므로 자원 배분과 응답 속도에 대하여 효율적으로 구현해야 함
  • 기존 JDBC 사용 시 문제점
    • DB 프로그램에서 트랜잭션 처리와 Connection 관리는 시스템의 성능과 안전성에 큰 영향
    • Connection 과정은 일정 시간이 필요한 부담되는 작업
    • 불필요한 연결에 의한 서버 자원의 낭비 발생
  • Connection Pool
    • 웹 애플리케이션이 서비스되기 전에 웹서버에서 미리 생성하여 준비한 다음 필요할 때 준비된 Connection 가져다 사용
    • Connection 객체는 서버가 시작될 때 서버에서 여러 개 준비 ⇒ Connection 객체들을 가지고 있는 리소스를 Connection Pool 이라고 함
  • DataSource
    • 여러개의 Connection 객체가 생성되어 운용될 때 각각을 직접 웹 애플리케이션에서 이용하면 체계적인 관리 어려움
    • Connection Pool 관리하는 목적으로 DataSource 객체 사용
    • JNDI Server에의해 웹 애플리케이션에 전달하는 방식 사용
    • 이용방법
      1. JNDI Server에서 lookup() 메소드를 통해 DataSource 객체 획득
      2. DataSource 객체의 getConnection() 메소드를 통해서 Connection Pool에서 Free 상태의 Connection 획득
      3. Connection 객체를 통한 DBMS 작업 수행
      4. 모든 작업이 끝나면 DataSource 객체를 통해서 Connection Pool에 Connection 반납
  • JNDI Server
    • 서버나 애플리케이션에서 분산환경에 서비스하고자 하는 자원을 Naming & Directory 서버에 이름값과 실제 자원을 연결하여 등록하면, 해당 자원을 이용하고자 하는 다른 애플리케이션에서 N&D 서버에 접근하여 이름값만 가지고 자원을 연결하여 이용할 수 있게 하는 개념

구현

  • server.xml
  • glabalNamingResources 태그 안에 설정

      <Resource driverClassName="oracle.jdbc.driver.OracleDriver" 
          		url="jdbc:oracle:thin:@127.0.0.1:1521:xe" 
          		username="scott" 
          		password="tiger" 
          		name="jdbc/myoracle" 
          		type="javax.sql.DataSource" 
          		maxActive="4" 
          		mixIdle="2" 
          		maxWait="5000" />
    
  • context.xml

      <ResourceLink global="jdbc/myoracle" name="jdbc/myoracle" type="javax.sql.DataSource" />
    
  • web.xml

      <resource-ref>
        	<description>Oracle Database example</description>
        	<res-ref-name>jdbc/myoracle</res-ref-name>
        	<res-type>javax.sql.DataSource</res-type>
        	<res-auth>Container</res-auth>
        </resource-ref>
    
  • DataSource 사용해서 DB 작업

      <%@ page language="java" contentType="text/html;charset=UTF-8"%>
      <%@ page import="java.sql.*" %>
      <%@ page import="javax.sql.*" %>
      <%@ page import="javax.naming.*" %>
        
      <% 
      	//1. JDNI 서버 객체 생성
      	InitialContext ic = new InitialContext();
      	//2. lookup()
      	DataSource ds = (DataSource)ic.lookup("java:comp/env/jdbc/myoracle");
      	//3. getConnection()
      	Connection conn = ds.getConnection();
        	
      	Statement stmt = conn.createStatement();
      	ResultSet rs = stmt.executeQuery("select * from test");
        	
      	while(rs.next()) {
      		out.print("<br>" + rs.getString("id") + ":" + rs.getString(2));
      	}
        	
      	rs.close();
      	stmt.close();
      	conn.close();
      %>
    

EL(Express Language)

개요

구문

  • ${ } 내에 표현식으로 표현
  • 지정된 문자, 연산자, 변수 사용
  • 서버에서 지원하는 서블릿 스펙에 따라 EL 사용법 다를 수 있음

EL 표현식에서 사용 가능

  • 문자
    • 논리 : true, flase
    • 숫자 : 정수, 실수
    • 문자열 : “ “ 또는 ‘ ‘
  • 연산자
    • 산술 연산자 : +, -, /, %, mod
    • 논리 연산자 : &&, ||, and, or, not
    • 비교 연산자 : ==, !=, <, >, <=, >=, eq, ne, lt, get, le, ge
    • empty 연산자 : 값이 null이나 공백 문자열인지 판단
      • ${empty “ “} ⇒ true
      • ${empty null} ⇒ true

내장 객체

  • 필요한 객체는 내장 객체 참조변수 이름으로 바로 사용 가능

정보 추출

  • JSP 태그로 작업할 수 있는 기능 모두 EL로 표현 가능
  • 코드 간소화
  • HttpServletRequest, HttpSession, ServletContext 객체에 등록한 데이터 접근할 때 간단한 코드로 처리

request 정보 추출

  • HttpServletRequest 객체는 forward 또는 include를 통해 실행된 페이지 사이에만 공유
  • ${book} 같이 표현하면 request ⇒ session ⇒ application 객체 순서로 getAttribute(”book”) 메소드 실행
    • 등록된 객체를 찾아 순차적 실행
    • 추출된 정보가 있으면 원래 등록된 객체의 타입으로 캐스팅.
    • getAttribute() 메소드 실행 중단

session 정보 추출

  • 클라이언트 단위로 정보를 유지시킬 때 HttpSession 객체에 정보 등록

application 정보 추출

  • 웹 애플리케이션 단위로 정보를 유지할 때 ServletContext 객체에 정보 등록

커스텀 태그

장점

  • 재사용성 - 한 번만 작성한 후 JSP 페이지 내에서 언제든지 사용
  • 역할 분담 - 개발자와 디자이너
  • 유지 보수성
  • 가독성

클래스 기반 커스텀 태그

  • 태그 기능 자바 클래스 파일에 구현한 다음, JSP 태그와 연결하여 사용

구성 요소

  • 태그 핸들러 클래스(Tag Handler Class)
    • 커스텀 태그를 사용할 때 호출되는 자바 클래스 파일. 실행문을 구현하고 있는 자바 객체
    • Tag 인터페이스를 상속받은 클래스들을 상속받으면 JSP 1.2 버전으로 작성
    • SimpleTag 인터페이스를 상속받은 SimpleTagSupport 클래스 상속받으면 JSP 2.0 이상 버전으로 작성
  • 태그 라이브러리 디스크립터(Tag Library Descriptor)
    • JSP 페이지 내에서 사용할 때 클래스를 직접 사용하는 것이 아니라 JSP 커스텀 태그 이름으로 사용
    • JSP 태그 이름을 설정하는 XML 파일
    • tld 확장자 사용
  • TLD 파일 등록
    • 자바 클래스와 JSP 태그 매핑한 정보
    • jsp 1.2 버전 ⇒ web.xml에 등록
    • jsp 2.0 버전 ⇒ 자동 인식하는 폴더에 넣기 ⇒ WEB-INF 폴더 또는 하위폴더, WEB-INF/lib 폴더의 jar 파일에 위치
  • taglib 지시자
    • 커스텀 태그를 사용하기 위해서 taglib 지시자를 사용하여 선언해야 함.
    • 태그 라이브러리의 uri와 prefix 값을 속성으로 가짐
    • TLD와 JSP 파일 연결

JSP 1.2

  • Tag 인터페이스 계열을 상속받아 태그 핸들러 클래스 작성
  • 실행 시 자동으로 호출되는 메소드
    • 시작 태그를 만나면 doStartTag()
    • 태그의 몸체가 처리된 후 doAfterBody()
    • 끝 태그를 만나면 doEndTag()
  • 몸체 처리
    • <body-content> : 커스텀 태그의 시작과 끝 사이에 있는 내용. 태그의 몸체에 대한 처리를 설정하는 태그
      • JSP(default) : 몸체의 내용을 JSP 코드로 처리
      • tagdependent : 몸체의 내용을 자신의 기능으로 처리
      • empty : 몸체가 없음을 선언. empty가 선언된 태그는 몸체를 가질 수 없음.
  • 실행 제어 - 메소드들이 반환하는 값
    • EVAL_BODY_INCLUDE : 메소드가 종료된 후 태그의 몸체를 처리.
    • SKIP_BODY : 태그의 몸체를 처리하지 않고 스킵
    • EVAL_BODY_AGAIN : 몸체를 다시 실행
    • EVAL_PAGE : 메소드가 종료된 후 계속해서 JSP 페이지가 실행
  • 속성 정의
    • TLD 파일에 <attribute> 태그로 정의
    • 태그 핸들러 클래스 객체에 속성과 같은 이름의 멤버변수 선언하고 getter, setter 메소드 선언
  • TEI 객체
    • TLD 파일에 지정하지 않은 커스텀 태그의 내용을 동적으로 변경하여 복잡성을 없애려고 할 때 사용

JSP 2.1

  • SimpleTag 인터페이스 계열을 상속받아 태그 핸들러 클래스 작성
  • 1.2와 달라진 점
    • SimpleTag 잍너페이스 추가
    • SimpleTagSupport 클래스 제공
    • doTag() 메소드로 Tag 관련 메소드 통일
    • JspFragment를 이용한 body 전달
    • 동적 Attribute 추가 방법 제공

태그 기반 커스텀 태그

  • JSP 파일에 커스텀 태그의 기능을 구현한 다음, 확장자를 tag로 지정

구성요소

  • Tag 파일
    • 일반 JSP 페이지에서 사용하던 page 지시자 대신 tag 지시자 사용
    • 일반 JSP 페이지에서 사용할 수 없는 지시자 추가로 사용

사용방법

  • 태그 파일 작성해서 저장 ⇒ WEB-INF/tags 폴더 또는 하위 폴더만 가능
  • JSP 페이지에서 커스텀 태그를 사용하기 위한 taglib 지시자 선언

    <%@ taglib prefix="my" tagdir="/WEB-INF/tags" %>

  • 태그 파일을 커스텀 태그로 사용할 대는 taglib의 tagdir 속성에 태그 파일들이 위치한 폴더를 지정
  • tagdir 속성에 지정한 폴더의 태그 파일들은 각각 파일 하나당 하나의 커스텀 태그로 사용

지시자

  • tag 지시자 : 커스텀 태그에 대한 기본적인 정보 설정
  • attribute 지시자 : 속성 정의
  • variable 지시자 : EL에서 사용하는 변수를 선언할 때 사용

태그 처리

  • <jsp:doBody> : 커스텀 태그의 몸체 처리

    <%@ tag body-content="empty" pageEncoding="utf-8">

    • empty
    • tagdepent
    • scriptless : EL이나 액션 태그가 몸체에 사용되었을 때 처리된 결과를 몸체로 사용한다는 정보
  • 동적 속성

    • 속성을 미리 정의하지 않고 Map 형태로 받아서 사용

      <%@ tag dynamic-attributes=" 변수이름 " %>

JSTL

  • 태그 라이브러리를 공통으로 사용하기 위해 정해진 표준

Core

  • 프로그램 개발 시 사용되는 기본적인 기능
  • <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

formatting

  • 날짜, 시간에 관한 형식 처리
  • <%@ taglib prefix="fmt" uri="http://java.sum.com/jsp/jstl/fmt" %>

sql

  • 데이터베이스 작업에 관한 기능들 수행하는 태그
  • <%@ taglib prefix="fmt" uri="http://java.sum.com/jsp/jstl/sql" %>

xml

  • xml 지원하는 기능의 태그들
  • <%@ taglib prefix="fmt" uri="http://java.sum.com/jsp/jstl/xml" %>

function

  • 여러 가지 함수 기능
  • <%@ taglib prefix="fmt" uri="http://java.sum.com/jsp/jstl/functions" %>

MVC 디자인 패턴

  • 애플리케이션을 세가지 영역인 모델, 뷰, 컨트롤러로 구분하여 작업을 분리
  • 서로간의 결합도 최소화, 유지보수성 높음
  • 개발의 효율성 극대화

MVC 디자인 패턴의 두 가지 모델

Model1

  • 컨트롤러를 JSP로 작성
  • JSP가 클라이언트의 요청을 처리하면서 동시에 뷰의 역할도 가능
  • 컨트롤러와 뷰의 구분 없이 간단하고 빠르게 개발 가능
  • 구현 작업이 복잡할 때는 역할이 구분되지 않아서 유지보수 어려움

Model2

  • 컨트롤러를 서블릿으로 작성
  • 요청 받아 처리하는 페이지는 서블릿이고, 뷰와 분리

뷰(view)

  • 클라이언트로부터 요청이 일어나거나 처리된 결과를 보여주는 페이지
  • HTML, CSS, JavaScript, JSP로 작성
  • 서버와 독립적으로 다양한 UI 사용 가능

컨트롤로(Controller)

  • 뷰에서 클라이언트가 서비스를 요청했을 때 실행되는 페이지
  • 서비스를 처리하는 메소드를 호출함으로써 클라이언트 요청과 서비스 처리 객체를 연결해주는 중계 역할을 하며 서비스 서리 흐름 제어
    • 뷰에서 들어온 요청 받음
    • 클라이언트가 전달한 파라미터 추출
    • 파라미터 유효성 검사.
    • 서비스 객체의 메소드 호출하며 파라미터 서비스 객체로 전달
    • 출력 뷰 페이지로 이동

모델(Model)

  • 서비스 객체
    • 서비스 처리를 하기 위한 내용으로만 구현된 객체
    • 일반 자바로 작성
  • DAO 객체
    • DB 처리 담당
    • 일반 자바로 작성

3계층 아키텍처

  • 웹 애플리케이션을 개발할 때 구조적인 측면에서 3계층 아키텍처 사용

프레젠테이션 계층

  • 최상위에 위치하는 영역
  • 클라이언트와 애플리케이션 간에 상호작용 할 수 있게 하는 인터페이스 역할
  • 단순히 웹 브라우저를 통해 클라이언트로부터 서비스를 요청받아서 비즈니스 계층의 메소드를 호출해주거나, 클라이언트카 보낸 데이터를 비즈니스 계층으로 전달하는 기능만 구현
  • 비즈니스 계층의 작업이 끝난 다음 처리 결과 뷰 페이지로 이동하는 기능
  • 프런트엔드 영역 - HTML, CSS, JavaScript, JSP, Servlet, Image 사용

비즈니스 계층

  • 클라이언트가 요청한 서비스를 처리하는 비즈니스 로직 구현
  • 클라이언트와 직접 연결되지 않으며, 프레젠테이션 계층과 연결되어 실행되는 영역
  • 서비스 처리에 관한 기능만 구현
  • 일반 자바 코드로 구현
  • 백엔드 or 미들웨어 영역

영속 계층

  • 데이터베이스 서버, 파일 시스템에 접근하여 데이터를 생성, 관리하는 기능
  • 서비스를 처리할 때 영구적으로 저장된 데이터를 추출, 수정, 삭제, 생성하는 작업은 비즈니스 계층이 아닌 영속 계층에서 처리
  • 백엔드 영역

프레임워크

  • 어느 정도 완성되어 있는 틀을 사용하여 빠르고 효율적으로 개발

장점

  • 개발 기간 단축 - 필요한 기능을 프레임워크에서 제공하는 라이브러리 사용해서 빠르고 간편하게 개발
  • 성능 향상 - 검증된 효율적인 아키텍처와 설계 사용
  • 유지보수성 향상 - 업무 파악 빠르게 할 수 있음. 프레임워크는 유지보수를 고려하여 설계되어 작업 최소화

단점

  • 프레임워크 학습 필요
  • 프레임워크 선택 어려움 - 잘못된 프레임워크 선택하면 개발 및 운영, 유지보수에 많은 어려움 초래
  • 유연성 부족 - 커스터마이징 어려움

프론트 컨트롤러 디자인 패턴

  • 뷰에서 들어오는 요청에 대하여 각각의 컨트롤러에서만 처리하면 수많은 뷰의 요청 통제 불가
  • 대표 컨트롤러를 두고 뷰에서 들어오는 모든 요청을 담당하게 해서 모든 요청을 일괄적으로 처리

프론트 컨트롤러 설정

  • URL 패턴 지정 ⇒ ~.do, ~.action 등
  • 프런트 컨트롤러 등록 ⇒ web.xml <url-pattern> 태그에 등록

서브 컨트롤러 연결

  • 프런트 컨트롤러에서 일괄적으로 처리할 기능 구현하고, 처리가 완료된 후에는 반드시 실제 요청한 서비스를 처리하는 컨트롤러 실행
  • 어떤 서브 컨트롤러가 실행될지 map 객체에 저장