[Servlet] DataSource를 이용한 DB 연동

Bam·2024년 4월 30일
0

Spring

목록 보기
20/48
post-thumbnail

Connection Pool

지난 포스트에서 서블릿과 DB를 연동해서 DB의 데이터를 조회하는 방법에 대해 알아보았습니다. 그런데 지난번 방식의 경우 요청이 들어올 때마다 DAO 객체를 만들었고, 이 DAO 객체는 생성마다 DB에 연결/해제 과정을 반복했습니다.

이렇게 작성을 하는 경우 처리작업을 수행할 때 마다 DB 연결과정에서 시간이 소요된다는 것 입니다. 실제로 우리가 지난번 코드를 실행시키고 /member를 입력했을 때 결과가 바로 뜨는게 아니라 1초 정도의 딜레이가 있었습니다.

실제 서비스에서도 이처럼 딜레이가 발생한다면 큰 불편을 초래하겠죠. 그래서 현재는 웹 애플리케이션이 시작되면 DB 연결을 미리 설정하여 실제 작업시에 연결 시간을 없앰과 동시에 데이터만 빠르게 처리할 수 있도록 만들어줍니다. 이때 웹 애플리케이션 시작과 동시에 DB 연결을 하고 연결 상태를 유지하는 기술을 커넥션 풀(Conncetion Pool)이라고 부릅니다.

우리가 사용하고 있는 톰캣 컨테이너의 경우에는 자체적으로 Connection Pool 기능을 제공하고 있습니다. 톰캣 컨테이너가 실행되는 순간 Connection Pool 객체를 생성하고 이 객체가 DB 연결을 수행/유지합니다.

그리고 작업 과정에서 DB 연동이 필요한 순간 Connection Pool 객체의 메소드를 호출해서 톰캣 컨테이너와 DB를 연동하게 됩니다.

톰캣에서 DataSource를 사용하기 위해서는 DBCP라는 라이브러리를 다운로드해야합니다. 이 링크에서 DBCP를 다운받습니다. 그리고 프로젝트의 lib 디렉토리에 넣어줍니다.

그리고 context.xml을 이용해서 DataSource를 설정해야하는데, context.xml을 생성하는법은 이 포스트를 참조해서 만들어주세요. 그리고 다음과 같이 <Resource/> 태그를 작성합니다.

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/">
    <Resource
            name="jdbc/oracle"
            auth="Container"
            type="javax.sql.DataSource"
            driverClassName="oracle.jdbc.driver.OracleDriver"
            url="jdbc:oracle:thin:@localhost:1521/xe"
            username="DB_유저명"
            password="DB_비밀번호"
    />
</Context>

이 코드에서 name 속성을 이용해 DB에 접근합니다. 이때 driverClassName, url, username, password 네 가지 정보로 DB에 연결합니다.

그리고 MemberDAO 클래스를 다음과 같이 수정합니다.

package com.example.helloservlet.dbexample2;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.*;
import java.sql.Date;
import java.util.*;

public class MemberDAO {
    private Connection connection;
    private PreparedStatement preparedStatement;
    private DataSource dataSource;

    public MemberDAO() {
        try {
        	//context.xml의 정보를 이용해서 DB와 연결된 DataSource 취득
            Context context = new InitialContext();
            Context envContext = (Context) context.lookup("java:comp/env");
            dataSource = (DataSource) envContext.lookup("jdbc/oracle");
        }
        catch (NamingException e) {
            e.printStackTrace();
        }
    }

    public List<MemberDTO> listMembers() {
        List<MemberDTO> members = new ArrayList<MemberDTO>();

        try {
        	//DataSource를 이용한 DB 연동
            connection = dataSource.getConnection();

            String sql = "SELECT * FROM member";
            System.out.println("query: " + sql);

            preparedStatement = connection.prepareStatement(sql);
            ResultSet resultSet = preparedStatement.executeQuery();

            while (resultSet.next()) {
                String id = resultSet.getString("id");
                String password = resultSet.getString("password");
                String name = resultSet.getString("name");
                String email = resultSet.getString("email");
                Date joinDate = resultSet.getDate("joinDate");

                MemberDTO memberDTO = new MemberDTO();
                memberDTO.setId(id);
                memberDTO.setPassword(password);
                memberDTO.setName(name);
                memberDTO.setEmail(email);
                memberDTO.setJoinDate(joinDate);
                members.add(memberDTO);
            }

            resultSet.close();
            preparedStatement.close();
            connection.close();
        }
        catch (SQLException e) {
            throw new RuntimeException(e);
        }

        return members;
    }
}

톰캣 서버를 실행해서 http://localhost:8090/HelloServlet_war_exploded/member2에 접속하면 동일한 결과를 얻을 수 있음을 확인할 수 있습니다.

0개의 댓글