티스토리 뷰

개요

지난 글에서 Maven, Servlet 3 기반의 Hello, World!를 출력하는 간단한 웹 프로젝트를 만들어봤다. 화면에 구구단을 출력하고 끝낼 것이 아니라면 웹 프로젝트는 데이터베이스와의 연동이 필수이다. 이번 글에서는 지난 글에 이어 데이터베이스 커넥션 풀을 구성하고 데이터베이스에 간단하게 질의한 결과를 화면에 출력하는 예제를 소개하겠다. 기본 프로젝트 구성은 지난 글을 참고한다.

pom.xml 라이브러리 의존성 추가

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP-java6</artifactId>
            <version>2.3.7</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.187</version>
        </dependency>
        <dependency>
            <groupId>org.sql2o</groupId>
            <artifactId>sql2o</artifactId>
            <version>1.5.4</version>
        </dependency>
  • Don't Reinvent The Wheel, Unless You Plan on Learning More About Wheels. 프로젝트에 사용할 라이브러리 선정은 가장 골치 아프면서도 재미있는 작업이다. 모든 것을 내가 만들어야 직성이 풀리는 사람이 아닌 이상 우리는 이미 만들어진 검증된 라이브러리를 사용해서 최대한 빠른 시간에 견고한 코드를 작성해야 한다. 아래와 같이 예제에서 사용할 라이브러리를 선정하였다.
  • LOGBacklog4j의 원작자인 Ceki Gulcu가 새롭게 개발한 SLF4J를 지원하는 로깅 라이브러리이다. 혹시 이 글을 읽는 독자 중 아직도 습관적으로 System.out.println()를 사용하여 디버깅한다면 로깅 라이브러리 사용에 익숙해지기를 권한다.
  • HikariCP는 세계에서 가장 빠른 성능의 JDBC 커넥션 풀 라이브러리이다. 나는 사내 프로젝트에 최근 3년간 BoneCP를 사용하다가 HikariCP로 교체하였다.
  • H2는 순수하게 Java로만 작성된 초경량 RDBMS이다. 혹시 Oracle, MySQL 등의 RDBMS 환경구성에 부담을 느껴 평소 데이터 모델을 설계하는 연습을 게을리했다면 이 기회에 H2에 익숙해지기를 권한다.
  • Sql2o는 개인적으로 선호하는 경량의 JDBC 헬퍼 라이브러리이다. 물론 MyBatis가 지배하는 국내 개발환경에서는 MyBatis만 할 줄 알아도 먹고 사는데 지장없다.

ServletContextListener 클래스 작성

package com.jsonobject.webappexample;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

@WebListener
public class ApplicationConfig implements ServletContextListener {

