차근차근 Modern Spring Boot 3 기초 (5) JPA Entity를 사용하는 JPA Repository
Spring Data JPA를 통해 손쉬운 기초 CRUD
JPA Repository 객체를 다루기 위해 알아야 할 것
- JPA Repository로 만든 repository 객체들은 스프링에서 bean(빈)이라는 것으로 관리됩니다.
이 개념을 이해하고 설명하기 위해 다음 개념들을 학습해야 합니다.
레이어드 아키텍처(Layered Architecture)
수직적으로 계층을 나누는 프로젝트 아키텍처(프로젝트 구조)입니다. 그중 대표적으로 세 계층에 대하여 알아야 합니다. 우리가 기억해야 할 것은 코드에서 직접 명명하여 사용하는 다음 세 명칭입니다.
⭐️ 컨트롤러(Controller)
사용자의 요청을 받아 사용자에게 응답합니다. 마치 은행 창구처럼 사용자와 직접 소통을 주고 받는 계층입니다. 따라서 필요한 처리에 대하여, 다른 계층에 명령을 전달하는 역할을 하며, 계층에서는 지휘관 역할로 이해할 수 있습니다.
따라서 컨트롤러의 소스 코드는, 마치 영어 문장을 읽듯이 편하게 읽히는 수준에 가깝게 작성하여, 로직 흐름을 쉽게 파악할 수 있도록 하는 것이 좋습니다. 복잡한 처리는 실무자인 서비스 계층으로 넘겨 주는 것이 좋습니다.
⭐️ 서비스(Service)
복잡한 처리를 역할별로 담당하는 계층입니다. 역할에 따라 실무자가 따로 존재하는 것이 좋습니다. 프로그래밍에서 고전적으로 함수를 나누어 작성함으로써 코드의 가독성을 높여 왔는데, 그런 함수 묶음을 관리하는 것은 주로 서비스 계층의 역할입니다. (일부 동작은 유틸리티 클래스로 대체 가능)
⭐️ 레포지터리(Repository)
서비스 계층에서 관리하는 여러 처리는 주로 프로그램 내부 로직입니다. 프로그램 외부와 소통하기 위한 영역은 따로 구분해 두는 것이 좋습니다.
외부와 소통하는 로직은, 프로그램 내부 로직의 흐름 중 일부분으로 포함되면서도, 프로그램 외부와 소통하기 위하여 외부에도 종속되기 때문에, 프로그램 내부에서 다룰 땐 독립적 관리가 중요합니다.
따라서 여러 처리 중에서도 데이터베이스와 연결되는 영역은 레포지터리(repository)라는 빈으로 관리하게 됩니다. (Persistence layer)
IoC 컨테이너와 Bean
순수하게 자바를 배우는 학습자는 인스턴스를 생성하기 위해서 new 생성자()
등의 코드로 직접 객체를 생성해야 하며, 이것을 변수 등에 직접 대입하여 사용해야 한다고 알고 있을 것입니다.
하지만 프레임워크에서는 이러한 작업을 개발자가 직접 수행할 필요가 없는 경우가 많습니다. 개발자는 프레임워크가 요구하는 것들을 미리 준비해서 프레임워크에 제공하며, 전체적인 제어는 개발자가 아니라 프레임워크가 수행하는 '제어의 역전(IoC)'이라는 개념 덕분입니다.
스프링에서도 이 제어의 역전을 담당하는 'IoC 컨테이너'라는 것이 있는데, 이 컨테이너는 제어의 역전과 동시에 몇몇 주요한 개념에 관련하여 핵심 동작을 관리합니다. IoC 컨테이너를 통한 빈(bean)의 관리와 의존성 주입(DI; Dependency Injection) 개념을 짧게 다룹니다.
스프링에서 빈을 쉽게 이해하기 위해서는, 이것이 어떤 의미로는 단순히 객체를 뜻한다는 것을 이해해야 합니다. 빈은 재사용 가능한 컴포넌트 객체인데, 위에서 설명한 컨트롤러, 서비스, 레포지터리 등이 모두 빈으로 등록되는 것들입니다.
특징적인 것은 우리가 new 키워드 등을 통해 직접 객체를 생성하지 않아도, 몇몇 애노테이션이나 기타 스프링에서 사용 가능한 방식으로 표시해 두면 자동으로 객체가 생성되어 빈으로 등록된다는 것입니다. 참고로 빈 관리에서 보통 선택하는 전략은 싱글톤 전략이고, 하나의 객체만 만들어 두고 재사용합니다. (단, 싱글톤 패턴을 완전히 충족하지는 않습니다.)
JPA Repository
JpaRepository<T, ID>
인터페이스를 계승하는 인터페이스를 작성해 두면 자동으로 구현되어 빈으로 등록도 됩니다. 다음이 예시입니다.
public interface AccountRepository extends JpaRepository<Account, UUID> {
// Account save(Account entity);
// Optional<Account> findById(UUID id);
// boolean existsById(UUID id);
// void deleteById(UUID id);
// ...
}
JpaRepository<다룰_엔티티, 아이디_타입>
인터페이스를 통해save
,findById
등 이미 생성되어 있는 메서드를 사용할 수 있습니다. 또한 메서드 네이밍의 규칙을 잘 따른다면 메서드를 커스텀하여 사용할 수 있습니다.상단에
@Repository
애노테이션을 사용하지 않아도 빈으로 등록됩니다.
이제 서비스 클래스 등 context로 관리되는 스코프에서 이 JPA Repository의 객체인 빈을 주입받아 사용할 수 있습니다. 빈 등록은 이번 글에서 다루었고, 다음 글에서는 등록된 빈을 사용해 보겠습니다.
< Prev
Persistent Entity 만들기(JPA Entity)
Next >