TIL - 20251108

juni·2025년 11월 7일

TIL

목록 보기
172/316

1108 Spring Boot: JPA 연동과 테스트 코드 작성


✅ 1. Spring Data JPA: 데이터 접근 계층의 자동화

  • Spring Data JPA는 JPA(Java Persistence API)를 더 쉽고 효율적으로 사용할 수 있도록 도와주는 Spring 프레임워크의 모듈입니다. 복잡한 데이터 접근 계층(DAO) 구현을 자동화하여 개발 생산성을 획기적으로 높여줍니다.

JpaRepository 인터페이스

  • 역할: 데이터베이스에 대한 CRUD(생성, 조회, 수정, 삭제) 작업을 위한 인터페이스입니다.
  • 사용법: 개발자는 JpaRepository<Entity, ID> 인터페이스를 상속받는 자신만의 Repository 인터페이스를 정의하기만 하면 됩니다.
    public interface UserRepository extends JpaRepository<User, Long> {
        // 이 인터페이스를 정의하는 것만으로...
    }
  • 제공되는 기능: 위와 같이 인터페이스만 정의해도, Spring Data JPA는 런타임에 자동으로 구현체를 만들어 다음과 같은 기본 메서드들을 제공합니다.
    • save(entity): 데이터 저장 (INSERT) 및 수정 (UPDATE)
    • findById(id): ID로 단건 조회 (SELECT)
    • findAll(): 모든 데이터 조회 (SELECT)
    • deleteById(id): ID로 데이터 삭제 (DELETE)
    • count(): 전체 데이터 개수 조회

➕ 쿼리 메서드 (Query Methods)

  • 개념: 정해진 명명 규칙에 따라 메서드 이름을 작성하면, Spring Data JPA가 해당 이름에 맞는 JPQL(Java Persistence Query Language) 쿼리를 자동으로 생성하여 실행하는 기능입니다.

  • 규칙: findBy, countBy 등의 접두사 뒤에 엔티티의 필드 이름을 조합하여 작성합니다.

  • 예시:

    public interface UserRepository extends JpaRepository<User, Long> {
        // SELECT * FROM users WHERE username = ?
        Optional<User> findByUsername(String username);
    
        // SELECT * FROM users WHERE email = ? AND status = ?
        List<User> findByEmailAndStatus(String email, UserStatus status);
    
        // SELECT COUNT(*) FROM users WHERE status = ?
        long countByStatus(UserStatus status);
    }
  • 장점: 간단한 조회 쿼리는 SQL이나 JPQL을 한 줄도 작성하지 않고, 메서드 선언만으로 해결할 수 있어 매우 편리합니다.


✅ 2. JPA 엔티티(Entity)와 데이터베이스 매핑

  • 엔티티: 데이터베이스의 테이블과 직접적으로 매핑되는 Java 객체입니다. JPA는 이 엔티티 객체의 변화를 감지하여 데이터베이스에 자동으로 SQL을 실행합니다.

➕ 주요 어노테이션 복습

  • @Entity: 이 클래스가 JPA가 관리하는 엔티티임을 선언합니다.
  • @Table: 엔티티와 매핑될 테이블의 이름을 지정합니다.
  • @Id: 테이블의 기본 키(Primary Key)에 해당하는 필드임을 나타냅니다.
  • @GeneratedValue(strategy = GenerationType.IDENTITY): 기본 키 값을 데이터베이스(e.g., MySQL의 AUTO_INCREMENT)가 자동으로 생성하도록 위임합니다.
  • @Column: 필드와 매핑될 컬럼의 세부 속성(이름, nullable, unique 등)을 지정합니다.

✅ 3. 테스트 코드 작성의 중요성과 Spring Boot 테스트

  • 테스트 코드는 내가 작성한 코드가 의도한 대로 정확하게 동작하는지를 검증하는 코드입니다. 테스트 코드는 코드의 안정성을 보장하고, 리팩토링 시 자신감을 주며, 코드 자체를 설명하는 문서의 역할을 합니다.

  • Spring Boot Test: Spring Boot는 테스트를 매우 쉽게 작성할 수 있도록 강력한 테스트 지원 기능을 제공합니다.

➕ 주요 테스트 어노테이션

  1. @SpringBootTest:

    • 통합 테스트(Integration Test)를 위한 핵심 어노테이션입니다.
    • 실제 애플리케이션과 거의 동일한 환경(모든 Bean을 Spring 컨테이너에 로드)을 구성하여 테스트를 진행합니다.
    • 장점: 실제 운영 환경과 가장 유사한 조건에서 테스트할 수 있어 신뢰도가 높습니다.
    • 단점: 모든 Bean을 로드하므로 상대적으로 무겁고 실행 속도가 느립니다.
  2. @DataJpaTest:

    • JPA 관련 계층(Repository)만을 테스트하기 위한 슬라이스 테스트(Slice Test) 어노테이션입니다.
    • JPA와 관련된 Bean들(JpaRepository, EntityManager 등)만 컨테이너에 로드하므로 @SpringBootTest보다 훨씬 가볍고 빠릅니다.
    • 특징:
      • 기본적으로 인메모리 데이터베이스(In-memory DB, e.g., H2)를 사용하여 테스트를 실행합니다. (실제 DB 오염 방지)
      • 각 테스트 메서드가 끝날 때마다, 해당 메서드에서 수행된 모든 데이터베이스 작업을 자동으로 롤백(Rollback)합니다. 이를 통해 각 테스트는 서로에게 영향을 주지 않고 독립적으로 실행될 수 있습니다.

➕ JUnit 5와 AssertJ를 이용한 테스트 코드 예시

  • JUnit 5: Java 진영의 표준 테스트 프레임워크. @Test, @DisplayName 등의 어노테이션을 제공.
  • AssertJ: 테스트 결과의 검증을 위한 라이브러리. assertThat(결과).isEqualTo(기대값)과 같이 자연스러운 문법을 제공.
@DataJpaTest // JPA 계층 테스트
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    @DisplayName("사용자 저장 및 조회 테스트")
    void saveAndFindUserTest() {
        // given - 테스트 준비
        User newUser = new User("testuser", "password123");

        // when - 테스트 실행
        User savedUser = userRepository.save(newUser);
        Optional<User> foundUser = userRepository.findById(savedUser.getId());

        // then - 결과 검증
        assertThat(foundUser).isPresent(); // foundUser가 존재하는지 확인
        assertThat(foundUser.get().getUsername()).isEqualTo("testuser");
    }
}

📌 요약

  • Spring Data JPAJpaRepository 인터페이스와 쿼리 메서드를 통해 데이터 접근 계층의 개발을 극적으로 단순화합니다.
  • JPA 엔티티@Entity, @Id 등의 어노테이션을 통해 데이터베이스 테이블과 매핑됩니다.
  • 테스트 코드는 소프트웨어의 안정성을 보장하는 필수적인 요소이며, Spring Boot는 이를 위한 강력한 지원을 제공합니다.
  • @SpringBootTest통합 테스트에, @DataJpaTestJPA 계층의 단위 테스트에 사용되며, 가볍고 빠르며 자동 롤백 기능을 제공하여 Repository 테스트에 매우 유용합니다.

0개의 댓글