[WIL] GDG Spring 세션 6주차

Nakyeong Lee·2024년 11월 23일
0

Index

DAO와 JDBC 템플릿
트랜잭션
🔗resources

DAO와 JDBC 템플릿

JDBC 템플릿?

Spring JDBC Template은 JDBC(Java Database Connectivity)의 복잡함을 간소화하고, 반복적인 코드를 줄이는 데 도움을 주는 템플릿 클래스이다.

특징

  • 템플릿 메서드 패턴 구현
    JDBC Template은 템플릿 메서드 패턴을 활용하여 데이터베이스 작업의 구조를 정의하고, 세부 구현을 콜백 메서드로 위임한다.
    • 반복 작업 추상화: 데이터 연결 및 해제, 예외 처리 등의 공통 작업을 자동으로 처리한다.
    • 콜백 사용: RowMapper, ResultSetExtractor 등을 사용하여 결과를 개발자가 원하는 방식으로 매핑할 수 있다.
  • 대량 작업 지원
    batchUpdate() 메서드를 통해 다량의 데이터 작업(예: 일괄 삽입)을 효율적으로 수행할 수 있다.

템플릿 메서드 패턴

템플릿 메서드 패턴은 메서드의 구조를 정의하고, 일부 단계를 하위 클래스에서 구현하도록 하는 디자인 패턴이다. Spring JDBC Template은 이 패턴을 활용하여 JDBC 작업의 기본 구조를 제공하며, 반복적인 코드 작성을 줄이고 코드 재사용성을 극대화한다.

템플릿 메서드 패턴의 이점

  • 코드 표준화: 데이터 접근 로직이 일관된 구조를 유지한다.
  • 커스터마이징 가능: 특정 로직을 필요에 따라 재정의할 수 있다.
  • 중복 제거: 자원 관리 및 예외 처리를 템플릿이 자동으로 처리한다.

Spring JDBC 사용법

  1. 의존성 추가
  2. DataSource 설정
  3. JdbcTemplate 생성

JDBC 템플릿의 장점

자원 관리 자동화

Spring이 자원의 열기와 닫기를 자동으로 처리하므로, 개발자는 메모리 누수에 대해 걱정할 필요가 없다.

예외 변환

Spring은 JDBC 예외를 DataAccessException으로 변환하여 예외 처리를 일관되게 만든다.

코드 간소화

반복적인 코드 작성을 줄여 개발자가 핵심 로직에 집중할 수 있도록 도와준다.

배치 작업 지원

batchUpdate()를 통해 대규모 데이터 작업을 효율적으로 처리할 수 있다.

JDBC 사용 시 문제점

코드 중복

데이터베이스 연결, 쿼리 실행, 자원 정리 등 반복적인 작업이 많아 코드가 복잡해진다.

예외 처리의 번거로움

JDBC는 checked 예외를 사용하므로, 각 작업마다 예외를 처리하거나 전달해야 한다.

자원 관리 부담

Connection, Statement, ResultSet 등 자원을 직접 관리해야 하며, 잘못된 자원 관리는 메모리 누수를 초래할 수 있다.

JPA와 JDBC의 비교

특징JPAJDBC
코드 복잡성간결함 (SQL 자동 생성)복잡함 (SQL 직접 작성 필요)
객체 지향 지원엔티티와 관계를 기반으로 객체 지향 설계 가능객체 지향 지원 없음
성능 최적화1차 캐시, Lazy Loading 등 최적화 기능 제공최적화 기능 없음
데이터 접근 제어선언적 트랜잭션 관리 지원직접 트랜잭션 관리 필요

DAO?

Data Access Object
데이터 접근을 간소화하는 핵심 기술

DAO(Data Access Object)는 애플리케이션에서 데이터베이스와의 상호작용을 추상화하고 캡슐화하는 디자인 패턴이다. 이 패턴은 데이터 소스 접근과 비즈니스 로직을 분리하여 코드의 재사용성과 유지보수성을 높이는 데 중요한 역할을 한다.

스프링 DAO의 역할

데이터 접근 캡슐화

