implementation 'org.springframework.boot:spring-boot-starter-data-redis'
# application.yml
spring:
redis:
host: 127.0.0.1
port: 6379
@Configuration
@RequiredArgsConstructor
@Slf4j
public class RedisConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
log.info("host={}, port={}", host, port);
return new LettuceConnectionFactory(host, port);
}
@Bean
public RedisTemplate<String, String> redisTemplate() {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setEnableTransactionSupport(true);
return redisTemplate;
}
}
Spring boot에서 저희가 설정해주는 application.yml 설정정보는 해당 어노테이션을 통해서 묶어서 Bean으로 설정합니다.
~Properties
와 같은 이름을 가진 클래스의 대부분에 @ConfigurationProperties 어노테이션이 부착되어있는 것을 확인할 수 있습니다.그래서 개발자가 디테일하게 커스텀한다거나, 다른 정보의 bean을 여러개 생성하지 않는다면 Spring에서 application.yml 정보를 통해서 Bean으로 자동적으로 등록해줍니다.
RedisProperties 클래스 일부
@Value 어노테이션에서 RedisProperties 활용해서 세팅 수정해보겠습니다.
@Configuration
@RequiredArgsConstructor
@Slf4j
public class RedisConfig {
private final RedisProperties redisProperties;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
log.info("host={}, port={}", redisProperties.getHost(), redisProperties.getPort() );
return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
}
@Bean
public RedisTemplate<String, String> redisTemplate() {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setEnableTransactionSupport(true);
return redisTemplate;
}
}
자동으로 RedisProperties를 만들어주기 때문에 RedisProperties만 생성자 주입을 통해서 RedisConfig를 Bean으로 등록이 가능해집니다.
Spring Data Jdbc, Spring Data Jpa와 같은 Spring data 프로젝트의 의존성을 활용해보신 분들이라면 application.yml 설정만을 통해서 JpaRepository, Transaction, JdbcTemplate 등을 사용해보신 경험이 있을 것입니다.
Spring에서 자동적으로 @ConfigurationProperties 어노테이션을 활용하여 Bean으로 등록해줘서 가능합니다.
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
의존성을 필요로합니다.
Spring에서 자동적으로 해당 정보를 Bean으로 등록해주지 않는다면, @EnableConfigurationProperties라는 어노테이션을 필요로합니다.
@Configuration 클래스 또는 Application 코드에 @EnableConfigurationProperties(~Properties.class)를 설정해주어야 합니다.
예시로 설명해드리면 Spring에서 Redis를 통해서 캐싱을 사용하기위해서 CacheManager를 Bean으로 등록해줘야합니다.
이 때도 동일하게 application.yml 에 아래와 같이 설정할 수 있습니다.
cache:
type: redis # cache를 레디스 활용
redis:
time-to-live: 600000 # redis cache TTL
이 때, @EnableConfigurationProperties(CacheProperties.class) 어노테이션을 부착하면 정상적으로 작동합니다.
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(CacheProperties.class)
public class CacheConfig {
private final CacheProperties cacheProperties;
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
.disableCachingNullValues()
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(RedisSerializer.json()))
.entryTtl(cacheProperties.getRedis().getTimeToLive());
return RedisCacheManager.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory)
.cacheDefaults(redisCacheConfiguration)
.build();
}
}
.yml 파일 생성하기
하나로 묶을 prefix와 key를 계층적으로 구성해서 설정합니다.
# /resource/custom/setting.yml
custom:
id: 1
user-name: aaron2 # yaml의 경우 케밥케이스와 스네이크케이스를 사용(케밥케이스를 권장)
email: cms05041@gmail.com
application.yml에 import를 설정합니다.
spring:
config:
import: custom/setting.yml
CustomProperties 클래스를 생성합니다.
@ConfigurationProperties(prefix = "custom") // prefix 설정
@RequiredArgsConstructor // 롬복 생성자
@ConstructorBinding // 생성자로 설정정보 주입
@Getter
public class CustomProperties {
private final Integer id;
private final String userName;
private final String email;
}
CustomConfig 클래스를 생성합니다.
@Configuration
@EnableConfigurationProperties(CustomProperties.class)
@PropertySource("classpath:custom/setting.yml") // 설정정보 위치 생략가능
@RequiredArgsConstructor
public class CustomConfig {
private final CustomProperties customProperties;
}
설정정보가 정상적으로 주입되고 Bean으로 생성되었는지 테스트합니다
@SpringBootTest
class customTest {
@Autowired
private CustomProperties customProperties;
@Test
void settingTest() {
assertThat(customProperties.getId()).isEqualTo(1);
assertThat(customProperties.getUserName()).isEqualTo("aaron2");
assertThat(customProperties.getEmail()).isEqualTo("cms05041@gmail.com");
}
}
.yml 설정
auth: # prefix
provider: # Map 객체 이름
github: # Map에서 key값
client-id: github_client_id
client-secret: github_client_secret
access-token-uri: http://localhost:9090/login/oauth/access_token
user-info-uri: http://localhost:9090/user,http://localhost:9090/user/emails
naver: # Map에서 key값
client-id: naver_client_id
client-secret: naver_client_secret
access-token-uri: http://localhost:9090/oauth2.0/token
user-info-uri: http://localhost:9090/v1/nid/me
AuthProperties 클래스 구현하기
@ConfigurationProperties(prefix = "auth")
public class AuthProperties {
private final Map<String, OauthProperties> provider = new HashMap<>();
public OauthProperties getOauthProperty(String key) {
return provider.get(key);
}
@ConstructorBinding
@RequiredArgsConstructor
@Getter
public static class OauthProperties {
private final String clientId;
private final String clientSecret;
private final String accessTokenUri;
private final String userInfoUri;
}
}
@Configuration
@EnableConfigurationProperties(AuthProperties.class)
@PropertySource("classpath:custom/setting.yml")
@RequiredArgsConstructor
public class OauthConfig {
private final AuthProperties authProperties;
}
설정정보 테스트해보기
@SpringBootTest
class AuthPropertiesTest {
@Autowired
private AuthProperties authProperties;
@Test
void checkSetGithubPropertiesTest() {
String key = "github";
AuthProperties.OauthProperties githubProperties = authProperties.getOauthProperty(key);
assertThat(githubProperties.getClientId()).isEqualTo("github_client_id");
assertThat(githubProperties.getClientSecret()).isEqualTo("github_client_secret");
assertThat(githubProperties.getAccessTokenUri()).isEqualTo("http://localhost:9090/login/oauth/access_token");
assertThat(githubProperties.getUserInfoUri()).isEqualTo("http://localhost:9090/user,http://localhost:9090/user/emails");
}
@Test
void checkSetNaverPropertiesTest() {
String key = "naver";
AuthProperties.OauthProperties naverProperties = authProperties.getOauthProperty(key);
assertThat(naverProperties.getClientId()).isEqualTo("naver_client_id");
assertThat(naverProperties.getClientSecret()).isEqualTo("naver_client_secret");
assertThat(naverProperties.getAccessTokenUri()).isEqualTo("http://localhost:9090/oauth2.0/token");
assertThat(naverProperties.getUserInfoUri()).isEqualTo("http://localhost:9090/v1/nid/me");
}
}