[ 국비교육 ] Day 31

리팩토링 한답시고 2일 동안 배운 기술은 다음과 같다.

  • main → main(ui) + DAO(DB 메서드) | DTO(데이터 저장)
  • DAO : UI를 배제한 오로지 데이터만을 다루는 용도의 클래스로 ‘데이터 관련’ 기능 클래스
  • PrepareStatement : Statement를 상속받는 클래스로 보안과 기능을 업그레이드
  • try-resource : DB와의 연결을 메서드가 끝날 때 자동으로 닫게 설정
  • Connection : 메서드 별로 들어가던 Connection을 따로 메서드로 빼줌
  • 암호화 : SHA256 해싱으로 pw을 암호화해서 DB에 저장

가장 큰 건 main과 DAO, DTO의 분리이다. 이로 인해 파트별로 분업이 가능해졌다.
그러나, 남은 한 가지 문제는 연결이다.


DBCP

[ 문제1 ]

우리가 만든 프로그램은 DB, UI가 한 컴퓨터에 존재한다. 한 마디로 싱글 플레이이다.
하지만 실 서비스는 여러 고객이 네트워크를 타고 본사의 DB를 통해 CRUD를 한다.

하나의 DB-하나의 사용자 | 하나의 DB-여러 사용자

따라서 실 서비스에선 다음과 같은 문제가 있다.

동접자가 많을 경우, 연결을 try-resource 처리해도 그 이상의 접속이 들어오면서 DB가 오작동을 일으킬 수도 있다.

일단 try-resource 때문에 메서드 사용 후, 연결은 무조건 끊긴다.
하지만 기본 연결이 100인데, 그 이상이 동시에 들어오면 연결을 끊기 전에 한도를 초과하는 Connection이 생성되게 된다.
이 경우, DB가 뻗는다.

[ 해결 방안 ]

DB – DBMS – (connection) - DBCP – DAO – UI

그 해결방안으로 나온 것이 ‘DBCP기법(DateBase Connection Pool)’ 이다.

  • DBCP 객체로 모든 연결이 관리된다.
  • 일정량의 DBMS와의 연결을 미리 만든다.
  • 요청이 들어오면 연결을 빌려주고, 처리가 끝나면 DBCP로 반환된다.
  • 수량 이상의 사용자는 대기시킨다.
  • 수량을 크게 잡으면 사용자가 없을 경우 메모리 낭비가 있다.

[ 사용법 ]

DBCP 외장라이브러리를 검색해서 넣는다. 다만 ‘의존성 라이브러리’이기 때문에 잘 찾아서
불러오면 된다.

public Connection getConnection() throws Exception{
	BasicDataSource bds = new BasicDataSource(); // DBCP Object 
	bds.setUsername("kh");
	bds.setPassword("kh");
	bds.setUrl("jdbc:oracle:thin:@localhost:1521:xe"); 
	bds.setDriverClassName("oracle.jdbc.driver.OracleDriver"); // 드라이버 로딩
	bds.setInitialSize(30);

	return bds.getConnection();
}

[ 문제 2 ]

: DBCP인스턴스 문제
위와 같은 방식은 메서드를 실행할 때마다, 인스턴스를 생성한다.
그러면 메서드가 실행될 때마다 30개의 연결이 만들어진다.
물론 지역변수라 메서드가 끝나면 지워지는게 당연하지만 메모리 상에서 지워지는 타이밍이 생각보다 늦기 때문에, 첫 문제처럼 똑같은 일이 발생한다.

[ 해결방안 ]

생성자와 멤버필드로 해서 DAO 인스턴스를 만들 때만 생성되게 한다.
물론, 프로그램을 만들면 하나의 DB에 연결된 여러 DAO가 존재한다.
따라서 이 방법도 어느 순간 앞의 문제가 DAO의 영역에서 발생한다. 하지만 이 부분은 현 시점에서 다루려면 복잡하기 때문에 Web 이후에 다루고자 한다.

[ 사용법 ]

private BasicDataSource bds = null; // 어느 메서드에서든지 사용할 수 있음

// 생성자
public CafeMenuDAO() {
	this.bds = new BasicDataSource(); 
	bds.setUsername("kh");
	bds.setPassword("kh");
	bds.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
	bds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
	bds.setInitialSize(30);
}

// getConnection 
public Connection getConnection() throws Exception{
	return bds.getConnection();
}

좋은 웹페이지 즐겨찾기