해당 글에서는 Spring Boot Configuration Processor를 활용하여서 외부 설정 소스 파일(yaml/yml, properties)을 불러오는 다양한 방법에 대해 알아봅니다
1) spring-boot-configuration-processor
💡 spring-boot-configuration-processor
- Spring Boot 애플리케이션의 외부화된 구성 및 속성 파일에 정의된 속성에 대해 쉽게 접근하여 값을 가져오는 기능을 제공하는 라이브러리입니다.
- 해당 라이브러리에서 @ConfigurationProperties 어노테이션을 통해서 적용된 클래스(class), 레코드(record)를 분석하여 메타데이터를 생성합니다.
1. 주요 특징
특징 | 설명 |
타입 안전성 | 컴파일 시점에서 타입 오류를 감지하여 런타임 에러를 방지합니다. 설정 값의 타입이 명확히 정의되어 있어 잘못된 타입 사용을 미리 방지할 수 있습니다. |
유연성 | 다양한 형식(YAML/YML, Properties 등)의 설정 파일을 지원하며, 필요에 따라 동적으로 설정을 변경할 수 있습니다. |
계층 구조 | 복잡한 설정을 계층적으로 구성할 수 있어 관련 설정을 그룹화하고 구조화하여 관리할 수 있습니다. 이는 설정의 가독성과 유지보수성을 향상시킵니다. |
검증 | @Validated 어노테이션을 통해 설정 값의 유효성을 검사할 수 있습니다. 이를 통해 잘못된 설정 값이 애플리케이션에 주입되는 것을 방지할 수 있습니다. |
자동 완성 기능 | IDE에서 설정 파일 작성 시 자동 완성 기능을 제공합니다. 이는 개발자의 생산성을 높이고 설정 오류를 줄이는 데 도움을 줍니다. |
2. configuration-processor에서의 메타데이터(Meta Data)
💡 configuration-processor에서의 메타데이터(Meta Data)
- configuration-processor에서는 @ConfigurationProperties(클래스)를 통해서 클래스, 레코드를 분석하여 메타데이터를 자동으로 생성합니다.
- 이는 외부 설정 소스(yaml/yml, properties 파일 등)를 통해서 클래스의 멤버 변수와 매핑이 되어서 값이 설정이 됩니다.
Configuration Metadata :: Spring Boot
Spring Boot jars include metadata files that provide details of all supported configuration properties. The files are designed to let IDE developers offer contextual help and “code completion” as users are working with application.properties or applica
docs.spring.io
💡 아래와 같은 oauth2.yml 파일이 있습니다.
spring:
security:
oauth2:
client:
# OAuth2 인증 제공자에 대한 설정 정보를 포함합니다.
provider:
kakao:
authorization-uri: https://kauth.kakao.com/oauth/authorize
💡 configuration-processor 설정을 통해 위에 yml 파일과 OAuth2ClientProperties 클래스가 매핑이 되며, 멤버 변수로 각각의 값이 매핑이 됩니다.
@ConfigurationProperties(prefix = "spring.security.oauth2.client")
public record OAuth2ClientProperties(ProviderProperties provider) {
public record ProviderProperties(ProviderConfig kakao) {
public record ProviderConfig(String authorizationUri) {
}
}
}
3. 메타데이터와 클래스-속성 파일 매핑의 관계
💡 메타데이터와 클래스-속성 파일 매핑의 관계
- 메타데이터는 클래스와 속성 파일 간의 "브리지" 역할을 하며, 매핑 과정의 정확성과 효율성을 크게 향상합니다.
1. 메타데이터 생성
- spring-boot-configuration-processor는 @ConfigurationProperties 어노테이션이 적용된 클래스를 분석하여 메타데이터를 자동으로 생성합니다.
2. 매핑 정보 제공
- 생성된 메타데이터는 클래스의 구조, 속성 이름, 타입 등의 정보를 포함하여 Spring Boot가 속성 파일과 클래스를 정확히 매핑할 수 있도록 돕습니다.
3. IDE 지원
- 메타데이터는 IDE에서 자동완성, 문서화, 유효성 검사 등의 기능을 제공하여 개발자가 속성 파일을 더 쉽고 정확하게 작성할 수 있게 합니다.
4. 런타임 바인딩
- Spring Boot는 이 메타데이터를 사용하여 런타임에 속성 파일의 값을 클래스의 필드에 정확하게 바인딩합니다.
Generating Your Own Metadata by Using the Annotation Processor :: Spring Boot
Spring Boot’s configuration file handling is quite flexible, and it is often the case that properties may exist that are not bound to a @ConfigurationProperties bean. You may also need to tune some attributes of an existing key. To support such cases and
docs.spring.io
4. spring-boot-configuration-processor 주요 어노테이션
주요 어노테이션 | 설명 |
@ConfigurationProperties | 외부 설정 파일의 속성을 자바 객체에 바인딩하는데 사용됩니다. 특정 접두사를 가진 속성들을 하나의 클래스에 매핑할 수 있습니다. |
@EnableConfigurationProperties | @ConfigurationProperties가 적용된 클래스를 활성화하고 빈으로 등록합니다. 주로 메인 애플리케이션 클래스나 설정 클래스에서 사용됩니다. |
@ConfigurationPropertiesScan | 지정된 패키지 내의 모든 @ConfigurationProperties 클래스를 스캔하고 빈으로 등록합니다. |
@ConstructorBinding | 생성자를 통한 바인딩을 활성화합니다. 불변 객체를 만들 때 유용하며, 모든 프로퍼티를 final로 선언할 수 있습니다. |
@DefaultValue | 프로퍼티의 기본값을 지정합니다. 설정 파일에 해당 프로퍼티가 없을 경우 이 값이 사용됩니다. |
@NestedConfigurationProperty | 중첩된 객체를 별도의 설정 클래스로 분리할 때 사용합니다. 복잡한 구조의 설정을 관리하는데 유용합니다. |
@Validated | 설정 클래스에 대한 유효성 검사를 활성화합니다. |
Generating Your Own Metadata by Using the Annotation Processor :: Spring Boot
Spring Boot’s configuration file handling is quite flexible, and it is often the case that properties may exist that are not bound to a @ConfigurationProperties bean. You may also need to tune some attributes of an existing key. To support such cases and
docs.spring.io
2) spring-boot-configuration-processor 초기 설정 및 기존 데이터 확인
1. 의존성 라이브러리 추가
dependencies {
implementation "org.springframework.boot:spring-boot-configuration-processor" // Spring Boot Configuration Processor
}
Maven Repository: org.springframework.boot » spring-boot-configuration-processor
2. 불러 올 데이터 확인 : application.properties(yml)
💡불러 올 데이터 확인 : application.properties(yml)
- yml 파일 형태로 구성이 되어 있으며 Spring Boot OAuth 2.0 기반의 카카오, 네이버 로그인에 대한 설정 정보입니다.
spring:
security:
oauth2:
client:
# OAuth2 인증 제공자에 대한 설정 정보를 포함합니다.
provider:
kakao:
authorization-uri: <https://kauth.kakao.com/oauth/authorize>
token-uri: <https://kauth.kakao.com/oauth/token>
user-info-uri: <https://kapi.kakao.com/v2/user/me>
user-name-attribute: id
naver:
authorization-uri: <https://nid.naver.com/oauth2.0/authorize>
token-uri: <https://nid.naver.com/oauth2.0/token>
user-info-uri: <https://openapi.naver.com/v1/nid/me>
user-name-attribute: id
# 클라이언트 애플리케이션(Spring Boot)에 대한 설정을 포함합니다.
registration:
kakao:
client-id: xx
client-secret: xx
redirect-uri:
authorization-grant-type: authorization_code
client-authentication-method: POST
client-name: kakao
scope:
- name
- profile_nickname
- account_email
naver:
client-id: xx
client-secret: xx
redirect-uri:
authorization-grant-type: authorization_code
client-authentication-method: client_secret_post
client-name: naver
scope:
- nickname
- email
- profile_image
3. 조회 방법 확인 : @value
💡조회 방법 확인 : @value
- 기존의 @Value 어노테이션을 통해 properties 파일을 가져왔습니다. 이는 타입의 안정성도 보장이 되지 않고, 값을 찾는데 복잡하다는 문제점이 있었습니다.
- 이를 해결하기 위한 방법으로 properties 파일을 spring-boot-configuration-processor를 활용하여서 객체 형태로 구성합니다.
어노테이션 | 설명 |
@Value | Spring Framework에서 제공하는 어노테이션으로, 외부 설정 파일(properties, YAML 등)의 값을 Spring 빈의 필드나 메서드 파라미터에 주입하는 데 사용됩니다. 주로 단일 값을 주입할 때 사용되며, 표현식을 통해 복잡한 값도 주입할 수 있습니다. |
@Value("${spring.security.oauth2.client.provider.kakao.token-uri}")
private String KAKAO_TOKEN_URL = "";
@Value("${spring.security.oauth2.client.provider.kakao.user-info-uri}")
private String KAKAO_USER_INFO_URL = "";
@Value("${spring.security.oauth2.client.provider.kakao.user-name-attribute}")
private String KAKAO_USER_NAME_ATTRIBUTE = "";
@Value("${spring.security.oauth2.client.registration.kakao.client-id}")
private String KAKAO_CLIENT_ID = "";
@Value("${spring.security.oauth2.client.registration.kakao.client-secret}")
private String KAKAO_CLIENT_SECRET = "";
@Value("${spring.security.oauth2.client.registration.kakao.redirect-uri}")
private String KAKAO_REDIRECT_URL = "";
@Value("${spring.security.oauth2.client.provider.naver.token-uri}")
private String NAVER_TOKEN_URL = "";
@Value("${spring.security.oauth2.client.provider.naver.user-info-uri}")
private String NAVER_USER_INFO_URL = "";
@Value("${spring.security.oauth2.client.provider.naver.user-name-attribute}")
private String NAVER_USER_NAME_ATTRIBUTE = "";
@Value("${spring.security.oauth2.client.registration.naver.client-id}")
private String NAVER_CLIENT_ID = "";
@Value("${spring.security.oauth2.client.registration.naver.client-secret}")
private String NAVER_CLIENT_SECRET = "";
@Value("${spring.security.oauth2.client.registration.naver.redirect-uri}")
private String NAVER_REDIRECT_URL = "";
3) spring-boot-configuration-processor 활용하기 : 생성자(Getter) 이용 방법
💡 spring-boot-configuration-processor 활용하기 : 생성자(Getter) 이용 방법
- 이 방식은 생성자를 통해 설정 값을 주입받는 방식입니다. 이는 불변성을 보장하며, 모든 필드가 final로 선언될 수 있습니다.
- 생성자를 통해 모든 필드가 초기화되므로, 누락된 설정 값을 쉽게 발견할 수 있습니다. 테스트하기 쉽고, 스프링의 생성자 주입 방식과 일관성이 있습니다.
1. OAuth2ClientProperties
💡OAuth2ClientProperties
- 아래와 같은 구성을 통해서 application.properties 또는 application.yml 파일의 설정을 타입 안전하게 자바 객체로 매핑할 수 있습니다. 이를 통해 설정 값에 쉽게 접근하고 관리할 수 있습니다.
- @ConfigurationProperties 어노테이션을 통해 'spring.security.oauth2.client' 접두사로 시작하는 설정을 매핑합니다.
- 구성은 크게 ProviderProperties와 RegistrationProperties 두 개의 내부 클래스로 구성되어 있습니다.
- 각 내부 클래스는 카카오와 네이버에 대한 설정을 포함합니다.
- ProviderConfig 클래스는 인증 제공자의 URI 정보를 포함합니다.
- RegistrationConfig 클래스는 클라이언트 ID, 비밀키, 리다이렉트 URI 등의 클라이언트 등록 정보를 포함합니다.
어노테이션 | 설명 |
@ConfigurationProperties | 외부 설정 파일의 속성을 자바 객체에 바인딩하는데 사용됩니다. 특정 접두사를 가진 속성들을 하나의 클래스에 매핑할 수 있습니다. |
package com.adjh.springbootoauth2.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Getter
@Setter
@ConfigurationProperties(prefix = "spring.security.oauth2.client")
public class OAuth2ClientProperties {
private Map<String, Provider> provider = new HashMap<>();
private Map<String, Registration> registration = new HashMap<>();
@Getter
@Setter
public static class Provider {
private String authorizationUri;
private String tokenUri;
private String userInfoUri;
private String userNameAttribute;
}
@Getter
@Setter
public static class Registration {
private String clientId;
private String clientSecret;
private String redirectUri;
private String authorizationGrantType;
private String clientAuthenticationMethod;
private String clientName;
private List<String> scope;
}
}
2. SpringBoot3SecurityOauth2Application
💡 SpringBoot3SecurityOauth2Application
- Main Class 내에서 구성한 properties 파일을 스캔합니다. 이는 단건 클래스로 조회 및 등록을 하거나 혹은 패키지 경로에 따라 여러 클래스를 조회 및 등록하는 방법이 있습니다.
- @EnableConfigurationProperties(OAuth2ClientProperties.class)의 경우는 OAuth2ClientProperties 클래스 내에서 구성한 Properties 파일을 매핑합니다.
- 그리고 @ConfigurationPropertiesScan("com.adjh.springbootoauth2.config.properties") 경우에는 “com.adjh.springbootoauth2.config.properties” 패키지 내의 properties를 매핑한 파일들을 모두 스캔합니다.
어노테이션 | 설명 |
@EnableConfigurationProperties | @ConfigurationProperties가 적용된 클래스를 활성화하고 빈으로 등록합니다. 주로 메인 애플리케이션 클래스나 설정 클래스에서 사용됩니다. |
@ConfigurationPropertiesScan | 지정된 패키지 내의 모든 @ConfigurationProperties 클래스를 스캔하고 빈으로 등록합니다. |
package com.adjh.springbootoauth2;
import com.adjh.springbootoauth2.config.properties.OAuth2ClientProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
// 단건 클래스로 조회 및 등록
@EnableConfigurationProperties(OAuth2ClientProperties.class)
// or
// 패키지 경로에 따라 여러 클래스 조회 및 등록
@ConfigurationPropertiesScan("com.adjh.springbootoauth2.config.properties")
public class SpringBoot3SecurityOauth2Application {
public static void main(String[] args) {
SpringApplication.run(SpringBoot3SecurityOauth2Application.class, args);
}
}
3. Properties 파일 호출
💡Properties 파일 호출
- 아래와 같이 프로퍼티의 값을 객체 내애서 불러와서 클래스 내에서 사용이 됩니다. 해당 방식에서는 특히 이전에 @Getter를 통해서 .get() 메서드를 통해 데이터를 호출해 옵니다.
- 또한, init() 메서드에 @PostConstruct 어노테이션이 붙어있어, 빈 생성 후 자동으로 실행되며, OAuth2ClientProperties 객체로부터 각 설정 값을 가져와 필드에 할당합니다.
@Slf4j
@Service("OAuth2ServiceImpl")
public class OAuth2ServiceImpl implements OAuth2Service {
private final RestTemplateConfig restTemplateConfig;
private OAuth2ClientProperties oAuth2ClientProperties;
public OAuth2ServiceImpl(RestTemplateConfig restTemplateConfig, OAuth2ClientProperties oAuth2ClientProperties) {
this.restTemplateConfig = restTemplateConfig;
this.oAuth2ClientProperties = oAuth2ClientProperties;
}
private String KAKAO_TOKEN_URL;
private String KAKAO_USER_INFO_URL;
private String KAKAO_USER_NAME_ATTRIBUTE;
private String KAKAO_CLIENT_ID;
private String KAKAO_CLIENT_SECRET;
private String KAKAO_REDIRECT_URL;
private String NAVER_TOKEN_URL;
private String NAVER_USER_INFO_URL;
private String NAVER_USER_NAME_ATTRIBUTE;
private String NAVER_CLIENT_ID;
private String NAVER_CLIENT_SECRET;
private String NAVER_REDIRECT_URL;
@PostConstruct
public void init() {
KAKAO_TOKEN_URL = oAuth2ClientProperties.getProvider().getKakao().getTokenUri();
KAKAO_USER_INFO_URL = oAuth2ClientProperties.getProvider().getKakao().getUserInfoUri();
KAKAO_USER_NAME_ATTRIBUTE = oAuth2ClientProperties.getProvider().getKakao().getUserNameAttribute();
KAKAO_CLIENT_ID = oAuth2ClientProperties.getRegistration().getKakao().getClientId();
KAKAO_CLIENT_SECRET = oAuth2ClientProperties.getRegistration().getKakao().getClientSecret();
KAKAO_REDIRECT_URL = oAuth2ClientProperties.getRegistration().getKakao().getRedirectUri();
NAVER_TOKEN_URL = oAuth2ClientProperties.getProvider().getNaver().getTokenUri();
NAVER_USER_INFO_URL = oAuth2ClientProperties.getProvider().getNaver().getUserInfoUri();
NAVER_USER_NAME_ATTRIBUTE = oAuth2ClientProperties.getProvider().getNaver().getUserNameAttribute();
NAVER_CLIENT_ID = oAuth2ClientProperties.getRegistration().getNaver().getClientId();
NAVER_CLIENT_SECRET = oAuth2ClientProperties.getRegistration().getNaver().getClientSecret();
NAVER_REDIRECT_URL = oAuth2ClientProperties.getRegistration().getNaver().getRedirectUri();
}
@Override
public LoginKakaoReqDto kakaoLogin(LoginKakaoReqDto loginKakaoReqDto) {
log.debug("KAKAO_TOKEN_URL: {}", KAKAO_TOKEN_URL);
log.debug("KAKAO_USER_INFO_URL: {}", KAKAO_USER_INFO_URL);
log.debug("KAKAO_USER_NAME_ATTRIBUTE: {}", KAKAO_USER_NAME_ATTRIBUTE);
log.debug("KAKAO_CLIENT_ID: {}", KAKAO_CLIENT_ID);
log.debug("KAKAO_CLIENT_SECRET: {}", KAKAO_CLIENT_SECRET);
log.debug("KAKAO_REDIRECT_URL: {}", KAKAO_REDIRECT_URL);
log.debug("NAVER_TOKEN_URL: {}", NAVER_TOKEN_URL);
log.debug("NAVER_USER_INFO_URL: {}", NAVER_USER_INFO_URL);
log.debug("NAVER_USER_NAME_ATTRIBUTE: {}", NAVER_USER_NAME_ATTRIBUTE);
log.debug("NAVER_CLIENT_ID: {}", NAVER_CLIENT_ID);
log.debug("NAVER_CLIENT_SECRET: {}", NAVER_CLIENT_SECRET);
log.debug("NAVER_REDIRECT_URL: {}", NAVER_REDIRECT_URL);
}
}
4. 결과 확인
💡 결과 확인
- 위와 같이 구성한 결과를 아래와 같이 출력하였습니다.