DAO는 데이터베이스와 상호작용하는 로직을 캡슐화한다. 이를 통해 개발자는 SQL 쿼리, 데이터 소스 세부 사항 등을 비즈니스 로직과 분리할 수 있다. 결과적으로 코드의 가독성과 유지보수성이 크게 향상된다.

코드 재사용성

DAO 패턴은 데이터 소스와 독립적인 일관된 인터페이스를 제공한다. 이는 동일한 로직을 다양한 데이터 소스(MySQL, PostgreSQL, MongoDB 등)에서 재사용할 수 있도록 도와준다.

유지보수 용이성

데이터 접근 로직을 한 곳에 집중시킴으로써, 변경 사항이 발생했을 때 해당 DAO 클래스만 수정하면 된다. 이는 애플리케이션 전체에서의 일관성을 유지하고 유지보수의 복잡성을 줄이는 데 기여한다.

스프링 DAO의 필요성

코드 간소화

Spring DAO는 JDBC와 관련된 반복적인 코드를 줄여준다. 데이터베이스 연결, PreparedStatement 생성, ResultSet 처리와 같은 번거로운 작업은 Spring이 관리하며, 개발자는 핵심 비즈니스 로직에만 집중할 수 있다.

예외 처리 개선

기존 JDBC는 checked 예외를 사용하는데, 이는 매번 예외를 처리하거나 상위 메서드로 전달해야 하므로 코드가 복잡해질 수 있다. Spring은 checked 예외를 unchecked 예외로 변환하여, 예외 처리를 더 유연하게 관리할 수 있도록 합니다. Spring이 제공하는 DataAccessException은 데이터 접근과 관련된 예외를 계층화된 구조로 제공하여 특정 예외에 따라 적절히 대처할 수 있게 합니다.

테스트 용이성

Spring은 의존성 주입(DI, Dependency Injection)을 통해 DAO를 쉽게 모의(Mock) 객체로 대체할 수 있도록 합니다. 이를 통해 실제 데이터베이스 없이도 단위 테스트를 수행할 수 있어 개발 및 디버깅 속도가 빨라집니다.

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {

    @Mock
    private UserDao userDao;

    @InjectMocks
    private UserService userService;

    @Test
    public void testFindUser() {
        User mockUser = new User(1, "John Doe");
        Mockito.when(userDao.findById(1)).thenReturn(mockUser);

        User user = userService.findUserById(1);
        Assertions.assertEquals("John Doe", user.getName());
    }
}

트랜잭션

트랜잭션?

트랜잭션은 데이터베이스 작업의 일관성, 안정성, 신뢰성을 보장하는 핵심 개념으로 데이터베이스에서 여러 작업을 하나의 논리적 단위로 묶어 수행한다.
JDBC Template은 Spring의 트랜잭션 관리 기능을 활용할 수 있다.

트랜잭션의 4가지 주요 속성

  • 원자성 (Atomicity): 모든 작업이 성공하거나 모두 실패해야 함.
  • 일관성 (Consistency): 트랜잭션 전후로 데이터베이스 상태가 일관되게 유지됨.
  • 격리성 (Isolation): 동시 실행 트랜잭션 간 간섭 방지.
  • 지속성 (Durability): 트랜잭션 완료 후 변경 사항이 영구적으로 반영됨.

트랜잭션 관리의 중요성

Spring에서 트랜잭션 관리의 핵심 목표는 데이터 무결성과 안정성을 유지하는 것이다.

  • 데이터 일관성 유지
    트랜잭션은 여러 작업을 하나의 단위로 묶어 실행하므로, 모든 작업이 성공하거나 모두 롤백된다.
  • 에러 복구
    트랜잭션 중 문제가 발생하면 롤백(Rollback) 을 통해 데이터를 복구한다. 이는 시스템이 오류 상황에서도 안정성을 유지할 수 있게 해준다.
  • 동시성 제어
    여러 사용자가 동일한 데이터를 동시에 접근하거나 수정하는 경우, 경쟁 상태를 방지한다. 이를 통해 데이터의 정확성과 일관성을 유지할 수 있다.

