HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
[New] 타일러팀
[New] 타일러팀
/
🎾
김수미
/SpringBoot 강의노트/
DAY4 : Property, Profile

DAY4 : Property, Profile

Created
Apr 7, 2022 02:28 AM
Tags
📎
Environment
  • ApplicationContext는 EnvirionmentCapable이란 클래스를 extends 함으로써, Environment 라는 기능을 제공한다.
  • Environment란? Spring Application이 처한 다양한 환경, 즉 개발 환경, 테스트 환경, 운영 환경 등 의미
    • DataBase 또는 mockServer 등의 변경이 빈번하게 일어나는 환경 변화 중 하나이다.
  • Spring의 환경은 프로파일과 프로퍼티로 제공된다.
    • 프로파일에 따라 환경이 바뀌고, 그에 따라 프로퍼티가 바뀐다.
    • 즉, 환경에 따라 프로파일과 프로퍼티 소스가 다르게 설정된 Environment 오브젝트가 사용된다.
 
📎
Property
  • Application을 개발하다 보면 DB/SFTP 접속정보, 서버포트 정보 등 다양한 정보를 Application 속성 즉 Property로 정의하고 설정하게 된다.
  • 이러한 Property 정보는 변동이 잦거나, 보안상의 이슈가 발생할 수 있는 경우가 많기 때문에 외부에 저장해두고 이를 Application이 읽어올 수 있도록 관리하는 경우가 많다.
  • Property 소스 : Property 파일, JVM 시스템 Property, OS 환경변수, Property객체 등
  • Spring Environment 객체의 역할 : 속성을 직접 정의하거나 다양한 속성 정보를 외부 Property 소스로부터가져오는 인터페이스 제공
  • Environment 객체를 이용해 직접 속성을 정의하고, 그 속성을 불러오는 코드를 작성해보자 (실습)

  • Spring 프로젝트를 생성하면 application.properties 라는 파일이 자동으로 생성되는데, 이는 SpringBoot에서 디폴트로 사용하는 property 파일이다.
  • Property 파일은 주로 key:value 형식으로 작성한다.
  • Spring에서 이미 정의해둔 Property를 사용할수도 있고, 직접 Property를 정의해도 된다.
version = v1.0.0 kdt.version = v1.0.0 kdt.support-vendors = a, b, c, d, e, f, g kdt.minimum-order-amount = 1
→ application.properties
@PropertySource("application.properties")
var environment = applicationContext.getEnvironment(); var version = environment.gerProperty("kdt.version"); var minimumOrderAmount = environment.getProperty("kdt.minimum-order-amount",Integer.class); var supportVendors = environment.gerProperty("kdt.support-vendors",List.class);
→ getProperty의 두번째 인자로 Class type을 넣어주면, 해당 type 대로 객체를 호출해준다.
@Value("v1.1.1") private String version;
→ 이런식으로 @Value Annotation을 이용해 Property 값을 참조 할수도 있다.
@Value("${kdt.version}") private String version; @Value("${JAVA_HOME}") // JVM 환경변수 private String javaHome;
→ ${keyName} 을 이용해 key 값으로 Property value를 찾을 수도 있다.
@Value("${kdt.version:v0.0.0}") private String version;
→ ${keyName}에서 keyName 뒤에 :~ 를 붙이면, keyName에 해당하는 값을 찾지 못한 경우 ~ 의 값을 default로 사용한다는 의미가 된다.
그래서 property는 그냥 상수처럼 미리 작성해두고 가져다가 사용하는 개념인가?
 
📎
YAML Property
  • YAML : "YAML은 마크업 언어가 아니다 (YAML Ain't Markup Language)” 라는 재귀적인 문장의 약어
  • 원래 뜻은 “또 다른 마크업 언어 (Yet Another Markup Language)”였으나, YAML의 핵심은 문서 마크업이 아닌 데이터 중심에 있다는 것을 보여주기 위해 변경되었다.
  • 오늘날 XML과 JSON이 데이터 직렬화에 주로 쓰이기 시작하면서, 많은 사람들이 YAML을 '가벼운 마크업 언어'로 사용하려 하고 있다.
  • 특히 Spring 에서는 Property 작성에 YAML을 사용할 수 있다.
    • YAML 문법
      ⚡️ 목표 YAML 문법에 대해 전반적으로 알아봅니다. 이미 익숙하더라도 한 번 더 체크해보세요! 쿠버네티스 실습에서 중요한 건 아키텍처, 그다음이 YAML입니다. 앞으로 YAML파일을 수십 개 만들 겁니다 😵 "블로그를 만들 건데, APP서버는 3개 띄워주시고 DB서버는 1대, 도메인은 blog.subicura.com으로 연결해주세요"를 쿠버네티스에 요청하려면 1. 어떤 오브젝트를 사용할지 정하고 2. 상세 설정을 YAML형식 으로 정의해야 합니다.
      YAML 문법
      https://subicura.com/k8s/prepare/yaml.html#%EA%B8%B0%EB%B3%B8%EB%AC%B8%EB%B2%95
      YAML 문법
kdt: version: "v1.0" minimum-order-amout: 1 support-vendors: - a - b - c - d # multiline 표현 방법 # 아래처럼 '-' 를 붙이면 마지막에 줄바꿈 미포함 description: |- line 1 hello world line 2 xxxx line 3
→ (application.yaml).property 에서 key=value 형식을 사용했다면, YAML 에선 key:value 형식을 사용
@PropertySource(value = "application.yaml" , factory = YamlPropertiesFactory.class) // 이게 있어야 @ConfigurationProperties를 쓸 수 있다 @EnableConfigurationProperties
  • SpringFramework의 @PropertySource는 YAML을 지원하지 않기 때문에, Property Source Factory를 구현해서 사용해야 한다.
    • SpringBoot는 YAML을 지원하지만 SpringFramework는 지원하지 않는다.