    private static final Logger logger = LoggerFactory.getLogger(ApplicationConfig.class);

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        logger.info("===== contextInitialized() start");
        HikariConfig config = new HikariConfig();
        config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
        config.setConnectionTestQuery("SELECT NOW()");
        config.addDataSourceProperty("URL", "jdbc:h2:~/someDatabase;MODE=MySQL");
        config.addDataSourceProperty("user", "someUser");
        config.addDataSourceProperty("password", "somePassword");
        HikariDataSource ds = new HikariDataSource(config);
        sce.getServletContext().setAttribute("dataSource", ds);
        logger.info("===== contextInitialized() end");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}
  • 웹 애플리케이션의 특성상 DataSource 오브젝트는 모든 서블릿 클래스에서 접근이 가능해야 하며 이는 ServletContext 오브젝트에 담아 해결할 수 있다. ServletContextListener의 구현 클래스를 작성하면 웹 애플리케이션의 시작과 끝에 실행할 로직을 작성할 수 있다. 시작을 담당하는 contextInitialized() 메써드에 DataSource 오브젝트를 생성하여 ServletContext 오브젝트에 저장한다.
  • H2는 Embedded와 In-Memory 방식을 모두 지원하는 순수 Java로 작성된 RDBMS이다. 프로젝트 테스트부터 간단한 소형 애플리케이션까지 광범위하게 사용할 수 있다. JDBC URL을 어떻게 작성하냐에 따라서 아래와 같이 Embedded와 In-Memory 방식으로 연결할 수 있다.
    • jdbc:h2:~/someDatabase: 현재 사용자 디렉토리(Windows의 경우 C:\Users\%userName%, Linux의 경우 /home/userName)의 someDatabase라는 파일의 데이터베이스에 연결한다. 파일이 존재하지 않으면 새로 생성한다. DataSource 오브젝트가 소멸해도 데이터는 유지된다.
    • jdbc:h2:mem:someDatabase: someDatabase라는 이름의 In-Memory 데이터베이스에 연결한다. DataSource 오브젝트가 소멸하면 데이터가 모두 제거된다.
    • MODE=MySQL: MySQL 호환성 모드를 사용한다. H2는 고유의 ANSI SQL을 제공하지만 때때로 테스트를 위해 다른 RDBMS를 흉내낸 호환성 모드로 실행할 수 있다. 완전히 호환되지 않기 때문에 간단한 테스트 목적으로만 사용해야 한다.
  • H2의 파일 데이터베이스는 최초 데이터베이스 연결(파일 생성)시 명시한 user, password로 계정이 생성된다. 후에 틀린 user, password로 연결 시도시 org.h2.jdbc.JdbcSQLException: Wrong user name or password 예외가 발생한다.

Servlet 클래스 작성

package com.jsonobject.webappexample;

import java.io.PrintWriter;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sql2o.Connection;
import org.sql2o.Sql2o;

@WebServlet("/showDbTime")
public class showDbTimeServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    private static final Logger logger = LoggerFactory.getLogger(showDbTimeServlet.class);

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html><head></head><body>");

        Sql2o sql2o = new Sql2o((DataSource) this.getServletContext().getAttribute("dataSource"));
        Connection connection = sql2o.open();
        String now = connection.createQuery("SELECT NOW()").executeAndFetchFirst(String.class);
        connection.close();

        out.println("<h1>" + now + "</h1>");
        out.println("</body></html>");
    }
}
  • Servlet 3이 제공하는 @WebServlet 어노테이션을 이용하여 /showDbTime 주소 요청시 데이터베이스의 현재 시간을 출력하는 소스 코드를 작성하였다.
  • 앞서 ServletContext에 담은 DataSource 오브젝트를 이용하여 데이터베이스의 현재 시간을 획득하여 화면에 출력한다. 편의상 JDBC를 제어하기 위한 방법으로 Sql2o 라이브러리를 사용하였는데 다른 방법을 사용해도 무관하다. 또한, 예제 차원에서 서블릿 클래스에 데이터베이스 관련 코드를 작성하였는데 본래 서블릿에서 데이터베이스 관련 코드는 분리되어야 한다. 이 부분에 대해서는 다음 글에서 자세히 설명할 예정이다.

번외 팁: H2 데이터베이스 외부 접근하기

  • 앞서 생성한 H2 데이터베이스는 소스 코드 외부에서 어떻게 접근할 수 있을까? H2가 제공하는 H2 Console 프로그램을 이용하면 가능하다. H2 홈페이지에서 Windows Installer 버전을 다운로드하여 설치한다.
  • 설치가 끝났으면 웹 브라우저를 실행하고 http://localhost:8082 주소에 접속한다. H2 ConsoleLogin 화면이 나타날 것이다.
  • JDBC URL, User Name, Password에 앞서 소스 코드에서 설정한 값을 입력하고 Connect 버튼을 클릭한다. 데이터베이스에 접속하여 CRUD를 수행할 수 있다.
  • 또는 DBeaver와 같은 범용 JDBC 클라이언트에서도 접근이 가능하다. Oracle, MySQL, H2를 하나의 툴에서 접근 가능하기 때문에 이 방법을 추천한다.
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함