본문 바로가기
코딩일기/날씨앱 만들기 프로젝트

[Spring Boot] properties 를 통해서 키 값 숨기기

by 욱파이어니어 2021. 10. 24.
728x90
반응형

우리가 프로젝트를 진행하다보면 API key와 같은 민감 정보들을 사용할때가 있다.

그런 민감 정보들을 소스에다가 적어두고 깃허브에 올리거나 타인에게 공유를 하게 되면

민감 정보들이 유출될수가 있다.

 

 

그래서 민감 정보들을 숨기기 위해서 우리가 사용할 파일을 spring boot 안에 있는 application.properties 파일에

민감정보들을 입력해 해당 파일에서 값을 가져오는 것이다.

 

일단 그러기 위해서는 일단 properties 파일을 만들자.

 

resource/application-API-KEY.properties

shortweather-key=키값을 넣으면 된다.

 

그리고 application.properties 파일에서 내가 만든 파일을 include하게 한다.

 

 

resource/application.properties

#My Key will be placed in here
spring.profiles.include=API-KEY

 

자 그럼 이제 application-API-KEY.properties에 있는 값들을 소스에서 불러와 보자.

 

application-API-KEY.properties에 저장되어 있는 값들을 받아오기 위해서 사용할수 있는 방법은 2가지이다.

 

1. @Value 어노테이션 사용해서 값 주입받기

2.  Environment API를 주입받아서 사용하기.

 

각각의 방법을 자세히 살펴보자.

 

1. @Value 어노테이션 사용해서 값 주입받기

 

이 방법은 간단하다 일단은 @Value를 통해서 값을 주입 받을 Class를 생성한다.

나는 아래와 같은 방식으로 만들었다.

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class ApiKey {
	@Value("${shortweather-key}")
	private String apiKey;

	public String getApiKey() {
		return apiKey;
	}

	@Override
	public String toString() {
		return "ApiKey [apiKey=" + apiKey + "]";
	}
	
}

@Value("${properties파일에 적은 키값}") 이렇게 적어주고 그 밑에 변수명을 적어주면 된다.

 

그리고 이제 해당 Class를 @Component를 통해서 bean을 등록해주고

해당 bean을 주입받아서 사용 하면 된다.

나는 @Autowired 대신 생성자 주입을 통해서 값을 주입받았다.

 

public class Application implements CommandLineRunner{

	private final static String BASE_URL = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0";
	private final ApiKey API_KEY;
	
	
	public Application(ApiKey apiKey) {
		this.API_KEY = apiKey;
	}
 }

이렇게 주입을 받고 이제 생성한 API_KEY를 사용해서 값을 가져왔다.

    @Override
    public void run( String... args ) throws Exception {
        
        String serviceKey = API_KEY.getApiKey();
        String pageNo = "1";
        String numOfRows = "12";
        String dataType = "JSON";
        String base_date = "20211020";
        String base_time = "2300";
        String nx = "55";
        String ny = "127";

        DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(BASE_URL); //UriBuilder를 생성하는 옵션을 설정하는 DefaultUriBuilderFactory 인스턴스 생성
        factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); //encoding 모드 설정

        WebClient wc = WebClient.builder().uriBuilderFactory(factory).baseUrl(BASE_URL).build();

        String response = wc.get()
                .uri(uriBuilder -> uriBuilder.path("/getVilageFcst")
                        .queryParam("serviceKey", serviceKey)
                        .queryParam("numOfRows", numOfRows)
                        .queryParam("pageNo", pageNo)
                        .queryParam("dataType", dataType)
                        .queryParam("base_date", base_date)
                        .queryParam("base_time", base_time)
                        .queryParam("nx", nx)
                        .queryParam("ny", ny).build())
                .retrieve().bodyToMono(String.class).block();

        System.out.println(response);
        System.out.println(API_KEY.getApiKey());
        
    }

 

main 메소드 안에서 처리하지 않고 따로 run()를 생성한 이유는 main 메소드는 static 메소드여서

non-static 변수인 @Autowired 한 ApiKey 인스턴스를 사용할수 없었기 때문이다.

 

그리고 내가 @Autowired 한 인스턴스를 사용하려면 bean 등록 과정이 있어야 하는데

생성한 bean을 바로 static 메소드인 main() 사용하게 되면 bean이 등록되어 있지 않은 bean이라고 뜬다.

(실제로 그렇게 떳음)

 