public class YamlPropertiesFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String s, EncodedResource encodedResource encodedResource) throws IOException { var yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean(); yamlPropertiesFactoryBean.setResources(encodedResource.getResource()); var properties = yamlPropertiesFactoryBean.getObject(); return new PropertiesPropertySource (encodedResource.getResource.getFilename(), properties); } }
@Configuration @ConfigurationProperties(prefix = "kdt) // 위 Annotation을 사용하면 @ Value Annotation을 사용하지 않아도 된다. public class OrderProperties implements InitializingBean { private String version; private int minimumOrderAmount; private List<String> supportVendors' private String description; }
 
📎
Spring Profile
  • Profile이란? 특정한 특징이나 공통점을 찾아서 그룹지어 놓은 것을 의미
    • 애플리케이션 설정 일부를 분리하여 특정 환경에서만 사용 가능하게 해 준다.
  • Spring에서는 설정이나 Bean 같은 것을 그룹화하여 하나의 프로파일로 정의하고, 정의된 여러개의 프로파일 중 하나를 선택하여 어플리케이션을 구동시킬 수 있다.
  • DB 접속 정보를 staging이라는 프로파일로 만들어 둘 수도 있고, 운영/로컬 환경별로 profile을 생성해 둔 다음(로컬 환경변수들의 모음 등을) 개발 환경이 바뀔 때 마다 필요한 프로파일을 어플리케이션에 지정하여 환경 설정을 편리하게 할 수도 있다.
    • Profile을 이용하면 여러 Bean 정의들이 특정 Profile에서만 동작하게 할 수도 있고, 특정 Property 들을 특정 Profile로 정의해서 해당 Profile이 액티브 상태일때 적용되게 할 수도 있다.
강의 코드에서 사용된 Qualifier란 무엇인가? : Profile 지정자
@Profile("local") @Profile("dev")
→ Profile 사용을 위해선 Qualifier Annotation 대신 Profile Annotation을 사용해 주어야 한다.
var environment = application.getEnvironment(); environment.setActiveProfiles("dev"); // 기존 설정(default Profile이 읽히던)을 바꿨으므로 refresh 해 주었다 applicationContext.refresh();
# local 환경에서만 작동하는 property spring.config.activate.on-profile: local kdt: version: "v1.0.0" --- # 이걸 사용하면 하나의 yaml 파일에 여러개의 작동하는 yaml을 작성할 수 있다. # dev 환경에서만 작동하는 property spring.config.activate.on-profile: dev kdt: version: "v1.0.1"
  • SpringBoot 환경에서는 아래와 같이 Profile을 사용할 수 있다.
var springApplication = new SpringApplication(KdtApplication.class); springApplication.setAdditionalProfiles("local"); vat applicationContextspringApplication.run(args); var applicationContext = SpringApplication.run(LdtApplication.class, args);
→ run 할 때 Profile을 받아서 사용하는 방식
  • 혹은 IntelliJ의 SpringBoot Application Launcher에서 Profile을 설정해 줄 수도 있다.
    • 우측 상단에서 확인가능 (Run/Debug Configurations)
  • yaml 파일을 여러개로 나누어 작성한 다음 파일 이름에서 name을 지정해 줄 수도 있다.
    • application.yaml (default)
    • application-dev.yaml
    • application-local.yaml
@Profile({"default", "local"})
 
📎
Resource
  • 스프링 애플리케이션을 만들다 보면 외부 리스소를 읽어야 하는 경우가 있다.
    • 외부 리소스 이미지파일, 텍스트파일, 암/복호화를 위한 키파일 등
    • 이런 리소스 파일들은 파일 시스템, classpath, url을 통한 웹에서 다운로드 받는 식으로 가져올 수 있다.
    • 리소스 파일을 어디서 받아오는지에 따라 원래는 다른 방식을 사용해야 하지만, 스프링은 Resource와 ResourceLoader 인터페이스를 통해 통합된 하나의 API 를 제공한다.
  • 스프링 공식 문서를 보면 다양한 구현체를 볼 수 있다.
Core Technologies
There are pros and cons for considering validation as business logic, and Spring offers a design for validation (and data binding) that does not exclude either one of them. Specifically, validation should not be tied to the web tier and should be easy to localize, and it should be possible to plug in any available validator.
Core Technologies
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#resources-implementations
  • 코드를 통해 스프링에서 어떻게 Resource 를 받아올 수 있는지 살펴보자.
var resource = applicationContext.getResource("application.yaml"); var file = resource.getFile(); var strings = Files.readAllLines(file.toPath()); // 문자열 리스트로 반환됨
Syste.out.println(strings.stream().reduce("", (a, b) -> a + "\n" + b));
→ 이렇게 해주면 위에서 받은 문자열 리스트를 한줄에 하나씩 개행하면 출력해줄 수 있다.
var resource1 = applicationContext.getResource("classpath:application.yaml"); var resource2 = applicationContext.getResource("file:test/sample.txt");
→ 이렇게 Resource 주소 앞에 scheme을 지정해줄 수 있다. (default = classPathContextResource)
var resource3 = applicationContext.getResource("https://stackoverflow.com/"); var readableByteChannel = Channels.newChannel(resouce3.getURL().openStream()); var bufferReader = new BufferReader(Channels.newReader(readableByteChannel, StandardCharsets UTF_8)); // 웹에서 받아온 Resource의 HTML Body를 출력할 수 있다 var contents = bufferReader.lines().collect(Cokkectors.joining("\n")); Ststem.out.println(contents);
→ 웹에서 Urlresource 를 가져오는 code / getFile 대신 getURL을 사용해야 한다.