기술노트/백엔드.스프링부트
Spring JPA Repository 이해. 핵심 정리 | 업캐스팅, @Autowired
newlamb
2025. 4. 11. 21:23
Spring Boot와 JPA를 활용한 백엔드 개발에서는 JpaRepository, 인터페이스, 업캐스팅, @Autowired 주입 방식 등을 이해하는 것이 매우 중요합니다. 이 글에서는 비전공자나 초보자도 이해할 수 있도록 핵심 개념들을 순차적으로 정리합니다.
📌 1. 왜 BookRepository를 인터페이스로 선언할까?
public interface BookRepository extends JpaRepository<Book, Long> { }
🔍 이유:
- JpaRepository는 Spring Data JPA에서 제공하는 인터페이스로, CRUD 기능을 기본으로 제공
- 우리가 BookRepository를 인터페이스로 만들고 JpaRepository를 상속하면, Spring이 이 인터페이스의 프록시 구현체를 자동으로 생성해서 빈으로 등록함
- 개발자는 구현 없이도 Repository 사용 가능!
📘 2. JpaRepository는 인터페이스다. 그럼 추상 메서드는 어떻게 동작할까?
JpaRepository는 수많은 추상 메서드를 포함하고 있지만, 우리는 직접 구현하지 않습니다.
✨ Spring 내부 동작
- Spring이 런타임 시 JpaRepository를 구현한 클래스를 자동 생성함 (보통 SimpleJpaRepository)
- 이를 통해 인터페이스만 작성해도 CRUD 기능이 자동 제공됨
🔁 3. 인터페이스 간에도 상속이 가능한가요?
가능합니다!
public interface A { void methodA(); } public interface B extends A { void methodB(); }
- 인터페이스 → 인터페이스는 extends로 상속
- 클래스 → 인터페이스는 implements로 구현
🧠 4. 업캐스팅(Upcasting)의 개념과 사용 이유
BookRepository bookRepository = new EntityManager();
위 문장은 EntityManager가 BookRepository를 구현한 클래스일 경우 유효합니다.
✅ 업캐스팅이란?
- 자식 객체를 부모 타입으로 참조하는 것
- 목적: 유연한 코드, 의존성 주입(DI) 가능
인터페이스 변수 = 구현체 객체
- 이 구조 덕분에 Spring이 BookRepository 타입에 맞는 프록시 객체를 자동 주입할 수 있습니다.
📥 5. @Autowired로 주입할 때 실제로 무슨 일이 일어날까?
@Autowired private BookRepository bookRepository;
작동 흐름:
- Spring이 BookRepository 타입의 빈을 찾음
- 내부적으로는 SimpleJpaRepository 기반의 프록시 객체가 자동 생성됨
- 그 객체가 bookRepository에 자동 주입됨
🔁 DI(의존성 주입) 메커니즘이 핵심입니다.
🔍 6. 생성자 주입 vs 필드 주입 (@Autowired)
방식특징장점
필드 주입 | @Autowired 붙이기만 하면 됨 | 간단하지만 테스트 어려움 |
생성자 주입 | 생성자 통해 직접 주입 | 불변성 보장, 테스트 용이, 순환 참조 방지에 유리 |
📢 요즘은 생성자 주입이 강력히 권장됩니다.
🔑 7. extends vs implements 차이
키워드대상의미
extends | 클래스 → 클래스 인터페이스 → 인터페이스 |
상속 (코드 물려받기) |
implements | 클래스 → 인터페이스 | 구현 (메서드 내용 작성 필요) |
☑️ 핵심 요약
개념설명
JpaRepository | JPA에서 CRUD 기본 제공하는 인터페이스 |
인터페이스 상속 | interface B extends A 가능 |
업캐스팅 | 자식 객체를 부모 타입으로 참조하는 것 |
프록시 객체 | Spring이 생성한 구현체 (SimpleJpaRepository 기반) |
@Autowired | 자동 주입, 의존성 관리 핵심 어노테이션 |
생성자 주입 | 테스트 편하고 불변성 유지 가능 |
extends / implements | 상속 / 구현 키워드 |
💬 마무리
Spring JPA에서 Repository를 인터페이스로 만들고 JpaRepository를 상속하는 구조는 유지보수, 테스트, 생산성측면에서 아주 강력한 패턴입니다.
그 기반이 되는 업캐스팅, 인터페이스 상속, 프록시 주입 개념을 잘 이해하면, Spring의 DI 철학과 구조를 자연스럽게 받아들일 수 있게 됩니다.
📚 추천 학습 키워드
- Spring IoC / DI
- 프록시 패턴
- Bean Lifecycle
- SOLID 원칙 (특히 OCP)
- 자바 인터페이스 / 다형성
📊 Spring Data JPA 전체 동작 구조 & 흐름도 정리
🔄 전체 흐름 요약: Repository 생성부터 의존성 주입까지
[BookRepository 인터페이스]
↓ extends
[JpaRepository 인터페이스]
↓ 런타임 시 Spring 내부 처리
[SimpleJpaRepository 구현체 생성]
↓
[프록시 객체 생성 (Proxy)]
↓
[Spring 컨테이너에 Bean으로 등록]
↓
[Service에서 @Autowired or 생성자 주입]
📌 각 단계별 핵심 설명
✅ 1. 사용자 정의 Repository 인터페이스
public interface BookRepository extends JpaRepository<Book, Long> {}
- 사용자가 직접 구현 안 해도 됨
- Spring이 자동으로 구현체를 생성
✅ 2. JpaRepository 인터페이스
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID> {
// save, findById, delete 등 수많은 추상 메서드 포함
}
- 다형성 + 제네릭 덕분에 모든 엔티티에서 재사용 가능
- 내부적으로는 SimpleJpaRepository라는 클래스가 실제 구현체
✅ 3. Spring이 내부에서 구현체 생성 (프록시 방식)
BookRepository ← SimpleJpaRepository ← Repository 프록시 객체
- Spring은 BookRepository의 구현체를 만들지 않음
- 대신 SimpleJpaRepository 기반으로 프록시 객체를 생성해서 주입
📌 이게 바로 Spring Data JPA의 프록시 기반 동적 구현 전략
✅ 4. DI 컨테이너에서 Bean 등록 및 주입
@Autowired
private BookRepository bookRepository;
- Spring이 BookRepository 타입의 프록시 객체를 자동으로 주입
- 또는 생성자 주입 방식 사용 가능
🖼️ 시각화: 전체 흐름도 다이어그램
사용자 작성
┌──────────────────────────────┐
│ interface BookRepository │
│ extends JpaRepository │
└──────────────────────────────┘
│
▼
Spring 내부 처리
┌──────────────────────────────┐
│ interface JpaRepository │
│ extends PagingAndSorting... │
└──────────────────────────────┘
│
▼
Spring이 구현체 생성
┌──────────────────────────────┐
│ class SimpleJpaRepository │
│ implements JpaRepository │
└──────────────────────────────┘
│
▼
프록시 객체 생성 (동적 Proxy)
┌──────────────────────────────┐
│ Proxy(BookRepository) │
│ Bean으로 등록됨 │
└──────────────────────────────┘
│
▼
Service 등에서 주입
┌──────────────────────────────┐
│ @Autowired 또는 생성자 주입 │
│ private BookRepository repo; │
└──────────────────────────────┘
🧠 이 흐름이 중요한 이유
이유설명
유지보수성 | 인터페이스로 설계하면 구현체가 바뀌어도 코드 수정 최소화 |
테스트 용이성 | Mock 객체 주입이 쉬움 |
생산성 | 직접 구현 없이도 CRUD 기능 자동 제공 |
프레임워크 철학 | DI(의존성 주입), IoC(제어의 역전), OCP(개방-폐쇄 원칙) 실현 |
✅ 결론
Spring JPA의 Repository 구조는 "인터페이스 기반 설계 + 프록시 동적 생성 + DI 주입"이라는 강력한 조합으로 구성됩니다.
전체 흐름을 이해하고 나면, 복잡해 보이던 구조가 오히려 깔끔하고 유연하게 느껴질 거예요.