4) spring-boot-configuration-processor 활용하기 : 레코드 타입
💡 spring-boot-configuration-processor 활용하기 : 레코드 타입
- Java 14 버전에 추가된 레코드 타입을 사용하여 설정 값을 매핑하는 방식입니다.
- 이는 생성자 타입보다 간결한 코드로 설정 값을 정의하고 접근할 수 있습니다.@Getter 어노테이션을 통한 메서드 대신에 필드 이름을 직접 메서드처럼 호출을 한다는 장점이 있습니다.
Guide to @ConfigurationProperties in Spring Boot | Baeldung
1. OAuth2ClientProperties
💡 OAuth2ClientProperties
- @ConfigurationProperties 어노테이션을 사용하여 'spring.security.oauth2.client' 접두사로 시작하는 설정을 매핑합니다.
- 레코드(record) 타입을 사용하여 불변성을 보장하고 간결한 코드를 작성했습니다.
- OAuth2ClientProperties 클래스는 ProviderProperties와 RegistrationProperties 두 개의 내부 레코드로 구성됩니다.
- ProviderProperties는 카카오와 네이버의 인증 제공자 설정을 포함합니다.
- RegistrationProperties는 카카오와 네이버의 클라이언트 등록 정보를 포함합니다.
- 각 설정에는 인증 URI, 토큰 URI, 사용자 정보 URI, 클라이언트 ID, 비밀키, 리다이렉트 URI 등의 정보가 포함됩니다.
어노테이션 | 설명 |
@ConfigurationProperties | 외부 설정 파일의 속성을 자바 객체에 바인딩하는데 사용됩니다. 특정 접두사를 가진 속성들을 하나의 클래스에 매핑할 수 있습니다. |
package com.adjh.springbootoauth2.config.properties;
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
@ConfigurationProperties(prefix = "spring.security.oauth2.client")
public record OAuth2ClientProperties(ProviderProperties provider, RegistrationProperties registration) {
public record ProviderProperties(ProviderConfig kakao, ProviderConfig naver) {
public record ProviderConfig(String authorizationUri, String tokenUri, String userInfoUri, String userNameAttribute) {
}
}
public record RegistrationProperties(RegistrationConfig kakao, RegistrationConfig naver) {
public record RegistrationConfig(String clientId, String clientSecret, String redirectUri, String authorizationGrantType, String clientAuthenticationMethod,
String clientName, List<String> scope) {
}
}
}
2. SpringBoot3SecurityOauth2Application
💡 SpringBoot3SecurityOauth2Application
- Main Class에 @EnableConfigurationProperties을 통해서 Properties 클래스를 등록해 줍니다. 이는 Spring 애플리케이션 내에 컨텍스트를 등록하기 위해 수행합니다.
어노테이션 | 설명 |
@EnableConfigurationProperties | @ConfigurationProperties가 적용된 클래스를 활성화하고 빈으로 등록합니다. 주로 메인 애플리케이션 클래스나 설정 클래스에서 사용됩니다. |
@ConfigurationPropertiesScan | 지정된 패키지 내의 모든 @ConfigurationProperties 클래스를 스캔하고 빈으로 등록합니다. |
package com.adjh.springbootoauth2;
import com.adjh.springbootoauth2.config.properties.OAuth2ClientProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
// 단건 클래스로 조회 및 등록
@EnableConfigurationProperties(OAuth2ClientProperties.class)
// or
// 패키지 경로에 따라 여러 클래스 조회 및 등록
@ConfigurationPropertiesScan("com.adjh.springbootoauth2.config.properties")
public class SpringBoot3SecurityOauth2Application {
public static void main(String[] args) {
SpringApplication.run(SpringBoot3SecurityOauth2Application.class, args);
}
}
3. Properties 파일 호출
💡 Properties 파일 호출
- 아래와 같이 프로퍼티의 값을 객체 내애서 불러와서 클래스 내에서 사용이 됩니다. 해당 방식에서는 특히 생성자 @Getter를 통한 .get() 메서드가 아닌 속성값을 통해 데이터를 호출해 옵니다.
- 또한, init() 메서드에 @PostConstruct 어노테이션이 붙어있어, 빈 생성 후 자동으로 실행되며, OAuth2ClientProperties 객체로부터 각 설정 값을 가져와 필드에 할당합니다.
@Slf4j
@Service("OAuth2ServiceImpl")
public class OAuth2ServiceImpl implements OAuth2Service {
private final RestTemplateConfig restTemplateConfig;
private OAuth2ClientProperties oAuth2ClientProperties;
public OAuth2ServiceImpl(RestTemplateConfig restTemplateConfig, OAuth2ClientProperties oAuth2ClientProperties) {
this.restTemplateConfig = restTemplateConfig;
this.oAuth2ClientProperties = oAuth2ClientProperties;
}
private String KAKAO_TOKEN_URL;
private String KAKAO_USER_INFO_URL;
private String KAKAO_USER_NAME_ATTRIBUTE;
private String KAKAO_CLIENT_ID;
private String KAKAO_CLIENT_SECRET;
private String KAKAO_REDIRECT_URL;
private String NAVER_TOKEN_URL;
private String NAVER_USER_INFO_URL;
private String NAVER_USER_NAME_ATTRIBUTE;
private String NAVER_CLIENT_ID;
private String NAVER_CLIENT_SECRET;
private String NAVER_REDIRECT_URL;
@PostConstruct
public void init() {
KAKAO_TOKEN_URL = oAuth2ClientProperties.provider().kakao().tokenUri();
KAKAO_USER_INFO_URL = oAuth2ClientProperties.provider().kakao().userInfoUri();
KAKAO_USER_NAME_ATTRIBUTE = oAuth2ClientProperties.provider().kakao().userNameAttribute();
KAKAO_CLIENT_ID = oAuth2ClientProperties.registration().kakao().clientId();
KAKAO_CLIENT_SECRET = oAuth2ClientProperties.registration().kakao().clientSecret();
KAKAO_REDIRECT_URL = oAuth2ClientProperties.registration().kakao().redirectUri();
NAVER_TOKEN_URL = oAuth2ClientProperties.provider().naver().tokenUri();
NAVER_USER_INFO_URL = oAuth2ClientProperties.provider().naver().userInfoUri();
NAVER_USER_NAME_ATTRIBUTE = oAuth2ClientProperties.provider().naver().userNameAttribute();
NAVER_CLIENT_ID = oAuth2ClientProperties.registration().naver().clientId();
NAVER_CLIENT_SECRET = oAuth2ClientProperties.registration().naver().clientSecret();
NAVER_REDIRECT_URL = oAuth2ClientProperties.registration().naver().redirectUri();
}
@Override
public LoginKakaoReqDto kakaoLogin(LoginKakaoReqDto loginKakaoReqDto) {
log.debug("KAKAO_TOKEN_URL: {}", KAKAO_TOKEN_URL);
log.debug("KAKAO_USER_INFO_URL: {}", KAKAO_USER_INFO_URL);
log.debug("KAKAO_USER_NAME_ATTRIBUTE: {}", KAKAO_USER_NAME_ATTRIBUTE);
log.debug("KAKAO_CLIENT_ID: {}", KAKAO_CLIENT_ID);
log.debug("KAKAO_CLIENT_SECRET: {}", KAKAO_CLIENT_SECRET);
log.debug("KAKAO_REDIRECT_URL: {}", KAKAO_REDIRECT_URL);
log.debug("NAVER_TOKEN_URL: {}", NAVER_TOKEN_URL);
log.debug("NAVER_USER_INFO_URL: {}", NAVER_USER_INFO_URL);
log.debug("NAVER_USER_NAME_ATTRIBUTE: {}", NAVER_USER_NAME_ATTRIBUTE);
log.debug("NAVER_CLIENT_ID: {}", NAVER_CLIENT_ID);
log.debug("NAVER_CLIENT_SECRET: {}", NAVER_CLIENT_SECRET);
log.debug("NAVER_REDIRECT_URL: {}", NAVER_REDIRECT_URL);
}
}
4. 결과 확인
💡 결과 확인
- 위와 같이 구성한 결과를 아래와 같이 출력하였습니다.

