Search
Duplicate

마이크로 서비스

수업
Spring MSA
주제
5 more properties
080283
gilbutITbook

마이크로서비스 아키텍쳐

n계층
n계층 애플리케이션에서는 관심사가 잘 분리되어 있어 UI, 데이터, 비즈니스 로직 같은 영역을 따로 고려할 수 있다.
팀이 N-계층 애플리케이션의 여러 컴포넌트에서 독립적으로 작업하기 쉽다.
널리 알려진 엔터프라이즈 아키텍쳐이므로 숙련된 N-계층 프로젝트 개발자를 찾기 쉽다.
변경을 적용하려면 전체 애플리케이션 중지 재시작
메시지가 상하 전체 계층에 통행
대규모 계층에서는 리팩터링 어려움
대표적인 모놀리식 구조
마이크로 서비스
작고, 단순하고, 분리된 서비스 = 확장 가능하고, 회복적이며, 유연한 애플리케이션
마이크로 서비스 패턴
핵심 개발 패턴
서비스 세분성
통신 프로토콜(REST, MQ, Thrift)
인터페이스 설계
서비스 구성 관리
서비스 간 이벤트 처리
라우팅 패턴
서비스 디스커버리(유레카, etcd, 주키퍼), 서비스 메시
서비스 라우팅(API Gateway)
클라이언트 탄력성 패턴
클라이언트 부하 분산
회로 차단기 패턴
폴백 패턴
벌크헤드 패턴
보안 패턴
로깅 및 추적 패턴
애플리케이션 지표 패턴
빌드 및 배포 패턴
12 팩터 애플리케이션의 모범 사례

스프링 HATEOAS 구현

