AuthEntity 기반 DB 조회/수정/삭제 담당 // 토큰 검증 시 동시성 방지용
// SELECT로 읽은 row를 지금 트랜잭션이 끝날 때까지
// 다른 트랜잭션이 수정/삭제/잠금 못 하게 막는 역할
// → Refresh 토큰 탈취 동시 재사용 방지
@Lock(LockModeType.PESSIMISTIC_WRITE)
Optional<AuthEntity> findByTokenHashAndRevokedAtIsNull(String tokenHash);
// 특정 유저의 토큰 조회
Optional<AuthEntity> findByUser(UserEntity user);
// 아직 revoke 되지 않은 활성 토큰만 조회
Optional<AuthEntity> findByUserAndRevokedAtIsNull(UserEntity user);
설명:
findByTokenHashAndRevokedAtIsNull
findByUserAndRevokedAtIsNull
// 한 사람당 리프래시 토큰 1개 정책
// @Modifying: UPDATE / DELETE 실행 시 필수
// JPQL UPDATE는 영속성 컨텍스트를 우회하고 DB를 직접 수정함
// → 실행 후 영속성 컨텍스트와 DB 상태가 달라질 수 있음
@Modifying
@Query("""
update AuthEntity a
set a.revokedAt = :now
where a.user = :user
and a.revokedAt is null
""")
int revokeAllActiveByUser(@Param("user") UserEntity user,
@Param("now") LocalDateTime now);
설명:
@Modifying 필수