5) spring-boot-configuration-processor 활용하기 : 속성 분리
💡 spring-boot-configuration-processor 활용하기 : 속성 분리
- 호출부가 길어진다는 점이 있기에 좀 더 가시적으로 Properties 파일을 두 개로 분리하였습니다.
1. Provider 별 분리
💡 Provider 별 분리
- OAuth 2.0에서 kakao, naver가 동일한 형태의 값을 가지고 있기에 상위에 대해서 호출하고 kakao, naver 형태로 분리하는 형태로 구성하였습니다.
package com.adjh.springbootoauth2.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Getter
@Setter
@ConfigurationProperties(prefix = "spring.security.oauth2.client.provider")
public class OAuth2ProviderProperties {
private ProviderConfig kakao;
private ProviderConfig naver;
@Setter
@Getter
public static class ProviderConfig {
private String authorizationUri;
private String tokenUri;
private String userInfoUri;
private String userNameAttribute;
}
}
💡 Record 타입으로 구성
- 위와 동일하지만 다른 방식으로 .get() 형태를 사용하지 않고 가시적인 호출을 위해 Record 타입으로 구성하였습니다.
package com.adjh.springbootoauth2.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "spring.security.oauth2.client.provider")
public record OAuth2ProviderProperties(ProviderConfig kakao, ProviderConfig naver) {
public record ProviderConfig(
String authorizationUri,
String tokenUri,
String userInfoUri,
String userNameAttribute
) {
}
}
2. Registration 별 분리
💡 Registration 별 분리
- OAuth 2.0에서 kakao, naver가 동일한 형태의 값을 가지고 있기에 상위에 대해서 호출하고 kakao, naver 형태로 분리하는 형태로 구성하였습니다.
package com.adjh.springbootoauth2.config.properties;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
@Getter
@Setter
@ConfigurationProperties(prefix = "spring.security.oauth2.client.registration")
public class OAuth2RegistrationProperties {
private RegistrationConfig kakao;
private RegistrationConfig naver;
@Setter
@Getter
public static class RegistrationConfig {
private String clientId;
private String clientSecret;
private String redirectUri;
private String authorizationGrantType;
private String clientAuthenticationMethod;
private String clientName;
private List<String> scope;
}
}
💡 Record 타입으로 구성
- 위와 동일하지만 다른 방식으로 .get() 형태를 사용하지 않고 가시적인 호출을 위해 Record 타입으로 구성하였습니다.
package com.adjh.springbootoauth2.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;
@ConfigurationProperties(prefix = "spring.security.oauth2.client.registration")
public record OAuth2RegistrationProperties(
RegistrationConfig kakao,
RegistrationConfig naver
) {
public record RegistrationConfig(
String clientId,
String clientSecret,
String redirectUri,
String authorizationGrantType,
String clientAuthenticationMethod,
String clientName,
List<String> scope
) {
}
}
3. Properties 파일 호출
💡Properties 파일 호출
- 아래와 같이 프로퍼티의 값을 객체 내에서 불러와서 클래스/레코드 내에서 사용이 됩니다. 해당 방식에서는 좀 더가시적으로 구성이 되었습니다.
3.1. 일반 클래스로 구성한 형태에서 호출
💡 일반 클래스로 구성한 형태에서 호출
- 구성한 클래스를 호출하여 각각의 값을 가져옵니다.
@Slf4j
@Service("OAuth2ServiceImpl")
public class OAuth2ServiceImpl implements OAuth2Service {
private final RestTemplateConfig restTemplateConfig;
private final OAuth2ClientProperties oAuth2ClientProperties;
private final OAuth2ProviderProperties oAuthProvider;
private final OAuth2RegistrationProperties oAuthRegistration;
public OAuth2ServiceImpl(RestTemplateConfig restTemplateConfig, OAuth2ClientProperties properties, OAuth2ProviderProperties oAuthProvider, OAuth2RegistrationProperties oAuthRegistration) {
this.restTemplateConfig = restTemplateConfig;
this.oAuth2ClientProperties = properties;
this.oAuthProvider = oAuthProvider;
this.oAuthRegistration = oAuthRegistration;
}
@Override
public LoginKakaoReqDto kakaoLogin(LoginKakaoReqDto loginKakaoReqDto) {
log.debug("KAKAO_TOKEN_URL: {}", oAuthProvider.getKakao().getTokenUri());
log.debug("KAKAO_USER_INFO_URL: {}", oAuthProvider.getKakao().getUserInfoUri());
log.debug("KAKAO_USER_NAME_ATTRIBUTE: {}", oAuthProvider.getKakao().getUserNameAttribute());
log.debug("KAKAO_CLIENT_ID: {}", oAuthRegistration.getKakao().getClientId());
log.debug("KAKAO_CLIENT_SECRET: {}", oAuthRegistration.getKakao().getClientSecret());
log.debug("KAKAO_REDIRECT_URL: {}", oAuthRegistration.getKakao().getRedirectUri());
log.debug("NAVER_TOKEN_URL: {}", oAuthProvider.getNaver().getTokenUri());
log.debug("NAVER_USER_INFO_URL: {}", oAuthProvider.getNaver().getUserInfoUri());
log.debug("NAVER_USER_NAME_ATTRIBUTE: {}", oAuthProvider.getNaver().getUserNameAttribute());
log.debug("NAVER_CLIENT_ID: {}", oAuthRegistration.getNaver().getClientId());
log.debug("NAVER_CLIENT_SECRET: {}", oAuthRegistration.getNaver().getClientSecret());
log.debug("NAVER_REDIRECT_URL: {}", oAuthRegistration.getNaver().getRedirectUri());
}
}
3.2. 레코드로 구성한 형태에서 호출
💡 레코드로 구성한 형태에서 호출
- get() 형태가 아닌 형태로 호출하기에 좀 더 명확하게 메서드를 이해하여 호출할 수 있습니다.
@Slf4j
@Service("OAuth2ServiceImpl")
public class OAuth2ServiceImpl implements OAuth2Service {
private final RestTemplateConfig restTemplateConfig;
private final OAuth2ClientProperties oAuth2ClientProperties;
private final OAuth2ProviderProperties oAuthProvider;
private final OAuth2RegistrationProperties oAuthRegistration;
public OAuth2ServiceImpl(RestTemplateConfig restTemplateConfig, OAuth2ClientProperties properties, OAuth2ProviderProperties oAuthProvider, OAuth2RegistrationProperties oAuthRegistration) {
this.restTemplateConfig = restTemplateConfig;
this.oAuth2ClientProperties = properties;
this.oAuthProvider = oAuthProvider;
this.oAuthRegistration = oAuthRegistration;
}
@Override
public LoginKakaoReqDto kakaoLogin(LoginKakaoReqDto loginKakaoReqDto) {
log.debug("KAKAO_TOKEN_URL: {}", oAuthProvider.kakao().tokenUri());
log.debug("KAKAO_USER_INFO_URL: {}", oAuthProvider.kakao().userInfoUri());
log.debug("KAKAO_USER_NAME_ATTRIBUTE: {}", oAuthProvider.kakao().userNameAttribute());
log.debug("KAKAO_CLIENT_ID: {}", oAuthRegistration.kakao().clientId());
log.debug("KAKAO_CLIENT_SECRET: {}", oAuthRegistration.kakao().clientSecret());
log.debug("KAKAO_REDIRECT_URL: {}", oAuthRegistration.kakao().redirectUri());
log.debug("NAVER_TOKEN_URL: {}", oAuthProvider.naver().tokenUri());
log.debug("NAVER_USER_INFO_URL: {}", oAuthProvider.naver().userInfoUri());
log.debug("NAVER_USER_NAME_ATTRIBUTE: {}", oAuthProvider.naver().userNameAttribute());
log.debug("NAVER_CLIENT_ID: {}", oAuthRegistration.naver().clientId());
log.debug("NAVER_CLIENT_SECRET: {}", oAuthRegistration.naver().clientSecret());
log.debug("NAVER_REDIRECT_URL: {}", oAuthRegistration.naver().redirectUri());
}
}
4. 결과 확인
💡 결과 확인
- 위와 같이 구성한 결과를 아래와 같이 출력하였습니다

오늘도 감사합니다😀
'Java > Spring Boot' 카테고리의 다른 글
[Java] Spring Boot 환경에서 CORS(Cross Origin Resource Sharing) 이해하고 활용하기 -1 (1) | 2024.10.26 |
---|---|
[Java] Spring Boot WebSocket + STOMP 이해하고 구성하기 -1: 초기 구성 및 간단 소켓 연결 (1) | 2024.09.28 |
[Java] Spring Boot Async 비동기 처리 이해하기 -2 : Executor (0) | 2024.08.15 |
[Java] Spring Boot Async 비동기 처리 이해하기 -1 : 주요 어노테이션 및 비동기 반환 유형 (0) | 2024.08.03 |
[Java] Spring Boot Data Redis 환경 구성 및 활용하기 -1 : 환경 구성 및 데이터 조작 방법 (12) | 2024.03.30 |