반응형
개발 환경
개발 환경 | 버전 |
java | 17 |
Spring Boot | 3.4.4 |
build | Gradle |
IDE | IntelliJ IDEA 2022.3 |
DB | H2 |
ORM | JPA |
Cache Annotation
🗂️ @Cacheable
- 목적: 메서드 실행 결과를 캐시에 저장하고, 다음 호출 시 캐시된 결과를 반환합니다.
- 작동 방식:
- 지정된 캐시에 해당 키가 존재하면 메서드를 실행하지 않고 캐시된 값 반환
- 캐시에 값이 없으면 메서드 실행 후 결과를 캐시에 저장
- 주로 사용되는 상황: 자주 조회되지만 자주 변경되지 않는 데이터
@Cacheable(value = "userCache", key = "#userId")
public User getUser(String userId) {
// select user
}
🔄 @CachePut
- 목적: 메서드를 실행하고 항상 결과를 캐시에 저장합니다.
- 차이점: @Cacheable은 캐시가 있으면 메서드를 실행하지 않지만, @CachePut은 무조건 실행 후 결과를 저장합니다.
- 주로 사용되는 상황: 데이터 수정 혹은 갱신 시, 캐시를 최신 상태로 유지하고 싶을 때
@CachePut(value = "userCache", key = "#user.userId")
public User updateUser(User user) {
// update user
}
🗑️ @CacheEvict
- 목적: 캐시에 저장된 데이터를 삭제합니다.
- 옵션:
- key: 특정 키만 삭제
- allEntries = true: 해당 캐시에 저장된 모든 데이터 삭제
- 주로 사용되는 상황: 데이터 삭제 시 캐시도 함께 제거해야 할 때
@CacheEvict(value = "userCache", key = "#userId")
public void deleteUser(String userId) {
// delete user
}
@CacheEvict(value = "userCache", allEntries = true)
public void reset() {
// delete all user
}
⚙️ @CacheConfig
- 목적: 클래스 단위로 공통 캐시 설정을 적용할 수 있습니다.
- 설정 예시: cacheNames, keyGenerator, cacheManager 등
- 효율성: 각 메서드에 반복적으로 설정하는 것을 줄일 수 있음
@CacheConfig(cacheNames = "userCache")
public class UserService {
@Cacheable(key = "#userId")
public User getUser(Long userId) {
// ...
}
}
📦 @Caching
- 목적: 하나의 메서드에 여러 개의 캐시 관련 어노테이션을 함께 사용할 수 있도록 해줍니다.
- 사용 예시: @Cacheable, @CachePut, @CacheEvict 등을 복합적으로 사용해야 할 경우
@Caching(
evict = {
@CacheEvict(value = "userCache", key = "#user.id"),
@CacheEvict(value = "orderCache", key = "#user.id")
}
)
public void deleteUser(User user) {
// ...
}
Cache 사용 설정
😊 Dependency 추가
implementation 'org.springframework.boot:spring-boot-starter-cache'
😊 @EnableCaching 추가
SpringBootApplication에 아래와 같이 @EnableCaching 추가
@EnableCaching
@SpringBootApplication
public class CacheApplication {
public static void main(String[] args) {
SpringApplication.run(CacheApplication.class, args);
}
}
Code
📄 Entity
@Entity
@Getter
@Setter
@Table(name = "t_user")
public class User {
@Id
private String userId;
private String name;
private int age;
}
📄 Controller
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/users")
public class UserController {
public final UserService service;
@GetMapping("/{id}")
public Optional<User> getUser(@PathVariable String id) {
return service.getUser(id);
}
@PostMapping
public User insertUser(@RequestBody User user) {
return service.insertUser(user);
}
@PutMapping
public User updateUser(@RequestBody User user) {
return service.updateUser(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable String id) {
service.deleteUser(id);
}
}
📄 Service
@Service
@RequiredArgsConstructor
@Slf4j
@CacheConfig(cacheNames = "userCache")
public class UserService {
private final UserRepository repository;
@Cacheable(key = "#userId")
public User getUser(String userId) {
log.info("DB 조회: {}", userId);
return repository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("사용자가 존재하지 않습니다."));
}
@CachePut(key = "#user.userId")
public User insertUser(User user) {
if (repository.existsById(user.getUserId())) {
throw new IllegalArgumentException("이미 존재하는 사용자입니다.");
}
return repository.save(user);
}
@CachePut(key = "#user.userId")
public User updateUser(User user) {
if (!repository.existsById(user.getUserId())) {
throw new IllegalArgumentException("사용자가 존재하지 않습니다.");
}
return repository.save(user);
}
@CacheEvict(key = "#userId")
public void deleteUser(String userId) {
repository.deleteById(userId);
}
@CacheEvict(allEntries = true)
public void resetCache() {
log.info("Cache reset");
}
}
Test
intellij에서 아래와 같이 테스트 진행
🚀 generated-requests.http
# 사용자 생성
POST http://localhost:8080/api/users
Content-Type: application/json
{
"userId": "u001",
"name": "홍길동",
"age": 25
}
###
# 사용자 조회 - DB 조회되지 않아야 함
GET http://localhost:8080/api/users/u001
###
# 사용자 수정
PUT http://localhost:8080/api/users
Content-Type: application/json
{
"userId": "u001",
"name": "임꺽정",
"age": 22
}
###
# 사용자 다시 조회 - DB 조회되지 않아야 함
GET http://localhost:8080/api/users/u001
###
# 사용자 삭제
DELETE http://localhost:8080/api/users/u001
###
# 사용자 조회 - DB 조회되어야 함
GET http://localhost:8080/api/users/u001
###
# 초기화
# GET http://localhost:8080/api/users/reset
📋 API 실행 결과
📋 Console
728x90
반응형
'back end > java' 카테고리의 다른 글
Hibernate 성능 튜닝 Tips (0) | 2025.03.10 |
---|---|
[JUNIT] Spring Test MockMvc의 한글 깨짐 처리 (0) | 2025.03.10 |
Spring Data JPA에서 Insert 전에 select query를 하는 이유 (0) | 2024.02.02 |
[java] 문자열 자르기 함수 split 함수 사용 시 주의 사항. 문자열 자르는 방법 (0) | 2024.01.17 |
[JAVA] Google Authenticator(OTP)를 이용한 two factor 개발 방법 (0) | 2024.01.16 |