이번에 게시판 구현을 하고 발표를 하면서 추가적으로 알게된 내용에 대해서 정리해보려고 공부를 했다.
생각보다 알아야 할 내용들이 너무 많더라..
어노테이션 종류도 너무많고 기본 개념에 대해서 이해를 좀 다하고 가고싶었다...
차근차근 공부한 내용을 포스팅 해야겠다..
일단 오늘은 만솔님이랑 스터디하면서 새롭게 알게된내용을 위주로 한번..작성해바야겟다..
1. JPA (Java Persistence API) 란 ?
- JPA는 Java 객체와 DB 테이블을 매핑해주는 ORM(Object(객체)-Relational Mapping(관계형DB)) 기술
- JDBC는 개발자가 SQL을 직접 작성했는데 JPA는 자바 객체를 조작하는것처럼 코딩해서 DB를 다루는 방식이다.
- 주요 흐름:
- `EntityManager`가 객체를 DB에 저장, 수정, 삭제, 조회
- 이때 내부적으로 SQL을 자동 생성해서 DB에 전달함
`EntityManager`는 JPA(Java Persistence API)에서 엔티티를 관리하는 핵심 인터페이스라고한다.
이것은 JPA (Hibernate) 관련!
이름부터 아예 영속성(Persistence)이라는 단어가 들어간다..ㅋ
영속성이라는 개념을 모르고는 JPA를 사용할 수가 없겠구나..
핵심 특징은
- 자동 SQL생성을 해주고 ( `save()`, `find()`, `delete()` 같은 메서드만 써도 자동으로 SQL이 실행 )
- 객체와 테이블 매핑을 해준다 (Java클래스와 DB테이블을 연결)
- 그리고 변경감지(더티체킹)기능이 있다. (객체값만 바꿔도 JPA가 알아서 UPDATE해준다...짱..ㅋ)
더티체킹은 변경된 필드만 트랜적션 시점에 업데이트해서 오버헤드를 방지하고
프로젝션은 필요한 필드만 조회한다 둘다 성능향상에 도움이되는 편리한 기능이있다.
공부를 하다보니까 각 class주체에 대해서 궁금해졌는데 파면 팔수록..공부할게 계속나온다..
- Spring Framework → 트랜잭션, DI 등 전체 구조
- JPA (Hibernate) → ORM 핵심 기능
- Spring Data JPA → 리포지토리 자동 구현, Projection 등 편리한기능제공
| 구분 | Spring Framework | JPA (Hibernate) | Spring Data JPA |
| 핵심 역할 | 전체 앱 구조 + 트랜잭션 관리 | ORM 엔진 (DB ↔ 객체 매핑) | JPA를 더 쉽게 쓰는 도구 |
| 주로 제공하는 기능 | AOP, DI, 트랜잭션, 선언적 설정 등 | Entity 관리, 더티 체킹, 연관관계, 쿼리 실행 | Repository 자동 생성, 쿼리 메서드, Projection 등 |
| 대표 어노테이션 | @Transactional, @Component, @Service | @Entity, @Id, @ManyToOne 등 | @Repository, @Query, @Modifying, @EntityGraph |
| 학습 포인트 | 구조와 제어 흐름 | ORM 핵심 원리 | 빠르고 간단한 데이터 접근 |
Spring Data JPA의 사용방법은
- 1. 엔티티를 만든다.
- 2. 레포지토리 인터페이스를 만든다
- `JpaRepository<T, ID>`를 상속하면 CRUD 메서드를 자동으로 사용가능
- 예: findAll(), findById(), save(), delete() 등
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByName(String name); // 자동 쿼리 생성
}
Spring Data JPA의 "쿼리 메서드(Query Method)" 규칙
JpaRepository<T, ID>를 상속하면 기본 CRUD 메서드는 자동으로 제공되지만,
그 외에 특정 조건으로 조회하고 싶을 때는 메서드 이름만으로 쿼리를 생성할 수 있다.
- 메서드명이 너무 길어지면 @Query나 QueryDSL 사용하는 게 더 낫다
- And, Or는 우선순위에 주의 (괄호처럼 처리 X, AND가 항상 먼저 실행됨)
- 반환 타입은 `List`, `Optional`, `Page`, `Slice` 등 다양하게 설정 가능
📍 다양한 반환타입
| 메서드 | 설명 |
| `List<Member> findByName(String name)` | 조건에 맞는 전체 리스트 |
| `Optional<Member> findByEmail(String email)` | 하나만 있을 때 (null 대비) |
| `Page<Member> findByTeam(Team team, Pageable pageable)` | 페이징된 결과 |
📍 자주쓰는 키워드 규칙
jpa를 사용하기전에 대강 키워드만봤을때 나는 sql이 더 익숙해서 너무 번잡스럽다고생각했는데 키워드만 처음에 제대로 적립해놓으면 간단하게 사용 할 수 있겠다. like같은건 ㅋ 왜 더 길게 키워드를 생성했는지는 모를일이지만
| 키워드 | 의미 | 예시 | 생성 쿼리 |
| `findBy` | 조회 시작 | `findByName` | `WHERE name = ?` |
| `And` / `Or` | 조건 결합 | `findByNameAndAge` | `WHERE name = ? AND age = ?` |
| `Between` | 범위 조회 | `findByAgeBetween` | `WHERE age BETWEEN ? AND ?` |
| `LessThan` / `GreaterThan` | 비교 | `findByAgeGreaterThan(20)` | `WHERE age > 20` |
| `Like` / `Containing` | 부분 검색 | `findByNameContaining("길")` | `WHERE name LIKE %길%` |
| `StartsWith` / `EndsWith` | 접두/접미 검색 | `findByNameStartsWith("홍")` | `LIKE '홍%'` |
| `In` | 리스트 조건 | `findByNameIn(List<String> names)` | `WHERE name IN (...)` |
| `IsNull` / `IsNotNull` | null 체크 | `findByEmailIsNull()` | `WHERE email IS NULL` |
| `OrderBy` | 정렬 | `findByAgeOrderByNameAsc()` | `ORDER BY name ASC` |
| `Top1, First3` | 상위 N개 제한 | `findTop1ByOrderByAgeDesc()` | `LIMIT 1` |
📍 예시
// 단일 조건
List<Member> findByName(String name);
// 다중 조건
List<Member> findByNameAndAge(String name, int age);
// 부분 일치
List<Member> findByNameContaining(String keyword);
// 정렬 포함
List<Member> findByAgeGreaterThanOrderByNameDesc(int age);
// 리스트 조건
List<Member> findByTeamNameIn(List<String> teamNames);
JPA를 더 잘 쓰기위한 키워드
이것말고도 훨씬 다양한 어노태이션이있지만 기본적으로 아래 표의 것들은 완전 기본이되는 어노태이션같다.
아래의 내용은 차차 쪼개서 포스팅을 하겠다.
| 개념 | 설명 |
| Entity | DB 테이블과 연결되는 자바 클래스 |
| @Id | 기본 키 지정 |
| @GeneratedValue | 기본 키 자동 생성 전략 |
| @OneToMany / @ManyToOne | 테이블 간 관계 매핑 |
| @Transactional | 트랜잭션 설정 (commit/rollback) |
| FetchType.LAZY | 지연 로딩 (성능 최적화) |
| JPQL / QueryDSL | SQL 대신 객체 기반 쿼리 작성 |
2. Projection 이란?
- DB에서 전체 Entity가 아닌 필요한 컬럼만 선택해서 조회하는 방법
- 성능 향상, 네트워크 트래픽 감소 등에 유리
스터디를 하면서 프로젝션이라는 개념을 처음알았는데 프로젝션에는 세가지 종류 있다.
동적/중첩 프로젝션은 어려운 개념인것같아서 우선 가장 많이 사용하는 방식 두가지를 공부해봤다.
| 유형 | 설명 | 장점 | 단점 |
| 인터페이스 기반 | 특정 getter 이름으로 조회할 필드 지정 | 가볍고 선언만으로 동작 | 복잡한 연산 불가 |
| 클래스 기반(DTO) | 생성자 또는 정적 팩토리 메서드로 값 전달 | 가공/로직 추가 가능 | 코드가 약간 복잡함 |
📍 인터페이스 기반 프로젝션
`username`만 SELECT 됨! (`SELECT m.username FROM Member m WHERE m.age > ?`)
public interface UsernameOnly {
String getUsername();
}
public interface MemberRepository extends JpaRepository<Member, Long> {
List<UsernameOnly> findByAgeGreaterThan(int age);
}
📍 클래스 기반 프로젝션 (DTO)
JPQL로 DTO 직접 매핑하는 방식
public class MemberDto {
private final String username;
public MemberDto(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
}
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("SELECT new com.example.MemberDto(m.username) FROM Member m WHERE m.age > :age")
List<MemberDto> findDtoByAgeGreaterThan(@Param("age") int age);
}
📍 요약
| 방식 | 설명 | 특징 |
| 인터페이스 기반 | `getXXX()` 선언만 하면 자동 매핑 | 제일 간편 |
| 클래스 기반 | 생성자 있는 DTO로 직접 매핑 | 유연성 높음 |
| 동적/중첩 | 복잡한 중첩 구조도 표현 가능 | 구조가 복잡함 |
'공부일기.. > JPA' 카테고리의 다른 글
| [JPA] Spring Data JPA 페이징 (3/3) - 성능 최적화와 테스트 (0) | 2025.12.13 |
|---|---|
| [JPA] Spring Data JPA 페이징(2/3) - 실무 패턴과 동적 쿼리 (0) | 2025.12.11 |
| [JPA] Spring Data JPA 페이징 (1/3) - 기본 개념과 핵심 객체 (0) | 2025.12.08 |
| [jpa] BaseEntity와 JPA Auditing - 동작 원리 , 중복필드 제거 (예시코드) (0) | 2025.10.18 |
| [JPA] JPA의 필수개념_2 (식별자 전략 (@Id, @GeneratedValue)) (1) | 2025.06.26 |