2.1 공통 개념
2.1.1 DAO 패턴
- 데이터 액세스 계층은 DAO 패턴이라 불리는 방식으로 분리하는 것이 원칙
- 비즈니스 로직이 없거나 단순하면 DAO와 서비스 계층 통합도 가능
- 의미있는 비즈니스 로직을 가진 애플리케이션이라면 DAO 패턴으로 분리
- DAO 패턴은 DTO 또는 도메인 오브젝트만을 사용하는 인터페이스를 통해 데이터 액세스 기술을 외부에 노출하지 않도록 만드는 방식
- 가장 중요한 장점은 DAO를 이용하는 서비스 계층의 코드를 기술이나 환경에 종속되지 않는 순수한 POJO로 개발할 수 있다는 점
- 단순한 DTO나 도메인을 사용하기 때문에 목 오브젝트, 테스트 대역 오브젝트로 대체해 단위 테스트가 가능
DAO 인터페이스와 DI
- 인터페이스를 이용해 접근하고 DI 되도록 작업 (액세스 기술과 어떤 API도 노출 X)
- DAO 클래스의 모든 public 메소드를 추가 하지않도록 주의, DAO를 사용하는 서비스 계층 코드에서 의미 있는 메소드만 인터페이스로 공개
- 특정 데이터 액세스 기술에만 의미 있는 DAO 메소드 이름은 피해야 함
- 일반적인 add(), update()와 같은 메소드 이름을 선택 (
persist()
,merge()
X)
- 일반적인 add(), update()와 같은 메소드 이름을 선택 (
예외처리
- 데이터 액세스 중에 발생하는 예외는 대부분 복구가 불가능
- DAO 메소드 선언부에 throw SQLException과 같은 내부 기술을 드러내거나 throw Exception과 같은 무책임한 선언은 좋지 않음
- DAO 내부에서 발생하는 예외는 모두 런타임 예외로 전환 필요
- 때로 의미 있는 DAO가 던지는 예외를 잡아 비즈니스 로직에 적용하는 경우가 필요
- 중복키 예외, 낙관적인 락킹 등이 대표적 예
- 의미 있는 예외를 처리하려고 할 때 JDBC나 각 데이터 액세스 기술에 예외에 일관성이 없기 때문에 예외를 서비스 계층에서 알고 있어야하는 문제가 발생
- 스프링은 특정 기술이나 DB의 종류에 상관없이 일관된 의미를 갖는 데이터 예외 추상화를 제공
- 각 기술과 DB에서 발생하는 예외를 스프링의 데이터 예외로 변환해주는 서비스를 제공
- JdbcTemplate과 같은 템플릿/콜백 기능을 사용하면 변환서비스가 자동으로 적용
- 데이터 액세스 기술의 API를 직접 쓸 땐 AOP를 이용해 예외를 전환해주는 기능을 사용
- 최신 데이터 액세스 기술은 JDBC와 다르게 런타임 예외를 사용
- 독립적인 추상 예외로 전환하고 일관된 예외 복구 기능을 적용할 필요가 없다면 스프링의 예외 변환 서비스를 사용하지 않아도 됌
2.1.2 템플릿과 API
- 데이터 액세스 기술을 사용하는 코드는 대부분 외부의 리소스와 연동하기 떄문에 try/catch/finally 반복되는 코드가 작성되기 쉬움
- 리소스 누수가 발생하지 않도록 예외상황에서 적절히 반환이 필요하기 떄문
- 이 때문에 코드가 길고 지저분해지는 단점이 발생
- 스프링은 템플릿/콜백 패턴을 이용해 반복되는 코드를 줄이는 템플릿을 제공
- 예외 변환과 트랜잭션 동기화 기능도 함께 제공
- 템플릿의 단점
- 데이터 액세스 기술의 API를 직접 사용하는 대신 템플릿이 제공하는 API를 이용
- 콜백 오브젝트를 익명 내부 클래스로 작성해야 하는 경우에 코드 이해가 불편
- 그러나 대부분의 기능은 내장 콜백을 사용하는 편리한 메소드를 이용하여 문제X
- 스프링은 일부 데이터 액세스 기술을 템플릿 대신 해당 API 그대로 사용해주기도 함
- 템플릿과 데이터 액세스 기술 API 사용 방법을 모두 지원하는 기술이라면 선택 가능
- 다만 스프링이 지원하지 않는 방식으로 데이터 액세스 기술을 사용하면 예외 변환과 트랜잭션 동기화의 혜택을 받기 어려움
2.1.3 DataSource
- DB를 사용하려면 Connection 타입의 DB 연결 오브젝트가 필요
- Connection은 모든 데이터 액세스 기술에서 사용되는 필수 리소스
- 엔터프라이즈 환경에서는 각 요청마다 Connection 새롭게 만들고 종료
- 커넥션을 매번 새롭게 만드는 건 비효율적이고 성능 저하
- 보통 미리 정해진 개수만큼의 DB 커넥션을 풀에 준비 후 애플리케이션이 요청할 때마다 풀에서 꺼내 하나씩 할당해주고 다시 돌려받아서 풀에 넣는 식의 풀링 기법을 이용
- 스프링에선 DataSource를 하나의 독립된 빈으로 등록하도록 강력하게 권장
- 스프링 데이터 엑세스 기술의 다양한 서비스에서 DataSource를 필요로 하고 있기 때문에 공유 가능한 스프링 빈으로 등록해줘야 함
- 스프링은 주요 데이터 액세스 기술이 자체적인 DataSource 생성 방식 대신 스프링 빈으로 등록된 DataSource를 사용하는 데 필요한 방법을 제공
학습 테스트와 통합 테스트를 위한 DataSource
- DataSource는 운영환경에서는 절대 사용해서는 안 되므로 주의가 필요
- 설정파일을 개발, 테스트, 운영환경에서 매번 수정해서 사용하지말고 개발용, 테스트용 스프링 설정파일을 따로 만들어 적용하는 것이 좋음
SimpleDriverDataSource
- 스프링이 제공하는 가장 단순한 DataSource 구현 클래스
- getConnection()을 호출할 때마다 DB 커넥션을 새로 만들고 풀 관리 하지 않음
- 실전에서 절대 사용X, 단순한 테스트용으로만 사용
SingleConnectionDataSource
- 하나의 물리적인 DB 커넥션만 만들어두고 이를 계속 사용하는 DataSource
- 순차적으로 진행되는 통합 테스트에서는 사용 가능하지만 동시에 두 개 이상의 스레드가 동작하는 경우에는 하나의 커넥션을 공유하게 되므로 위험
- 매번 DB 커넥션을 생성하지 않기 때문에 SimpleDriverDataSource에 비해 빠르게 동작
오픈소스 또는 사용 DB 커넥션 풀
- 오픈소스로 개발된 DB 커넥션 풀도 많이 사용
- 서버의 DB 풀로 등록해서 사용할 수도 있지만 일반적으로 애프리케이션 레벨에서 전용 DB 풀을 만들어 사용
아파치 Commons DBCP
- 가장 유명한 오픈소스 DB 커넥션 풀 라이브러리
c3p0 JDBC/DataSource Resource Pool
- JDBC 3.0 스펙을 준수하는 Connection과 Statement 풀을 제공하는 라이브러리
- 다양한 종류의 DB 풀과 옵션을 제공하므로 적절한 클래스와 프로퍼티를 설정을 이용
상용 DB 커넥션 풀
- 일부 상용 DB는 자체적으로 커넥션 풀 라이브러리를 제공
- 스프링의 빈으로 등록 가능하고 프로퍼티를 통해 설정이 가능하다면 어떤 것도 사용가능
JNDI/WAS DB 풀
- 대부분의 자바 서버는 자체적으로 DB 풀 서비스를 제공
- DB 풀 라이브러리를 사용해 애플리케이션 레벨이 아닌 서버가 제공하는 DB 풀을 사용해야 하는 경우에는 JNDI를 통해 서버의 DataSource에 접근 필요
<jee:jndi-lookup>
를 이용하면 JNDI를 통해 가져온 오브젝트를 스프링 빈으로 사용 가능
- 서버에 jdbc/DefaultDS라는 이름으로 등록된 서버의 데이터 소스가 있을때 아래와 같이 등록
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/DefaultDS" />
- JNDI의 환경설정 값을 제공하려면
<jee:environment>
를 이용
- JNDI에서 검색해서 가져오는 빈 오브젝트는 서버 밖에서는 동작X, 테스트환경 활용 어려움
- 테스트용으로 따로 준비된 DataSource가 정의되어 있는 테스트용 설정파일을 사용
- JNDI를 이용한 빈 설정파일을 테스트에서 사용하고 싶다면 스프링 테스트 프레임워크가 제공하는 JNDI 목 오브젝트를 사용 가능
- 테스트 환경에서 지정해주려면 SimpleNamingContextBuilder를 이용
- SimpleNamingContextBuilder는 JVM 레벨의 JNDI 오브젝트를 바인딩하는 기능을 제공
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); SimpleDriverDataSource ds = new SimpleDriverDataSource(...); builder.bind("jdbc/DefaultDS", ds); builder.activate();
'개발서적 > 토비 스프링 3.1-Vol.2' 카테고리의 다른 글
[토비의 스프링 - Vol.2] 2장 - 2.3 iBatis SqlMaps (0) | 2022.01.17 |
---|---|
[토비의 스프링 - Vol.2] 2장 - 2.2 JDBC (0) | 2022.01.17 |
[토비의 스프링 - Vol.2] 1장 - 1.5.5 프로퍼티 소스 (0) | 2022.01.17 |
[토비의 스프링 - Vol.2] 1장 - 1.5.4 런타임 환경 추상화와 프로파일 (0) | 2022.01.17 |
[토비의 스프링 - Vol.2] 1장 - 1.5.3 웹 애플리케이션의 새로운 IoC 컨테이너 구성 (0) | 2022.01.17 |