728x90
들어가면서
spring Boot 프로젝트에서 Ehcache 대신 Caffeine을 사용하면 성능을 향상시킬 수 있습니다.
Coffine이란 무엇인가?
Caffeine은 인기있는 오픈 소스 자바 캐시 라이브러리이며, Google이 개발하고 있습니다. Caffeine은 Java 8 이상을 지원하며, 최신 JVM의 기능을 활용하여 캐시 퍼포먼스를 높이고 메모리 사용을 최적화합니다.
Coffine은 Guava 캐시 라이브러리의 대체 제품입니다. Coffine은 Guava 캐시의 기능을 대부분 포함하고 있으며, 더 나은 쓰기 성능과 더 적은 메모리 사용량을 제공합니다.
어떤특징들이 있는가?
Caffeine은 다음과 같은 특징을 가지고 있습니다.
- 빠른 접근 및 응답 속도: Caffeine은 인-메모리 캐시를 사용하며, ConcurrentHashMap 및 ConcurrentLinkedHashMap과 같은 최신 자바 컬렉션을 활용하여 데이터에 대한 빠른 액세스 및 응답 속도를 제공합니다.
- 최신 JVM 최적화: Caffeine은 최신 JVM의 기능을 활용하여 캐시 퍼포먼스를 최적화합니다.
- 캐시 유효 기간 및 최대 크기 제한: Caffeine은 캐시 항목의 유효 기간 및 최대 크기 제한을 설정할 수 있습니다. 이러한 설정을 통해 메모리 사용을 최적화하고 캐시 데이터의 최신 상태를 유지할 수 있습니다.
- 스레드 안전성: Caffeine은 스레드 안전성을 보장하기 위해 synchronized 블록을 사용하지 않고 최신 자바 동시성 라이브러리를 활용합니다.
Caffeine 외 기타 library들에 대한 간단한 비교자료
라이브러리 | 기능 | 성능 | 기타 |
Ehcache | 분산 캐싱, 대규모 데이터 처리 | 높음 | Spring Boot에서 기본적으로 제공됨 |
Caffeine | 쓰기 성능이 뛰어나며, 메모리 사용량이 적음 | 매우 높음 | Guava 캐시의 대체제 |
Redis | 분산 캐싱, Pub/Sub 메시징, Set 처리 | 높음 | NoSQL 데이터베이스 |
Hazelcast | 분산 캐싱, 대규모 데이터 처리 | 높음 | 장애 복구 및 확장성이 뛰어남 |
Infinispan | 분산 캐싱, 대규모 데이터 처리 | 높음 | JBoss에서 개발됨 |
Coffine의 장점
- Guava 캐시의 대체제로서 Guava 캐시의 대부분의 기능을 포함하고 있음
- 쓰기 성능이 더 뛰어나며, 메모리 사용량이 더 적음
Coffine의 단점
- Guava 캐시와 달리, 캐시 다시 로드를 지원하지 않음
Coffine을 Spring Boot 3.0에 적용하는 코드 설정
1. Gradle 파일에 의존성 추가
dependencies {
implementation("com.github.ben-manes.caffeine:caffeine:3.0.0")
implementation("com.github.ben-manes.caffeine:caffeine-jcache:3.0.0")
}
2. Coffine 캐시 매니저 설정
@Configuration
@EnableCaching
public class CachingConfig extends CachingConfigurerSupport {
@Bean
@Override
public CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCaffeine(caffeineCacheBuilder());
return cacheManager;
}
Caffeine<Object, Object> caffeineCacheBuilder() {
return Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.maximumSize(100)
.weakKeys()
.recordStats();
}
}
Coffine을 적용한 CRUD 작성하기
1. application.yml 파일에 MySQL 정보 기재
spring:
datasource:
url: jdbc:mysql://localhost:3306/{database_name}?serverTimezone=UTC
username: {username}
password: {password}
jpa:
hibernate:
ddl-auto: create
show-sql: true
2. JPA 적용
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "email")
private String email;
// getters and setters
}
3. Coffine을 적용한 Repository 구현
@Repository
public class UserRepositoryImpl implements UserRepository {
@Autowired
private EntityManager entityManager;
@Cacheable(value = "users")
public List<User> findAll() {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> cq = cb.createQuery(User.class);
Root<User> root = cq.from(User.class);
cq.select(root);
TypedQuery<User> query = entityManager.createQuery(cq);
return query.getResultList();
}
@Cacheable(value = "users", key = "#id")
public User findById(Long id) {
return entityManager.find(User.class, id);
}
@CachePut(value = "users", key = "#user.id")
public User save(User user) {
entityManager.persist(user);
return user;
}
@CacheEvict(value = "users", key = "#id")
public void deleteById(Long id) {
User user = entityManager.find(User.class, id);
entityManager.remove(user);
}
}
JUnit6를 사용하여 테스트 코드 작성
@SpringBootTest
public class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
public void testFindAll() {
List<User> userList1 = userRepository.findAll();
List<User> userList2 = userRepository.findAll();
assertEquals(userList1, userList2);
}
@Test
public void testFindById() {
User user1 = userRepository.save(new User("John", "john@example.com"));
User user2 = userRepository.findById(user1.getId());
assertEquals(user1.getName(), user2.getName());
assertEquals(user1.getEmail(), user2.getEmail());
}
@Test
public void testSave() {
User user1 = new User("John", "john@example.com");
userRepository.save(user1);
User user2 = userRepository.findById(user1.getId());
assertEquals(user1.getName(), user2.getName());
assertEquals(user1.getEmail(), user2.getEmail());
}
@Test
public void testDeleteById() {
User user1 = userRepository.save(new User("John", "john@example.com"));
userRepository.deleteById(user1.getId());
assertNull(userRepository.findById(user1.getId()));
}
}
내저장소 바로가기 luxury515
'Springboot3.0 > 핵심기능' 카테고리의 다른 글
Spring IoC 에 관하여. (0) | 2023.04.15 |
---|---|
Spring Security 와 Siro 에 대한 비교 (0) | 2023.04.15 |
Redis를 이용한 refresh token (0) | 2023.04.11 |
Redis를 이용한 중복요청 방지 (0) | 2023.04.11 |
Springboot3.0 에서 kafka적용해보기 (0) | 2023.04.11 |