반응형
해당 글에서는 API Cache에 대해서 이해하고 REST API 환경에서 이를 적용하는 방법에 대해서 작성한 글입니다.
1) 개발환경 구성
💡 개발환경은 MyBatis를 기반으로 RDBMS로부터 전달받은 데이터를 캐시 처리하는 환경으로 구성하였습니다.
개발 환경 | 버전 |
java | 1.8 |
Spring Boot | 2.7.4 |
빌드관리도구 | Gradle 7.5 |
개발 툴 | IntelliJ IDEA 2022.3 |
spring-boot-starter-cache | 2.7.4 |
mybatis-spring-boot-starter | 2.2.2 |
[참고] 이전의 작성한 개발환경에 spring-boot-starter-cache를 추가하여 환경을 구성하였습니다.
2) API 캐싱, Spring Boot Cache 이해
💡 API Caching (캐싱)이란?
- API의 호출에 따라서 캐시를 이용하여 '서버의 부하를 줄이고 API 성능을 최적화'하여 '응답시간을 단축'시키는 역할을 수행합니다.
💡Spring Boot Starter Cache 란?
- 자주 사용되는 데이터를 ‘캐시’를 ‘메모리’에 저장하여 빠른 검색을 가능하게 하는 기능을 제공합니다.
- 해당 캐시에 저장되는 데이터를 CacheManager를 통하여 메모리뿐만 아니라 디스크, 데이터베이스, 클라우드 서비스와 같은 ‘다른 저장소’에도 저장이 가능합니다.
💡 [참고] API 캐시와 세션과 관련되어 작성한 글입니다.
1. Spring Boot Cache 사용 목적
💡 Spring Boot Cache 사용목적
- API에서 Database로부터 데이터를 조회하는 경우 ‘동일한 데이터를 반복하여 조회’ 해옴으로써 ‘불필요한 일을 반복하는 문제’가 발생합니다.
- 이에 따라서 API 캐시를 통해서 DB로부터 반복적으로 데이터를 조회해 오는 일에 대해 최초 데이터를 조회해 온 뒤 이후는 캐시에서 데이터를 조회해 오는 처리를 수행함으로써 API의 성능을 올리며 응답시간을 단축하는 효율성을 가져옵니다.
2. Spring Boot Cache 사용처
💡 Spring Boot Cache 사용처
- 해당 경우들에서 ‘자주 조회되는 데이터’에 대해서 캐시에 저장하여 성능향상을 기대할 수 있습니다. 이를 통해 외부 저장소에 대해서 부하 및 데이터베이스 등의 부하를 줄여서 서버의 성능을 개선하는데 도움이 됩니다.
- Spring Boot Cache의 사용처는 사용자의 로그인 정보(인증정보), 게시글 목록 등에 사용이 됩니다.
3) Spring Boot Cache Annotation
💡 Spring Boot Cache 라이브러리에서 사용되는 어노테이션 목록입니다.
Spring Boot Cache 어노테이션 설명
Annotation | 설명 |
@EnableCaching | Spring Boot Cache를 사용하기 위해 '캐시 활성화'를 위한 어노테이션을 의미합니다. |
@CacheConfig | 캐시정보를 '클래스 단위'로 사용하고 관리하기 위한 어노테이션을 의미합니다. |
@Cacheable | 캐시정보를 메모리 상에 ‘저장’하거나 ‘조회’ 해오는 기능을 수행하는 어노테이션입니다. |
@CachePut | 캐시 정보를 메모리상에 '저장'하며 존재 시 갱신하는 기능을 수행하는 어노테이션입니다. |
@CacheEvict | 캐시 정보를 메모리상에 '삭제'하는 기능을 수행하는 어노테이션입니다. |
@Caching | 여러 개의 ‘캐시 어노테이션’을 ‘함께 사용’할 때 사용하는 어노테이션입니다. |
주요 Annotation 비교하며 이해하기
💡 Spring Boot Cache에서는 아래의 주요한 어노테이션을 사용합니다.
어노테이션 | 주요 기능 | 캐싱 실행 시점 |
@Cacheable | 캐시 조회, 저장 기능 | - 캐시 존재 시 ‘메서드 호출 전 실행’ - 캐시 미 존재 시 ‘메서드 호출 후 실행’ |
@CachePut | 캐시 저장 기능 | - 캐시 존재 시 ‘메서드 호출 후 실행’ - 캐시 미 존재 시 ‘메서드 호출 후 실행’ |
@CacheEvict | 캐시 삭제 기능 | - beforeInvocation 속성값이 true일때 ‘메서드 호출 전 실행’ - beforeInvocation 속성값이 false일때 ‘메서드 호출 후 실행’ |
[ 더 알아보기 ]
💡 메서드의 호출 전/후 실행은 무슨 차이일까?
- 메서드의 호출 전에 실행 시 DB로부터 데이터를 처리하는 부분에 대해서 줄어들게 됩니다.
- 반대로 메서드의 호출 후에 실행하는 경우 DB로부터 데이터를 처리하여 가져오는 부분에 대해서 처리하는 부분이 늘어납니다.
💡 @CacheEvict의 beforeInvocation 속성이란?
- 캐시의 데이터를 삭제하는데 메서드 호출 전/후에 발생할지에 대해 설정하는 속성을 의미합니다.
- 속성의 기본값은 false이며 메서드 실행 전에 캐시에서 데이터를 삭제하여 예외가 발생한다면 캐시에서 데이터가 삭제되지 않습니다.
- 이에 따라 예외가 발생할 가능성이 있는 메서드에 대해서 beforeInvocation= “true”를 사용하지 않는 것이 좋습니다.
💡 @Cacheable과 @CachePut의 다른 점은?
-
@Cacheable의 경우는 ‘캐시가 존재하지 않을 경우’ 캐시를 저장하지만 @CachePut의 경우는 ‘캐시의 존재 여부를 떠나서’ 항상 저장 혹은 갱신을 수행합니다.
1. @EnableCaching
💡 @EnableCaching 이란?
- Spring Boot Cache를 사용하기 위해 '캐시 활성화'를 위해 사용됩니다.
- 해당 어노테이션의 선언 위치는 CacheManager()를 구현한 @Configuration부분에서 선언하여 사용합니다.
[참고] @EnableCaching 속성 값
속성 | 속성 기본 값 | 설명 |
value | 빈 이름 | 캐시 매니저 이름을 지정한다. |
order | Ordered.LOWEST_PRECEDENCE | 캐시 관련 빈들의 우선순위를 지정한다. |
keyGenerator | - | 캐시에서 사용할 키 생성기를 지정한다. |
cacheManager | - | 사용할 캐시 매니저를 직접 지정한다. |
cacheResolver | - | 사용할 캐시 리졸버를 직접 지정한다. |
proxyTargetClass | false | 프록시를 생성할 때 CGLIB를 사용할지, 아니면 JDK Dynamic Proxy를 사용할지 결정한다. |
[참고] CacheManager의 종류
CacheManager | 캐시 저장 위치 | 설명 |
ConcurrentMapCacheManager | 메모리 상에 캐시 저장 | ConcurrentHashMap 기반 캐시 구현체를 의미합니다. |
CaffeineCacheManager | 메모리 상에 캐시 저장 | Caffeine 기반 캐시 구현체 |
SimpleCacheManager | 메모리 상에 캐시 저장 | 단순 캐시 구현체를 의미합니다. |
EhCacheCacheManager | 디스크 또는 데이터베이스에 저장 | Ehcache 기반 캐시 구현체를 의미합니다. |
HazelcastCacheManager | 메모리 상에 캐시 저장 | Hazelcast 기반 캐시 구현체를 의미합니다. |
InfinispanCacheManager | 메모리 상에 캐시 저장 | Infinispan 기반 캐시 구현체를 의미합니다. |
RedisCacheManager | Redis 내의 데이터베이스에 저장 | Redis 기반 캐시 구현체를 의미합니다. |
CouchbaseCacheManager | Couchbase 내의 데이터베이스에 저장 | Couchbase 기반 캐시 구현체를 의미합니다. |
GemfireCacheManager | 자체 저장소에 저장 | GemFire 기반 캐시 구현체를 의미합니다. |
CoherenceCacheManager | 자체 저장소에 저장 | Oracle Coherence 기반 캐시 구현체를 의미합니다. |
[예시 설명]
- 해당 CacheConfig라는 클래스는 Config 파일입니다.
- @EnableCaching을 선언하여 Spring Boot Cache를 사용함을 선언하였고, @Bean을 이용하여서 CacheManager를 구성하였습니다.
- CacheManager에서는 ConcurrentMapCacheManager를 사용하고 “codeCache”를 메모리상에 등록하고 사용하도록 구성하였습니다.
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
log.debug("[+] CacheConfig Start !!! ");
// "codeCacheInfo"라는 캐시를 관리합니다.
return new ConcurrentMapCacheManager("codeCache");
}
}
2. @CacheConfig
💡 @CacheConfig 란?
- 캐시를 '클래스 단위'로 '사용하고 관리'하기 위해 사용됩니다.
- 이를 사용하면 ‘클래스 단위로 관리’를 하면 동일한 이름의 캐시를 반복하여 입력할 필요를 줄여줍니다.
- 해당 어노테이션의 선언 위치는 캐시를 사용하는 @Service 부분에서 선언하여 사용합니다.
[참고] @EnableCaching 속성 값
속성 | 설명 |
cacheNames | 캐시할 데이터의 이름을 지정합니다. |
cacheManager | 캐시 매니저의 이름을 지정합니다. |
cacheResolver | 캐시 리졸버의 이름을 지정합니다. |
keyGenerator | 캐시 키 생성기의 이름을 지정합니다. |
cacheManagerCustomizers | 캐시 매니저 커스터마이저의 이름을 지정합니다. |
key | 캐시할 데이터에서 사용할 키를 지정합니다. |
condition | 캐시를 적용할 조건을 지정합니다. |
unless | 캐시 적용을 제외할 조건을 지정합니다. |
sync | 캐시 동기화 여부를 지정합니다. |
beforeInvocation | 메서드 실행 전에 캐시를 적용할지 여부를 지정합니다. |
[예시 설명]
- 해당 CodeServiceImpl라는 클래스는 CodeService의 인터페이스의 구현체로 사용되는 파일입니다.
- @CacheConfig(cacheNames = "code")라는 속성으로 클래스 내부에서 “code”라는 값으로 공통적으로 사용하도록 구성하였습니다.
@Service
@CacheConfig(cacheNames = "code")
public class CodeServiceImpl implements CodeService {
...
}
3. @Cacheable
💡 @Cacheable 이란?
- 캐시 정보를 메모리 상에 '저장'하거나 '조회' 해오는 기능을 수행할 때 사용됩니다.
- 상세한 설명으로는 캐시의 속성값인 '값(value)과 키(key)'를 기반으로 수행이 됩니다.
- 최초 호출이 된 경우에는 메서드가 호출되어 '캐시 정보를 저장' 하며, 동일하게 재 호출이 된 경우에는 메서드의 호출 없이 '저장된 캐시의 정보를 조회하여 반환'합니다.
- @CachePut 어노테이션과 비슷한 기능을 수행하지만 '캐시 정보를 조회'하는데 주로 사용합니다.
- 해당 어노테이션의 선언 위치는 주로 @Service를 선언한 인터페이스의 구현체 부분에서 함께 선언하여 사용합니다.
[참고] @Cacheable 속성 값
속성 | 설명 |
value | 캐시로 사용될 이름을 지정합니다. |
key | 캐시의 key로 사용될 SpEL 표현식을 이용하여 지정합니다. |
condition | 캐시를 저장할 조건을 지정하는 SpEL 표현식을 이용하여 지정합니다. |
unless | 캐시를 저장하지 않을 조건을 지정하는 SpEL 표현식을 이용하여 지정합니다. |
cacheManager | 사용할 캐시 매니저를 지정하는데 사용될 캐시 매니저의 이름을 지정합니다. |
cacheResolver | 사용할 캐시 해결자 빈을 지정하는데 사용될 캐시 해결자 빈 이름을 지정합니다. |
[ 예시 설명 ]
- 해당 selectCodeList()의 메서드는 CodeServiceImpl라는 클래스는 CodeService의 인터페이스의 구현체로 사용되는 클래스 파일에 포함된 함수입니다.
- @Cacheable(value = "codeCacheInfo", key = "#codeDto.grpCd")를 통해서 해당 메서드의 호출을 하는 경우 codeCacheInfo의 캐시의 값에 객체로 전달받은 codeDto.grpCd 값에 따라서 해당 캐시가 저장이 됩니다.
- 동일한 값과 키값을 통해서 메서드의 호출이 발생하는 경우 메서드를 호출하지 않고 캐시에서 데이터를 가져와서 결과값을 반환해 줍니다.
@Service
public class CodeServiceImpl implements CodeService {
/**
* 코드 리스트를 조회합니다.
*
* @param codeDto CodeDto
* @return List<CodeDto>
*/
@Transactional(readOnly = true)
@Cacheable(value = "codeCacheInfo", key = "#codeDto.grpCd")
public List<CodeDto> selectCodeList(CodeDto codeDto) {
CodeMapper cm = sqlSession.getMapper(CodeMapper.class);
return cm.selectCodeList(codeDto);
}
}
4. @CachePut
💡 @CachePut 이란?
- 캐시 정보를 메모리상에 '저장'하며 존재 시 갱신하는 기능을 수행할 때 사용합니다.
- 상세한 설명으로는 캐시의 속성값인 '값(value)과 키(key)'를 기반으로 수행이 됩니다.
- 최초 호출이 된 경우에는 메서드가 호출되어 ‘캐시 정보를 저장’하며, 동일하게 재 호출이 된 경우에도 메서드가 호출되어 ‘캐시 정보를 갱신(수정 및 저장)’하여 캐시의 정보를 반환합니다.
- @Cacheable 어노테이션과 비슷한 기능을 수행하지만 '캐시 정보를 저장'하는데 주로 사용이 됩니다.
- 해당 어노테이션의 선언 위치는 주로 @Service를 선언한 인터페이스의 구현체 부분에서 함께 선언하여 사용합니다.
[참고] @CachePut 속성 값
속성 | 설명 |
value | 캐시 이름을 지정합니다. |
key | 캐시에 저장할 때 사용할 키를 지정한다. SpEL 표현식으로 작성 가능합니다 |
condition | 캐시에 저장할 조건을 지정한다. SpEL 표현식으로 작성 가능하며, 조건이 false 일 경우 캐시 저장을 하지 않습니다 |
unless | 캐시에 저장하지 않을 조건을 지정한다. condition과 반대로 동작하며, SpEL 표현식으로 작성 가능합니다 |
keyGenerator | 캐시에 사용할 키 생성기를 지정합니다 |
cacheManager | 캐시 매니저를 지정합니다. |
[ 예시 설명 ]
- 해당 selectCodeByCd()의 메서드는 CodeServiceImpl라는 클래스는 CodeService의 인터페이스의 구현체로 사용되는 클래스 파일에 포함된 함수입니다.
- @CachePut(value = "codeCacheInfo", key = "#cd")를 통해서 해당 메서드의 호출을 하는 경우 codeCacheInfo의 캐시의 값에 파라미터로 전달받은 cd 값에 따라서 해당 캐시가 저장이 됩니다.
- 동일한 값과 키를 통해서 메서드의 호출이 발생하더라도 메서드는 호출되어 해당 캐시를 갱신하여 결과값을 반환해 줍니다.
@Service
public class CodeServiceImpl implements CodeService {
/**
* 코드 키 값을 기반으로 코드 정보를 조회합니다
*
* @param cd String
* @return CodeDto
*/
@Transactional(readOnly = true)
@CachePut(value = "codeCacheInfo", key = "#cd")
public CodeDto selectCodeByCd(String cd) {
CodeMapper cm = sqlSession.getMapper(CodeMapper.class);
return cm.selectCodeByCd(cd);
}
}
5. @CacheEvict
💡 @CacheEvict 란?
- 캐시 정보를 메모리상에 '삭제'하는 기능을 수행할 때 사용합니다.
- 상세한 설명으로는 캐시는 속성값인 '값(value)과 키(key)'를 기반으로 수행이 됩니다.
- 어노테이션의 속성인 beforeInvocation의 값이 true이면 '메서드 호출 전'에 실행이 되며, false이면 '메서의 호출 후에 실행'이 됩니다.
- 해당 어노테이션의 선언 위치는 주로 @Service를 선언한 인터페이스의 구현체 부분에서 함께 선언하여 사용합니다.
[참고] @CacheEvict 속성 값
속성 | 설명 |
value | 캐시 이름을 지정합니다 |
key | 캐시에서 삭제할 키 값을 지정합니다. |
condition | 캐시 삭제 조건. SpEL 표현식 사용 가능합니다 |
allEntries | 전체 캐시 삭제 여부입니다 |
beforeInvocation | 메소드 실행 전 캐시 삭제 여부입니다 |
[ 예시 설명 ]
- 해당 deleteCode()의 메서드는 CodeServiceImpl라는 클래스는 CodeService의 인터페이스의 구현체로 사용되는 클래스 파일에 포함된 함수입니다.
- @CacheEvict(value = "codeCacheInfo", key = "#codeDto.grpCd", beforeInvocation = false)를 통해서 해당 메서드의 호출을 하는 경우 codeCacheInfo의 캐시 값과 codeDto.grpCd의 키 값에 따라서 캐시를 삭제합니다.
- beforeInvocation 속성을 false로 지정하였기에 메서드가 실행된 이후에 캐시를 삭제하도록 처리하였습니다.
@Service
public class CodeServiceImpl implements CodeService {
/**
* 코드 삭제
*
* @param codeDto CodeDto
* @return int
*/
@Transactional
@CacheEvict(value = "codeCacheInfo", key = "#codeDto.grpCd", beforeInvocation = false)
public int deleteCode(CodeDto codeDto) {
CodeMapper cm = sqlSession.getMapper(CodeMapper.class);
try {
return cm.deleteCode(codeDto);
} catch (Exception e) {
throw new BusinessExceptionHandler(e.getMessage(), ErrorCode.INSERT_ERROR);
}
}
}
6. @Caching
💡 @Caching이란?
- 여러 개의 '캐시 어노테이션을 함께 사용할 때 사용'됩니다.
- 예를 들어, @CachePut과 @CacheEvict를 함께 사용할 때 사용됩니다.
[참고] @Caching의 속성 값
속성 | 설명 |
cacheable | 캐시 정보를 조회하는데 사용하는 @Cacheable 어노테이션을 단일 혹은 다중으로 사용할 수 있도록 하는 속성입니다. |
put | 캐시 정보를 저장하는데 사용하는 @CachePut 어노테이션을 단일 혹은 다중으로 사용할 수 있도록 하는 속성입니다. |
evict | 캐시 정보를 삭제하는데 사용하는 @CacheEvict 어노테이션을 단일 혹은 다중으로 사용할 수 있도록 하는 속성입니다. |
[ 예시 설명 ]
- 해당 selectCodeList()의 메서드는 CodeServiceImpl라는 클래스는 CodeService의 인터페이스의 구현체로 사용되는 클래스 파일에 포함된 함수입니다.
- @Caching 어노테이션을 이용하여 조회를 수행하는 cacheable 속성과 수정을 수행하는 put 속성을 함께 사용하도록 구성하였습니다.
- 메서드를 호출하는 경우 조회와 생성이 함께 수행이 되도록 구성하였습니다.
/**
* 코드 리스트를 조회합니다.
*
* @param codeDto CodeDto
* @return List<CodeDto>
*/
@Transactional(readOnly = true)
@Caching(
cacheable = {
@Cacheable(value = "codeCacheInfo", key = "#codeDto.grpCd")
},
put = {
@CachePut(value = "codeCacheInfo", key = "#codeDto.grpCd"),
}
)
public List<CodeDto> selectCodeList(CodeDto codeDto) {
CodeMapper cm = sqlSession.getMapper(CodeMapper.class);
return cm.selectCodeList(codeDto);
}
3) Spring Boot Cache 설정하기
1. 라이브러리 추가합니다.
💡 build.gradle 파일 내에 ‘spring-boot-starter-cache' 라이브러리의 의존성을 추가합니다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-cache'
}
[참고] Maven Repository : spring-boot-starter-cache
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-cache
2. CacheManager 설정합니다.
💡 CacheManager 란?
- 캐시를 관리하고 캐시 된 ‘데이터를 저장’하고 ‘반환’하는 역할을 합니다.
- 일반적으로 메모리 상에 저장되는 데이터를 디스크, 데이터베이스, 클라우드 서비스와 같은 저장소에 저장이 가능하도록 합니다.
- 해당 캐시는 Redis, Ehcache, Caffeine 등 다양한 캐시 라이브러리와 연동하여 사용할 수 있습니다.
[참고] CacheManager의 종류
CacheManager | 캐시 저장 위치 | 설명 |
ConcurrentMapCacheManager | 메모리 상에 캐시 저장 | ConcurrentHashMap 기반 캐시 구현체를 의미합니다. |
CaffeineCacheManager | 메모리 상에 캐시 저장 | Caffeine 기반 캐시 구현체 |
SimpleCacheManager | 메모리 상에 캐시 저장 | 단순 캐시 구현체를 의미합니다. |
EhCacheCacheManager | 디스크 또는 데이터베이스에 저장 | Ehcache 기반 캐시 구현체를 의미합니다. |
HazelcastCacheManager | 메모리 상에 캐시 저장 | Hazelcast 기반 캐시 구현체를 의미합니다. |
InfinispanCacheManager | 메모리 상에 캐시 저장 | Infinispan 기반 캐시 구현체를 의미합니다. |
RedisCacheManager | Redis 내의 데이터베이스에 저장 | Redis 기반 캐시 구현체를 의미합니다. |
CouchbaseCacheManager | Couchbase 내의 데이터베이스에 저장 | Couchbase 기반 캐시 구현체를 의미합니다. |
GemfireCacheManager | 자체 저장소에 저장 | GemFire 기반 캐시 구현체를 의미합니다. |
CoherenceCacheManager | 자체 저장소에 저장 | Oracle Coherence 기반 캐시 구현체를 의미합니다. |
[ 더 알아보기 ]
💡 로컬 캐시(Local Cache)
- 캐시를 사용하는 한 개의 서버에서만 유효한 캐시입니다. 이는 서버의 메모리에 저장되며 서버가 재시작되거나 캐시가 만료될 때까지 유지됩니다.
💡 글로벌 캐시 (Globacl Cache)
- 여러 서버에서 공유하는 캐시입니다. 이를 위해서는 분산 캐시 기술이 필요하며 대표적인 기술로는 Redis, Memcached, Hazelcast 등이 있습니다. 글로벌 캐시를 사용하면 여러 서버에서 공유하는 캐시를 이용하여 성능을 향상할 수 있습니다.
💡 해당 예시에서는 @EnableCaching을 통해서 Spring Boot Cache를 사용함을 선언하였고 CacheManager인 ConcurrentMapCacheManager를 통해서 캐시를 관리합니다.
💡@EnableCaching 란?
- 캐시를 사용하기 위해 필요한 어노테이션으로 Spring Boot 애플리케이션에서 캐싱을 활성화하는 데 사용되며 @Configuration이 포함된 클래스에서 이를 적용합니다.
package com.adjh.multiflexapi.config;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 'ConcurrentMapCacheManager'를 통해서 캐시를 관리합니다.
*
* @author : lee
* @fileName : CacheConfig
* @since : 2023/03/28
*/
// 해당 Annotation을 추가합니다.
@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("codeCacheInfo");
}
}
[참고] CacheManager의 등록된 캐시가 아닐 경우 수행하면 어떻게 될까? 아래와 같이 CacheManager에는 “codeCacheInfo”라는 캐시만 관리하게 저장한 상태고 code 캐시를 사용함을 지정하였습니다
/**
* 코드 키 값을 기반으로 코드 정보를 조회합니다
*
* @param cd String
* @return CodeDto
*/
@Cacheable(value = "code", key = "#cd")
public CodeDto selectCodeByCd(String cd) {
CodeMapper cm = sqlSession.getMapper(CodeMapper.class);
return cm.selectCodeByCd(cd);
}
💡 아래와 같이 오류가 발생함으로 정확한 캐시를 CacheManager에서 관리할 수 있습니다.
[참고] Sprng Boot Reference
https://www.baeldung.com/spring-cache-tutorial
💡 해당 이론을 이해하셨다면 아래의 글을 참고하시면 실제 사용 예시를 확인해 보실 수 있습니다.
오늘도 감사합니다. 😀
반응형
'Java > Spring Boot' 카테고리의 다른 글
[Java] Spring Boot Batch 이해하고 설정하기 -1 : 정의 및 이해 (0) | 2023.04.22 |
---|---|
[Java] Spring Boot Cache 이해하고 설정하기 -2 : 사용 및 활용 예시 (0) | 2023.04.16 |
[Java] Spring Boot AOP(Aspect-Oriented Programming) 이해하고 설정하기 (2) | 2023.03.01 |
[Java] Spring Boot Tomcat Access Log 이해하고 설정하기 (0) | 2023.02.26 |
[Java] Spring Boot Security 이해하기 -4: JWT 환경 설정 및 구성 하기 (4) | 2023.01.01 |