Skip to main content Link Search Menu Expand Document (external link)

핵심개념이해 4

  • JPA repository 원리
    • 직접 repository 를 만들어봄으로써 자동으로 해주는 작업들이 뭔지 알아보기
    • 자동으로 해주는 작업들의 작동 원리 알아보기
  • JPA 사용시 유의할 점

JPA repository 원리

직접 repository 를 만들어봄으로써 자동으로 해주는 작업들이 뭔지 알아보기

아래와 같이 JpaRepository 를 상속하면 기본적인 CRUD 오퍼레이션들을 repository 로 사용할 수 있다. 그리고 명시적으로 @Repository 로 설정해주지 않아도 자동으로 bean 으로 등록까지 된다.

public interface PostRepository extends JpaRepository<Post, Long> {
}

위의 일련의 과정을 그저 ‘이렇게 하면 Spring이 알아서 해준다’가 아니라 조금 더 자세히 들여다보자.

먼저 위의 방법이 아니라 실제로 EntityManager 를 이용해서 Repository 를 직접 만들어보자.

@Repository
@Transactional
public class PostRepository {

    @PersistenceContext
    private EntityManager entityManager;

    public Post save(Post post) {
        entityManager.persist(post);
        return post;
    }

    public Optional<Post> findById(Long id) {
        return Optional.of(entityManager.find(Post.class, id));
    }
    
}
@Component
public class JpaRunner implements ApplicationRunner {

    @Autowired
    private PostRepository postRepository;

    @Override
    @Transactional
    public void run(ApplicationArguments args) throws Exception {

        Post post = new Post();
        post.setName("첫번째 포스팅");
        postRepository.save(post);

    }
}

간단한 예제이지만 이렇게 직접 Repository 를 만들어보면 extends JpaRepository<Post, Long>를 통해서 스프링에서 해주는 많은 일들이 무엇이었나를 잘 알 수 있다. 내가 직접 만든 save, findById 외에도 수많은 기본적인 CRUD 오퍼레이션들을 내부적으로 자동으로 구현해주는 것이다.

자동으로 해주는 작업들의 작동 원리 알아보기

그렇다면 extends JpaRepository<Post, Long> 를 통해서 뒷단에서 발생하는 작업들은 어떤 원리로 발생하는 것인지 알아보자. JPA를 사용하려면 @EnableJpaRepositories 를 사용해줘야하는데 스프링부트에서는 해당 어노테이션이 기본적으로 사용되고 있다. (그래서 지금까지 명시적으로 적어줄 필요가 없었던 것이다)

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(JpaRepositoriesRegistrar.class)
public @interface EnableJpaRepositories {

여기서 JpaRepositoriesRegistrar 가 있는데, 이 어노테이션의 상속구조를 따라가다 보면 ImportBeanDefinitionRegistrar 라는 인터페이스를 상속하고 있음을 알 수 있다.

결국 여기서 org.springframework.data.jpa.repository.JpaRepository 를 상속하는 interface 를 repository 로 사용할 수 있도록 bean 으로 등록해주고, 기본적인 자원들을 내부적으로 만들어준다고 볼 수 있다.

이와 관련하여 더 자세한 사항은 Spring Data Common 에서 살펴본다.

JPA 사용하여 개발할때 가져야 할 습관

JPA를 사용한다는 것은 곧 의도적으로 직접 사용하지 않는 이상 쿼리를 직접 만들어서 수행요청하지 않는다는 것이다. 즉, 자동 생성된 쿼리가 수행된다는 의미이다.

따라서 필연적으로 의도치 않게 성능에 오히려 마이너스가 되는 형태로 쿼리가 생성되고 수행 요청이 될 수 있다. 그렇기 때문에 JPA를 사용한다면 항상 로그를 통해서 개발한 로직에서 의도한 방식으로 적절하게 쿼리가 생성되고, 수행요청 되는지를 확인하면서 개발을 진행하여야 한다.

반드시 이러한 원칙을 가지고 JPA 를 사용해야 한다.

이를 위한 프로퍼티 설정은 아래를 참고하자.

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/fistkim
    username: root
    password: root
  jpa:
    hibernate:
      ddl-auto: create
    show-sql: true <--- sql visible
    properties:
      hibernate:
        format_sql: true <--- sql format
logging:
  level:
    org.hibernate.type.descriptor.sql: trace <--- 수행되는 sql의 값 visible

JPA 를 이용한 개발을 할 때에는 반드시 발생하는 모든 쿼리를 로그를 통해 직접 확인한다.