📕 목차
❤️ 학습 목표
- QueryDSL을 사용하여 타입 안전 쿼리를 작성하는 방법을 배웁니다. 복잡한 조건과 정교한 쿼리를 쉽게 구성할 수 있는 기법을 소개합니다.
- Auditing을 사용하여 엔티티의 생성 및 수정 시간을 자동으로 관리하는 방법을 배웁니다. Spring Data JPA에서 제공하는 Auditing 기능을 통해 데이터의 일관성과 추적성을 확보합니다.
- Projection을 사용하여 필요한 데이터만 선택적으로 조회하는 방법을 배웁니다. 과도한 데이터 로드를 방지하고 성능을 최적화하는 기법을 학습합니다.
1. 좀 더 멋지게 쿼리 생성하기 (QueryDSL)
QueryDSL
- 타입 안전한 쿼리를 자바 코드로 작성할 수 있게 도와주는 프레임워크
- 문자열 기반 JPQL의 단점을 보완 (오타, 런타임 오류 등)
Q 클래스
- QueryDSL이 작동하기 위한 기반이 되는 클래스
- Entity 기반으로 자동 생성되는 쿼리 전용 클래스
- 내부에 엔티티의 필드를 포함하고 있어, 객체처럼 접근 가능: QUser user = QUser.user;
JPAQueryFactory
- QueryDSL 쿼리를 생성하고 실행하는 핵심 클래스
- 내부적으로 EntityManager를 사용
- selectFrom(), where(), fetch() 등 메서드 제공
JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
QUser user = QUser.user;
List<User> result = queryFactory
.selectFrom(user)
.where(user.username.eq("teasun"))
.fetch();
2. 테이블 객체 방명록 설정하기 (Auditing)
Auditing
- 엔티티의 생성자/수정자, 생성일/수정일을 자동으로 기록해주는 기능
- ex: “누가 언제 만들고, 언제 수정했는가”를 자동으로 관리
Auditing 적용 방법
1. @EnableJpaAuditing 설정
- 메인 클래스에 추가
@EnableJpaAuditing(auditorAwareRef = "userAuditorAware")
@SpringBootApplication
public class Application { ... }
2. 엔티티에 Auditing 설정
- 공통 속성을 가지는 부모 엔티티에 설정
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class TimeStamp {
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime modifiedAt;
@CreatedBy
@ManyToOne
private User createdBy;
@LastModifiedBy
@ManyToOne
private User modifiedBy;
}
3. AuditorAware 구현
- 인증된 사용자를 반환하는 로직 구현
- @CreatedBy, @LastModifiedBy는 AuditorAware 구현이 반드시 필요함
- @CreatedDate, @LastModifiedDate는 자동으로 동작함
@Service
public class UserAuditorAware implements AuditorAware<User> {
@Override
public Optional<User> getCurrentAuditor() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth == null || !auth.isAuthenticated()) {
return Optional.empty();
}
return Optional.of(((UserDetailsImpl) auth.getPrincipal()).getUser());
}
}
4. SecurityContextHolder에 인증 정보 넣기 (예: JwtFilter)
public void setAuthentication(String username) {
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication auth = jwtUtil.createAuthentication(username);
context.setAuthentication(auth);
SecurityContextHolder.setContext(context);
}
전체 흐름 요약
- 사용자 로그인 후 → SecurityContextHolder에 인증 정보 저장
- 엔티티 저장 시 → AuditorAware가 현재 사용자 반환
- @CreatedBy, @LastModifiedBy에 사용자 정보 자동 저장
- @CreatedDate, @LastModifiedDate는 자동 시간 기록
3. 필요한 부분만 갱신하기 (Dynamic Insert/Update)
@DynamicInsert
- 정의: INSERT 시 null 값인 필드를 쿼리에서 제외함
- 사용 위치: 엔티티 클래스에 @DynamicInsert 어노테이션 추가
- 효과: 기본값이 DB에 설정된 컬럼에 null이 덮어씌워지는 것을 방지
- 쿼리 최적화: 불필요한 칼럼 제외로 SQL 간결화 및 성능 향상
@DynamicInsert
@Entity
public class User { ... }
@DynamicUpdate
- 정의: UPDATE 시 변경된 필드만 쿼리로 생성
- 사용 위치: 엔티티 클래스에 @DynamicUpdate 어노테이션 추가
- 효과: 변경되지 않은 필드에 대한 불필요한 업데이트를 방지
- 쿼리 최적화: 업데이트 대상 컬럼이 적을수록 효과 증가
@DynamicUpdate
@Entity
public class User { ... }
* 두 어노테이션 모두 Hibernate 전용 기능이며, 필드 수가 많을수록 성능 차이가 커진다. 특히 DB 기본값을 활용하거나 변경 감지 기반 최적화가 중요한 경우 유용하다.
👏 👏 👏 JPA 심화 강의 완강 👏 👏 👏
'Spring > 강의' 카테고리의 다른 글
[📕 JPA 심화] 4. SpringData JPA 기본 (1) | 2025.06.26 |
---|---|
[📕 JPA 심화] 3. RawJPA 기본 (1) | 2025.06.26 |
[📕 JPA 심화] 2. 데이터베이스 다루기 (2) | 2025.06.26 |
[📕 JPA 심화] 1. 프로젝트 세팅 (0) | 2025.06.26 |
[📘 심화 Spring] 3-4. N+1 문제 (0) | 2025.06.09 |