캐시(Cache)는 데이터 접근 속도를 높이기 위해 자주 사용되는 데이터를 임시로 저장해 두는 메모리 공간을 의미. 즉, 필요한 데이터를 빠르게 가져올 수 있도록 미리 저장해 두는 저장소.
@Service
public class UserService {
@Cacheable("users")
public User getUserById(Long id) {
// 데이터베이스에서 사용자 조회
}
}
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
// 사용자 삭제 로직
}
@CachePut(value = "users", key = "#user.id")
public User updateUser(User user) {
// 사용자 업데이트 로직
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
@Service
public class ProductService {
@Cacheable("products")
public Product getProductById(Long id) {
// 데이터베이스에서 제품 조회
}
}
@Service
public class ArticleService {
@Autowired
private ArticleRepository articleRepository;
@Cacheable(value = "articles", key = "#id")
public Article getArticleById(Long id) {
simulateSlowService(); // 데이터베이스 조회 시뮬레이션
return articleRepository.findById(id).orElse(null);
}
private void simulateSlowService() {
try {
Thread.sleep(3000L); // 3초 지연
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
취업 준비 중인 신입 Java/Spring 백엔드 개발자 분께서 캐시(Cache)를 실습하면서 이해도를 높일 수 있는 다양한 실습 과제를 소개해드리겠습니다. 이 실습 과제들은 캐시의 기본 개념부터 실제 프로젝트에 적용하는 방법까지 단계별로 학습할 수 있도록 구성되었습니다.
@Cacheable 사용하기Spring의 @Cacheable 어노테이션을 사용하여 메서드 결과를 캐싱해보고, 캐시의 동작을 이해합니다.
Spring Boot 프로젝트 생성
Spring Web, Spring Boot Starter Cache, Spring Boot DevTools.캐시 설정 활성화
@SpringBootApplication
@EnableCaching
public class CacheDemoApplication {
public static void main(String[] args) {
SpringApplication.run(CacheDemoApplication.class, args);
}
}
간단한 서비스 생성
@Service
public class UserService {
@Cacheable("users")
public String getUserById(Long id) {
simulateSlowService();
return "User" + id;
}
private void simulateSlowService() {
try {
Thread.sleep(3000L); // 3초 지연
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
컨트롤러 생성
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public String getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
}
테스트
/users/1 엔드포인트를 호출합니다.@Cacheable의 기본 동작 이해@CacheEvict와 @CachePut 어노테이션을 사용하여 캐시를 삭제하고 업데이트하는 방법을 학습합니다.
UserService 수정
@Service
public class UserService {
@Cacheable("users")
public String getUserById(Long id) {
simulateSlowService();
return "User" + id;
}
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
// 사용자 삭제 로직 (예: 데이터베이스에서 삭제)
System.out.println("User " + id + " deleted");
}
@CachePut(value = "users", key = "#id")
public String updateUser(Long id, String name) {
// 사용자 업데이트 로직 (예: 데이터베이스에서 업데이트)
return name;
}
private void simulateSlowService() {
try {
Thread.sleep(3000L); // 3초 지연
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
컨트롤러 수정
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public String getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
}
@PutMapping("/{id}")
public String updateUser(@PathVariable Long id, @RequestParam String name) {
return userService.updateUser(id, name);
}
}
테스트
/users/1을 호출하여 캐시에 저장된 값을 확인합니다./users/1을 DELETE 요청하여 캐시에서 삭제합니다./users/1을 호출하여 캐시가 삭제되었는지 확인합니다./users/1을 PUT 요청하여 캐시를 업데이트하고, 다시 GET 요청 시 업데이트된 값을 확인합니다.@CacheEvict를 사용한 캐시 삭제@CachePut을 사용한 캐시 업데이트Redis를 캐시 저장소로 사용하여 분산 캐시 환경을 구축하고 활용합니다.
Redis 설치 및 실행
docker run -d -p 6379:6379 --name redis-cache redis의존성 추가
pom.xml에 Redis 관련 의존성을 추가합니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
설정 파일 수정
application.properties에 Redis 설정을 추가합니다.
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
UserService 및 UserController는 이전과 동일하게 유지
테스트
/users/1을 호출하여 Redis에 캐시가 저장되는지 확인합니다.docker exec -it redis-cache redis-cli
> keys *
> get users::1TTL(Time To Live)과 LRU(Least Recently Used) 전략을 적용하여 캐시의 만료와 갱신을 관리합니다.
Caffeine 캐시 라이브러리 추가
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.2</version>
</dependency>
캐시 설정 클래스 작성
@Configuration
public class CacheConfig {
@Bean
public CaffeineCacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("users");
cacheManager.setCaffeine(Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(100));
return cacheManager;
}
}
UserService와 UserController는 동일하게 유지
테스트
캐시를 사용하지 않은 경우와 사용한 경우의 성능을 비교하여 캐시의 효과를 분석합니다.
UserService에 캐시 없는 메서드 추가
@Service
public class UserService {
@Cacheable("users")
public String getUserById(Long id) {
simulateSlowService();
return "User" + id;
}
public String getUserByIdNoCache(Long id) {
simulateSlowService();
return "User" + id;
}
private void simulateSlowService() {
try {
Thread.sleep(3000L); // 3초 지연
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
}
컨트롤러에 캐시 없는 엔드포인트 추가
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public String getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
@GetMapping("/nocache/{id}")
public String getUserNoCache(@PathVariable Long id) {
return userService.getUserByIdNoCache(id);
}
}
성능 테스트
/users/1과 /users/nocache/1을 각각 여러 번 호출하여 응답 시간을 비교합니다./users/1은 즉시 응답되고 /users/nocache/1은 매번 3초 지연됩니다.결과 분석
작은 규모의 실제 애플리케이션에 캐시를 적용하여 실무에서의 캐시 활용 경험을 쌓습니다.
간단한 블로그 애플리케이션 개발
게시글 조회에 캐시 적용
@Cacheable을 사용하여 자주 조회되는 게시글을 캐싱@CacheEvict와 @CachePut을 사용하여 게시글 수정 및 삭제 시 캐시를 업데이트캐시 성능 모니터링
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>application.properties에 Actuator 설정 추가management.endpoints.web.exposure.include=cache캐시 미세 조정
문서화 및 배포
위의 실습 과제를 통해 캐시의 기본 개념부터 실제 프로젝트에 적용하는 방법까지 단계별로 학습할 수 있습니다. 각 실습 과제를 진행하면서 다음과 같은 점들을 유념하세요.
이러한 실습을 통해 캐시의 중요성을 깊이 이해하고, 실제 업무에서도 효과적으로 활용할 수 있는 능력을 키우시길 바랍니다. 취업 준비에 많은 도움이 되길 바라며, 화이팅입니다!