스프링 HATEOAS는 HATEOAS 원칙(해당 리소스와 관련된 링크를 표시하는)을 준수하는 API를 생성하는 작은 프로젝트다. 이 원칙에 따르면 API는 각 서비스 응답과 함께 가능한 다음 단계 정보도 제공하며, 클라이언트를 다음 단계로 가이드할 수 있어야 한다.
링크 생성: Spring HAETOS는 Link및 WebMvcLinkBuilder와 같은 클래스를 통해 URI를 쉽게 생성하고 관리할 수 있는 기능을 제공합니다. 이를 통해 개발자는 서비스의 다른 부분으로의 링크를 리소스에 쉽게 추가할 수 있습니다.
@Getter @Setter @Builder @ToString public class License extends RepresentationModel<License> { private int id; private String licenseId; private String description; private String organizationId; private String productName; private String licenseType; // 생성자, 메소드 등 추가 가능 }
Java
복사
RepresentationModel 추가
@GetMapping("/{licenseId}") public ResponseEntity<License> getLicense(@PathVariable("organizationId") String organizationId, @PathVariable("licenseId") String licenseId) { License license = licenseService.getLicense(licenseId, organizationId); license.add( linkTo(methodOn(LicenseController.class).getLicense(organizationId, license.getLicenseId())).withSelfRel(), linkTo(methodOn(LicenseController.class).createLicense(organizationId, license, null)).withRel("createLicense"), linkTo(methodOn(LicenseController.class).updateLicense(organizationId, license)).withRel("updateLicense"), linkTo(methodOn(LicenseController.class).deleteLicense(organizationId, license.getLicenseId())).withRel("deleteLicense") ); return ResponseEntity.ok(license); }
Java
복사
add()는 RepresentationModel 클래스 메서드이며, linkTo()메서드는 LicenseController 클래스를 검사해서 루트 매핑을 얻고 methodOn() 메서드는 대상 메서드에 더미 호출을 수행하여 메서드 매핑을 가져온다.
두 메서드 모두 Org.springfreamework.hateoas.server.mvc,WebMvcLinkBuilder의 정적 메서드다.
{ "id": 309, "licenseId": "2", "description": "Software product", "organizationId": "test", "productName": "Ostock", "licenseType": "full", // link 추가 "_links": { "self": { "href": "http://localhost:8080/v1/organization/test/license/2" }, "createLicense": { "href": "http://localhost:8080/v1/organization/test/license" }, "updateLicense": { "href": "http://localhost:8080/v1/organization/test/license" }, "deleteLicense": { "href": "http://localhost:8080/v1/organization/test/license/2" } } }
JSON
복사

데브옵스 관점(97)

데브옵스 관점에서 마이크로 서비스와 관련된 운영상 요구 사항을 사전에 해결하고, 이러한 4가지 원칙을 마이크로서비스를 빌드하고 환경에 배포할 때마다 발생하는 표준 수명 주기 이벤트로 변환해야 한다.
이 4가지 원칙은 다음에 나오는 운영 수명 주기에 매핑할 수 있다. 다음은 이 4단계가 어떻게 연결되는지 보여준다.
서비스 조립: 동일한 서비스 코드와 런타임이 정확히 동일한 방식으로 배포되도록 반복성과 일관성을 보장해야 한다.
서비스 부트스트래핑: 마이크로서비스를 사람의 개입 없이 모든 환경에서 빠르게 시작하고 배포할 수 있도록 런타임 코드에서 애플리케이션 코드와 환경별 구성 코드를 분리한다.
서비스 등록 및 디스커버리: 새 마이크로서비스 인스턴스가 배포될 때 애플리케이션 클라이언트가 새 서비스 인스턴스를 발견할 수 있는 방법이다.
서비스 모니터링: 마이크로서비스 환경에서 높은 가용성이 요구되므로 한 서비스에 여러 인스턴스를 실행하는 것이 일반적이다. 데브옵스 관점에서 마이크로서비스 인스턴스를 모니터링해야 하며 장애가 발생한 서비스 인스턴스를 우회해서 라우팅하고 종료되는지 확인해야 한다.

서비스 조립

마이크로서비스 아키텍쳐 핵심 개념은 애플리케이션의 환경 변화(갑작스러운 사용자 유입, 인프라스트럭쳐 문제)에 대응하여 마이크로서비스의 많은 인스턴스를 신속히 배포할 수 있다는 것이다. 이를 위해 마이크로서비스는 정리된 모든 의존성을 포함한 단일 산출물로 패키징되고 설치될 수 있어야 한다.
마이크로서비스를 호스팅 하는 런타임 엔진도 이들 의존성에 포함된다.
다행히 거의 모든 자바 마이크로서비스 프레임워크는 코드와 함께 패키징하고 배포할 수 있는 런타임 엔진을 포함한다. 예를 들어 스프링 부트 예제에서 메이븐과 스프링부트는 내장형 톰캣 엔진을 포함하여 JAR 실행 파일을 빌드한다.
어떤 운영팀에는 런타임 환경을 바로 JAR 파일에 내장하는 개념이 애플리케이션 배포 방법에서 큰 변화가 될 수 있다. 전통적인 자바 웹 애플리케이션에서 애플리케이션은 애플리케이션 서버에 배포된다.
애플리케이션 서버의 구성 애플리케이션과 분리하면 배포 과정에서 문제점이 발생되는데, 이것은 많은 조직에서 애플리케이션 서버의 구성 정보를 소스 제어 저장소에서 관리하지 않고 사용자 인터페이스나 자체 스크립트로 관리하기 때문이다. 결국 애플리케이션 서버 환경에서 구성 불일치가 너무 쉽게 발생하여 표면적으로 무작위 장애를 일으킨다.

서비스 부트스트래핑

서비스 부트스트래핑은 마이크로서비스가 처음 시작하고 애플리케이션 구성 정보를 로드할 때 일어난다.
모든 애플리케이션 개발자가 알고 있듯이 애플리케이션의 런타임 동작을 구성 가능하게 만들어야 할 때가 있다.
일반적으로 이 작업은 애플리케이션과 함께 배포된 프로퍼티 파일에서 구성 데이터를 읽거나 관계형 데이터베이스 같은 데이터 저장소에서 데이터를 읽어 오는 것이 해당된다. 마이크로서버시는 대게 동일한 종류의 구성을 요구한다. 차이점은 클라우드에서 실행되는 마이크로서비스 애플리케이션에는 수백 수천 개의 마이크로서비스가 실행될 수 있다는 것이다.
서비스가 전 세계로 확장되면 이 문제는 더 복잡해진다. 지리적으로 분산된 서비스 수가 많기 때문에 새로운 구성 정데이터를 가져오기 위해 서비스를 재배포하는 일은 수행하기 어렵다.
서비스 외부의 데이터 저장소에 데이터를 저장하면 이 문제가 해결되지만, 클라우드의 마이크로서비스 상황에서는 몇 가지 고유한 난제가 있다.
구성 데이터는 단순한 편이라서 보통 자주 읽고, 자주 변경하지 않는다.
데이터는 정기적으로 액세스되므로 지연시간이 낮아야 한다.
구성 데이터 저장소는 단일 장애지점이기 때문에 절대 다운되면 안된다.

서비스 디스커버리

마이크로 서비스 소비자 관점에서 마이크로서비스는 위치 투명성을 가져야 한다. 클라우드 기반 환경에서 서버는 일시적이기 때문이다. ‘일시적’이라는 것은 서비스를 호스팅하는 서버가 일반적으로 기업 데이터 센터에서 실행되는 서비스보다 수명이 짧다는 것을 의미한다.
클라우드 기반 서비스는 자기 서버에 완전히 새로운 IP 주소를 할당받아 신속하게 시작되고 종료될 수 있다.
서비스를 수명이 짧고 폐기 가능한 객체로 다루자는 주장 덕분에 마이크로 서비스 아키텍쳐는 많은 서비스 인스턴스를 실행하며 높은 수준의 확장성과 가용성을 얻을 수 있었다.
그리고 상황이 허락되는 한 신속하게 서비스 요구와 회복탄력성을 관리할 수 있다. 모든 서비스에는 고유하고 비영구적인 IP 주소가 할당되어 있다. ‘일시적’ 서비스의 단점은 끊임없이 서비스 시작과 종료를 반복하는 상황에서 대규모 서비스를 수동 또는 직접 관리하면서 장애를 초래할 수 있다는 점이다.
마이크로서비스 인스턴스는 3자 에이전트에 자신을 등록해야 하는데, 이 등록과정을 서비스 디스커버리라고한다.
인스턴스가 서비스 디스커버리 에이전트에 등록될 때, 인스턴스는 에이전트에 다음 2가지 정보를 제공한다.
물리적 IP주소(서비스 인스턴스의 도메인 주소)
애플리케이션이 서비스를 찾을 때 사용되는 논리적 이름
특정 서비스 디스커버리 에이전트의 경우 상태 확인을 수행하는데 사용할 호출 가능한 URL을 등록할 때 서비스에 요구하기도 한다. 이제 서비스 클라이언트는 디스커버리 에이전트와 통신하여 서비스 위치를 찾는다.(99)

서비스 모니터링

서비스 디스커버리 에이전트 클라이언트를 서비스 위치로 안내하는 교통 경찰 역할만 하는것은 아니다. 클라우드 기반 마이크로서비스에는 애플리케이션에서 실행 중인 서비스 인스턴스가 많고, 조만간 그 서비스 인스턴스 중 하나가 고장날 수 있다.
서비스 디스커버리 에이전트는 등록된 각 서비스 인스턴스 상태를 모니터링하고 해당 서비스가 가용한지 확인하고자 지속적으로 모니터링하고 상태 확인 인터페이스를 핑한다.
일관된 상태 확인 인터페이스를 만들어 클라우드 기반 모니터링 도구를 사용하여 문제를 탐지하고 적절히 대응할 수 있다. 서비스 디스커버리 에이전트가 문제가 있는 서비스 인스턴스를 발견하면 고장 난 인스턴스를 종료시키거나 새로운 서비스를 추가하는 등 정상화 조치를 취할 수 있다.
하지만 스프링 부트에서 엔드포인트를 노출하기가 어렵지 않으며, 스프링 액추에이터 모듈을 포함하도록 메이븐 빌드 파일만 수정하면 된다. 스프링 엑추에티너는 서비스 상태를 이해하고 관리할 수 있게 하며, 추가 설치 없이 바로 운영가능한 엔드포인트를 제공한다.

요약

마이크로서비스의 성공을 위해 아키텍트, 소프트웨어 개발자, 데브옵스 이 3팀의 관점을 통합해야 한다.
마이크로서비스는 강력한 아키텍쳐 패러타임이지만 장단점이 있다.
HATEOAS는 애플리케이션 상태 엔진인 하이퍼미디어의 줄임말이다. 스프링 HATEOAS는 HATEOAS 원칙을 따르는 API를 생성할 수 있는 작은 프로젝트다.

4장

빌드팩

빌드팩은 애플리케이션 및 프레임워크 의존성을 제공하는 도구로, 소스 코드를 실행 가능한 애플리케이션 이미지로 변환한다. 즉 빌드팩은 애플리케이션을 실행하는데 필요한 모든 것을 탐색하고 가져온다.
스프링 부트는 클라우드 네이티브 빌드팩을 사용해 도커 이미지를 빌드할 수 있도록 지원한다.
./gradlew bootBuildImage
Java
복사

레이어로 분리된 JAR

./gradlew clean build java -Djarmode=layertools -jar build/libs/[.jar 이름] list
Java
복사
FROM openjdk:17-slim as build WORKDIR application ARG JAR_FILE=build/libs/msa-0.0.1-SNAPSHOT.jar COPY ${JAR_FILE} application.jar # Spring Boot Layer Tools를 사용하여 JAR 파일을 여러 레이어로 분해하고 추출 RUN java -Djarmode=layertools -jar application.jar extract && ls -la # 두 번째 스테이지: 동일한 Java 런타임 베이스 이미지를 사용하여 최종 애플리케이션 이미지를 구성 FROM openjdk:17-slim # 컨테이너 내에서 애플리케이션 파일이 위치할 작업 디렉토리를 설정 WORKDIR application # 첫 번째 빌드 스테이지에서 추출된 각 레이어(종속성, 스프링 부트 로더, 스냅샷 종속성, 애플리케이션 파일)를 # 현재 스테이지의 작업 디렉토리에 복사 COPY --from=build application/dependencies/ ./ COPY --from=build application/spring-boot-loader/ ./ COPY --from=build application/snapshot-dependencies/ ./ COPY --from=build application/application/ ./ # 컨테이너 시작 시 Spring Boot 애플리케이션을 실행하는 EntryPoint 설정 ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]
Java
복사
스프링부트는 레이어로 나뉜 JAR이라는 새로운 JAR 레이아웃을 도입했습니다. 이 포맷에서 /lib, /classes 폴더가 분리되어 레이어로 분류됩니다.
이렇게 레이어로 분리한 것은 빌드에 필요한 정보를 남겨 두고 빌드 간 변경될 가능성에 따라 코드를 나누기 위해서입니다. 이 방법은 빌드팩을 사용하지 않는 경우에 사용할 수 있는 훌륭한 대안책입니다.
아래의 단계를 따라가면 됩니다.
1.
애플리케이션 패키징
2.
layertools JAR 모드로 시스템 프로퍼티를 실행
3.
Dockerfile 실행
4.
이미지 빌드 및 실행

JAVA 명령어

# 메모리 설정: 최대 힙 사이즈를 1024MB로 설정 java -Xmx1024m -jar target/your-application-0.0.1-SNAPSHOT.jar # 가비지 컬렉션 설정: G1 가비지 컬렉터 사용 java -XX:+UseG1GC -jar target/your-application-0.0.1-SNAPSHOT.jar # 시스템 프로퍼티 설정: Spring 프로필을 'dev'로 활성화 java -Dspring.profiles.active=dev -jar target/your-application-0.0.1-SNAPSHOT.jar # 디버깅 설정: 원격 디버깅을 위해 애플리케이션 실행 java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:5005 -jar target/your-application-0.0.1-SNAPSHOT.jar
Bash
복사
# 첫 번째 스테이지: 실행 가능한 JAR 파일에서 레이어 추출 FROM openjdk:17-slim as build WORKDIR application # 애플리케이션 JAR 파일 지정 ARG JAR_FILE=target/your-application-0.0.1-SNAPSHOT.jar # JAR 파일을 작업 디렉토리로 복사 COPY ${JAR_FILE} application.jar # Spring Boot Layer Tools를 사용하여 레이어로 JAR 파일 분해 및 추출 RUN java -Djarmode=layertools -jar application.jar extract # 두 번째 스테이지: 레이어 복사 및 애플리케이션 실행 FROM openjdk:17-slim WORKDIR application # 첫 번째 스테이지에서 추출한 레이어를 현재 스테이지로 복사 COPY --from=build application/dependencies/ ./ COPY --from=build application/spring-boot-loader/ ./ COPY --from=build application/snapshot-dependencies/ ./ COPY --from=build application/application/ ./ # 컨테이너 시작 시 Spring Boot 애플리케이션을 실행하는 EntryPoint 설정 ENTRYPOINT ["java","org.springframework.boot.loader.JarLauncher"]
Bash
복사

EntryPoint

JarLauncher는 Spring boot의 일부로 제공되는 클래스 로더 중 하나입니다.
실행 가능한 JAR 파일 내에 있는 org.springframework.boo.loader 패키지에 위치하며, 애플리케이션의 메인 클래스를 찾아 실행합니다. JarLauncher는 Jar 파일안에 내장된 라이브러리와 클래스들을 로드하는데 필요한 로직을 처리합니다.
Springboot는 애플리케이션과 그 종속성을 포함하는 단일 실행 가능한 JAR 파일을 생성합니다. 이 Jar 파일 내부에는 JarLauncher를 포함한 여러 클래스 로더와 애플리케이션의 모든 클래스 및 리소스가 있습니다.

-Djarmode=layertools

해당 옵션은 Spring boot 2.3이상에서 도입된 기능으로, Spring boot 애플리케이션의 JAR 파일을 여러 레이어로 분해하여 관리하는데 사용됩니다. 이 옵션을 사용하면, layertools 모드가 활성화되어 JAR 파일 내의 클래스와 리소스를 분리된 레이어로 추출될 수 있습니다.
레이어 추출은 총 4가지로 분류되며, 도커 이미지 빌드에 사용됩니다.
dependencies: build.gradle, pom.xml과 같은 파일에 정의된 외부 라이브러리
spring-boot-loader: 스프링 부트 애플리케이션을 실행할 때 필요한 클래스 로더와 관련 코드, JAR 파일을 실행가능한 형태로 만들어 준다.
snapshot-dependencies: 스냅샷 버전의 종속성을 포함합니다. 스냅샷 종속성은 개발 중에 자주 변경될 수 있는 라이브러리나 프로젝트 내부 모듈을 가리킵니다.
application: 실제 코드 .class, .properties를 포함하며, 실제 작성한 코드와 구성파일입니다.
도커 이미지를 빌드할 때, 추출된 레이어를 활용하여 이미지의 레이어를 효율적으로 관리할 수 있습니다. 가장 자주 변경되는 application 레이어를 분리하여 관리함으로써, 이미지의 재빌드와 배포 시간을 단축할 수 있습니다.

클라우드 컨피그 서버

마이크로 서비스 개발을 위한 모범 사례로 다음 사항을 고려해야 한다.
배포되는 실제 코드와 구성 정보를 완전히 분리한다.
여러 환경에서도 절대 변경되지 않는 불변 애플리케이션 이미지를 빌드한다.
서버가 시작할 때 마이크로서비스가 읽어 오는 환경 변수 또는 중앙 저장소를 통해 모든 애플리케이션 구성 정보를 주입한다.

구성 관리

애플리케이션 구성을 만들기 위해 4가지 원칙을 소개한다.
1.
분리: 서비스 인터페이스 뒷단에 있는 구성 정보를 완전히 분리해야 한다. 실제로 애플리케이션 구성 정보는 서비스 인스턴스와 함께 배포되어서는 안되며, 시작중인 서비스에 환경 변수로 전달되거나 서비스가 시작할 때 중앙 저장소에서 읽어 들여야한다.
2.
추상화: 서비스 인터페이스 뒷단에 있는 구성 데이터의 접근 방식을 추상화해야 한다. 애플리케이션 구성 데이터를 조회하는데 서비스 저장소(파일 or JDBC 데이터베이스 기반)에서 직접 읽어오는 코드보다는 REST기반 JSON 서비스를 이용해야 한다.
3.
중앙 집중화: 클라우드 기반의 애플리케이션에는 실제로 수백 개의 서비스가 실행될 수 있어 구성 데이터를 보관하는데 사용되는 여러 저장소 수를 최소화하는 것이 중요하다.
4.
견고화: 애플리케이션 구성 정보는 배포되는 서비스와 완전히 분리되고 중앙 집중화 되므로, 구현할 솔루션은 가용서이 높고 이중화가 필요하다.

구현 솔루션 선택

시장에서 검증받은 많은 오픈 소스 프로젝트를 선택해서 구성 관리 솔루션을 구현할 수 있다.
etcd: go 언어로 작성된 오픈소스 프로젝트로 서비스 디스커버리와 키-값 관리에 사용된다.
유레카: 넷플릭스가 만들었으며 서비스 디스커버리와 키-값 관리에 사용된다.
Consul(콘술): 하시코프가 만들었으며, etcd나 유레카와 비슷하지만 분산 컴퓨팅 모델에 다른 알고리즘을 사용한다.
Zookeeper(주키퍼): 아파치 프로젝트로 분산 잠금 기능을 제공한다.
스프링 클라우드 구성: 오픈 소스 프로젝트로 다양한 백엔드와 함께 전반적인 구성관리 솔루션을 제공한다.
스프링 클라우드 구성 서버는 설정을 외부에서 관리하고 클라우드 환경에서 쉽게 분산시킬 수 있는 프로젝트다.
스프링 클라우드 컨피그 서버를 만들때 핵심 구성을 정의할 파일을 만들어야한다. 아래 2개중 하나를 선택하면 된다.
application.yml
bootstrap.yml
부트스트랩 파일은 스프링 클라우드의 특정 파일 타입이며 스프링 애플리케이션 이름, 스프링 클라우드 구성 서버 위치, 암호화/복호화 정보 등을 지정한다. 특히 부트스트랩 파일은 부모 격인 ApplicationContext로 로드되고 이 부모 컴포넌트는 application.properties나 application.yml 파일을 사용하는 컴포넌트보다 먼저 로드된다.
여기서는 bootstrap.yml을 통해 컨피그 서버와 마이크로 서비스의 구성 정보를 확인한다.
spring: application: name: config-server server: port: 8071
YAML
복사
@SpringBootApplication @EnableConfigServer // 스프링 클라우드 컨피그 서비스 활성화 public class ConfigserverApplication { public static void main(String[] args) { SpringApplication.run(ConfigserverApplication.class, args); } }
Java
복사
스프링 클라우드 컨피그 서버는 bootstrap.yml 파일에서 애플리케이션 구성 데이터를 보관할 저장소를 지정한다.
파일 시스템 기반의 저장소를 설정하는 것이 가장 쉽다.
spring: application: name: config-server profiles: active: native # 프로필 지정 cloud: config: server: native: search-locations: file://(FILE_PATH) # 구성 파일이 저장된 검색 위치 server: port: 8071
YAML
복사
스프링 클라우드 컨피그 서버는 native 프로파일로 실행되도록 지정해야 하며, 스프링 프로파일은 스프링 프레임워크가 제공하는 핵심 기능임을 기억하자.
native는 클라우드 컨피그 서버용으로만 생성한 프로파일이며, 구성 파일을 클래스 파일 시스템에서 검색하고 읽도록 지시하는 프로파일임을 기억하자.
파일 시스템 기반의 저장소를 사용할 때, git 또는 볼트 구성을 사용하지 않는 컨피그 서버의 프로파일이기 때문에 native를 사용한다. 대신 로컬 클래스패스나 파일 시스템에서 직접 구성 데이터를 로드한다.
구성항목중 가장 중요한건 search-locations다. 구성 서버에서 관리할 애플리케이션들의 디렉토리를 쉼표로 구분하여 매개변수로 전달할 수 있다. 특정 클래스 패스 지정도 가능하다.
native: search-locations: classpath:/config # src/main/resource/config 폴더검색
YAML
복사
예제를 간결하게 하기 위해 3가지 환경(default, dev, production)에 대해서만 설정한다.
스프링 클라우드 컨피그는 모든 것이 계층 구조로 동작한다. 애플리케이션 구성 정보는 애플리케이션 이름과 환경별로 구성할 프로퍼티를 표시하며, 각 환경에서 다음과 같은 구성 프레임을 설정한다.
라이선싱 서비스에 직접 사용될 예제용 프로퍼티
라이선싱 서비스에 사용될 스프링 액추에이터
라이선싱 서비스의 데이터베이스 구성
dev를 호출할 때 스프링 클라우드 컨피그 서버는 default와 dev의 구성 프로퍼티를 모두 반환했다.
스프링 클라우드 컨피그가 두 구성정보를 모두 반환하는 이유는 스프링 프레임워크가 문제를 해결하는데 계층적 메커니즘을 수행하기 때문이다. default 프로파일에서 정의된 프로퍼티를 먼저 찾은 후 특정 환경에 값이 있다면 그 값으로 default 값을 교체한다. 다시 설명하자면 licensing-servier.properties 파일에서 프로퍼티를 정의하고 다른 환경 구성에서는 정의하지 않았다면 프레임워크는 default값을 사용한다.
docker run --name some-postgres \ -e POSTGRES_DB=msa \ -e POSTGRES_USER=admin \ -e POSTGRES_PASSWORD=1234 \ -p 5432:5432 \ -d postgres
YAML
복사