선언적 트랜잭션 관리

Spring은 선언적 트랜잭션 관리를 통해 간단한 설정으로 트랜잭션 기능을 활성화할 수 있다.

트랜잭션 관리자 설정

DataSourceTransactionManager를 빈으로 등록하여 JDBC 기반 트랜잭션을 관리한다.

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

@EnableTransactionManagement 사용

Spring 설정 클래스에 @EnableTransactionManagement 어노테이션을 추가하여 트랜잭션 관리를 활성화한다.

@Configuration
@EnableTransactionManagement
public class AppConfig {
    // DataSource 및 TransactionManager 설정
}

@Transactional 사용

트랜잭션이 필요한 메서드나 클래스에 @Transactional을 붙여 트랜잭션 처리를 정의한다.

@Transactional
public void performTransactionalOperation() {
    // 트랜잭션 내에서 수행될 작업
}

트랜잭션 전파란?

트랜잭션 전파(Propagation)는 하나의 트랜잭션이 진행 중일 때 다른 트랜잭션을 실행하는 경우, 트랜잭션의 동작 방식을 정의하는 개념이다.

필요성

  • 메서드 호출: 한 메서드가 다른 메서드를 호출할 때 트랜잭션을 공유하거나 새로 생성할지 결정한다.
  • 안전한 데이터 처리: 작업을 하나의 단위로 묶어 처리하여 중간 실패 시 모든 작업을 취소한다.
  • 설정 용이성: Spring에서 복잡한 코드 없이 간단히 설정 가능하다.

전파 속성

  1. REQUIRED (기본 설정)

    • 기존 트랜잭션이 있으면 참여하고, 없으면 새 트랜잭션을 생성한다.
    • 가장 일반적으로 사용된다.
  2. REQUIRES_NEW

    • 항상 새로운 트랜잭션을 시작하며, 기존 트랜잭션은 일시 중단된다.
  3. NESTED

    • 기존 트랜잭션 내부에서 중첩 트랜잭션을 실행한다.
    • 부분적 롤백이 가능하다.
  4. SUPPORTS

    • 트랜잭션이 있으면 참여하고, 없으면 비트랜잭션으로 실행한다.

에러 처리

트랜잭션 내에서 발생하는 예외를 적절히 처리하여 데이터 무결성을 유지할 수 있다.

전파 설정

@Transactionalpropagation 속성을 통해 전파 방식을 지정한다.

예외 처리

  • Spring은 기본적으로 RuntimeException 발생 시 트랜잭션을 롤백한다.
  • 특정 예외에 대해 롤백 규칙을 설정할 수 있다.
@Transactional(rollbackFor = CustomException.class)
public void performOperation() {
    // CustomException 발생 시 롤백
}

롤백 규칙

rollbackFornoRollbackFor 속성을 사용해 세밀한 예외 처리 규칙을 정의할 수 있다.

CRUD 연산 예시

CREATE (INSERT)

  • JdbcTemplateupdate() 메서드를 사용하여 데이터를 삽입한다.
  • 자동 생성된 키 값을 얻기 위해 KeyHolder를 사용할 수 있다.
String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
    PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
    ps.setString(1, "John");
    ps.setInt(2, 30);
    return ps;
}, keyHolder);

READ (SELECT)

  • queryForObject()로 단일 데이터를, query()로 다중 데이터를 조회한다.
String sql = "SELECT * FROM users WHERE id = ?";
User user = jdbcTemplate.queryForObject(sql, new Object[]{1}, new UserRowMapper());

UPDATE

  • update() 메서드를 사용하며, 다중 파라미터나 배치 업데이트도 지원한다.
String sql = "UPDATE users SET age = ? WHERE id = ?";
jdbcTemplate.update(sql, 35, 1);

DELETE

  • update() 메서드로 DELETE 쿼리를 실행하며, 조건부 삭제가 가능하다.
String sql = "DELETE FROM users WHERE id = ?";
jdbcTemplate.update(sql, 1);

🔗resources

profile
Web Backend Developer

0개의 댓글