따라서 내가 생성한 bean을 사용하기 위해서는 스프링 초기화 작업이 이루어지고 난후에 사용해야 한다.

그래서 main() 에 bean을 사용하지 않고 따로 CommandLineRunner 를 implements 하여서 

그 안에 run() 을 @Override 한것이다.

 

그래서 해당 API_KEY를 가져온 방법의 전체 소스는 아래와 같다.

 

@SpringBootApplication
public class Application implements CommandLineRunner{

	private final static String BASE_URL = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0";
	private final ApiKey API_KEY;
	
	
	public Application(ApiKey apiKey) {
		this.API_KEY = apiKey;
	}
	
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
	
    @Override
    public void run( String... args ) throws Exception {
        
        String serviceKey = API_KEY.getApiKey();
        String pageNo = "1";
        String numOfRows = "12";
        String dataType = "JSON";
        String base_date = "20211020";
        String base_time = "2300";
        String nx = "55";
        String ny = "127";

        DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(BASE_URL); //UriBuilder를 생성하는 옵션을 설정하는 DefaultUriBuilderFactory 인스턴스 생성
        factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); //encoding 모드 설정

        WebClient wc = WebClient.builder().uriBuilderFactory(factory).baseUrl(BASE_URL).build();

        String response = wc.get()
                .uri(uriBuilder -> uriBuilder.path("/getVilageFcst")
                        .queryParam("serviceKey", serviceKey)
                        .queryParam("numOfRows", numOfRows)
                        .queryParam("pageNo", pageNo)
                        .queryParam("dataType", dataType)
                        .queryParam("base_date", base_date)
                        .queryParam("base_time", base_time)
                        .queryParam("nx", nx)
                        .queryParam("ny", ny).build())
                .retrieve().bodyToMono(String.class).block();

        System.out.println(response);
        System.out.println(API_KEY.getApiKey());
        
    }
    
}

 

 

 자 그럼 이제 Environment 를 의존성 주입 받아서 사용해보자.

 

 

 

 

2.  Environment API를 주입받아서 사용하기.

 

이 방법도 사실 1번과 큰 차이가 없다 1번은 따로 Class를 만든것이고 

이번건 이미 만들어져 있는 Environmet Class를 의존성 주입 받는것과 동일하다.

따라서 따로 설명을 하지는 않고 소스만 올리겠다.

 

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.DefaultUriBuilderFactory;

@SpringBootApplication
public class Application implements CommandLineRunner{

	private final static String BASE_URL = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0";
	private Environment env;
	
	
	public Application(Environment  env) {
		this.env = env;
	}
	
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
	
    @Override
    public void run( String... args ) throws Exception {
        
    	String key = "shortweather.key";
    	
        String serviceKey = env.getProperty(key);
        String pageNo = "1";
        String numOfRows = "12";
        String dataType = "JSON";
        String base_date = "20211020";
        String base_time = "2300";
        String nx = "55";
        String ny = "127";

        DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(BASE_URL); //UriBuilder를 생성하는 옵션을 설정하는 DefaultUriBuilderFactory 인스턴스 생성
        factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); //encoding 모드 설정

        WebClient wc = WebClient.builder().uriBuilderFactory(factory).baseUrl(BASE_URL).build();

        String response = wc.get()
                .uri(uriBuilder -> uriBuilder.path("/getVilageFcst")
                        .queryParam("serviceKey", serviceKey)
                        .queryParam("numOfRows", numOfRows)
                        .queryParam("pageNo", pageNo)
                        .queryParam("dataType", dataType)
                        .queryParam("base_date", base_date)
                        .queryParam("base_time", base_time)
                        .queryParam("nx", nx)
                        .queryParam("ny", ny).build())
                .retrieve().bodyToMono(String.class).block();

        System.out.println(response);
        System.out.println(env.getProperty(key));
        
    }
    
}

 

 

이것의 참조 자료는 아래 스택 오버플로우를 통해서 이다.

(제가 올린 질문입니다. 추천 눌러주심 감사합니다.)

https://stackoverflow.com/questions/69686585/spring-boot-value-annotaion-return-null/69686681?noredirect=1#comment123177026_69686681 

 

Spring Boot @Value annotaion return null

I'm trying to put api key in application.properties and get api key from it. So I put api key in application.properties. application.properties server.port=8090 #My Key will be placed in here

stackoverflow.com

 

반응형