Search
Duplicate

[Spring MSA] 01-1.

수업
Spring MSA
주제
5 more properties
microservices
eazybytes

마이크로 서비스?

모놀리틱

장점
간단하게 개발이 가능하다.
크로스관련 문제를 덜 겪는다.
네트워크 지연시간을 줄일 수 있다.
단점
새로운 기술을 도입하기 힘들다.
에자일이 힘들다
실패 원자적이지 않다.
작은 업데이트할때 전체를 업데이트해야 한다.
단일 지점 DB만 가지고 있는다.

SOA(Service Oritented Architecture

UI로직을 분리할 수 있었지만 미들웨어를 꼭 써야한다는 단점이 있다.
장점
재사용성 증가
고가용성
병렬 개발
단점
SOAP처럼 복잡한 프로토콜을 사용해야 한다.
아주 복잡하고 무거운 상업용 미들웨어를 사용해야 한다.

MSA

장점
개발하기 쉽고, 테스트하기 좋다.
애자일 증가
수평적 확장 가능성
병렬 개발
비즈니스 도메인 위주의 개발
단점
복잡성 증가
인프라 오버헤드
보안 걱정(다수의 서버가 배포되므로 관리가 힘들다)
마이크로 서비스는 독립적 배포성에 우선순위를 둔다.

왜 스프링부트 마이크로서비스인가?

스프링 부트는 이미 잘 알려진 스프링 프레임워크를 기반으로 만들어졌습니다. 이를 사용하여 자바 기반의 웹 애플리케이션과 마이크로서비스를 쉽게 개발하고 배포할 수 있으며, 개발자의 생산성을 크게 향상시키는 동시에 개발 및 운영 팀의 작업을 단순화합니다. 스프링 부트의 주요 장점 중 하나는 전통적인 WAR 또는 EAR 파일 대신 자체 포함되고 실행 가능한 JAR 파일을 생성하여 비즈니스 로직에만 집중할 수 있게 해주며, 내장된 서버로의 배포 및 시작을 자동화한다는 것입니다.
이러한 방식은 별도의 웹 서버가 필요 없게 만들며, 수동으로 서버를 관리할 필요성을 없앱니다. 또한, 스프링 부트는 다음과 같은 다양한 추가 이점을 제공합니다:
1.
내장 기능과 통합: 스프링 부트는 자동 구성(auto configuration), 의존성 주입(dependency injection)과 같은 개념을 통해 많은 내장 기능과 통합을 제공합니다. 또한 다양한 클라우드 플랫폼을 지원합니다.
2.
쉬운 설정 변경: 기본 설정에 만족하지 않는 개발자는 스프링 부트 프레임워크 내의 속성을 통해 이를 쉽게 오버라이드할 수 있습니다.
3.
내장 서버: 스프링 부트는 Tomcat, Jetty, Undertow와 같은 내장 서버를 제공하여 별도의 서버 설치 및 유지보수 없이 바로 마이크로서비스를 실행할 수 있게 해줍니다.
4.
생산 준비 기능: 스프링 부트는 애플리케이션의 메트릭, 건강 모니터링, 외부 설정과 같은 다양한 생산 준비 기능을 지원합니다. 이는 스프링 부트 액추에이터와 같은 의존성을 사용함으로써 달성됩니다.
5.
빠른 프로젝트 시작: 스타터 종속성들을 범위로 하여 빠르게 마이크로서비스 프로젝트를 시작하고 코딩할 수 있습니다.
6.
클라우드 준비: 생성된 마이크로서비스는 클라우드에 쉽게 배포될 수 있으며, Docker를 이용해 컨테이너화가 가능하고 AWS, GCP, Azure와 같은 클라우드 제공업체에 쉽게 배포할 수 있습니다.
이러한 이점들 덕분에 스프링 부트는 개발자와 운영 팀에게 큰 도움이 됩니다. 특히 이러한 '자체 포함된 JAR'은 서버 설치와 구성의 필요성을 제거하며, ‘통통한 JAR’ 또는 ‘우버 JAR’이라고도 불리우는데, 이는 모든 종속성과 비즈니스 로직을 포함하고 있어 별도의 서버 없이도 실행이 가능합니다.
스프링 부트 프레임워크의 도입을 통해, 개발자들은 모노리틱 접근 방식으로 웹 애플리케이션을 구축할 때의 복잡성을 벗어나 더욱 신속하고 유연하게 마이크로서비스를 구축하고 배포할 수 있게 되었습니다. 이 강의 시리즈를 통해 저는 이 모든 장점들을 직접 보여드릴 예정이며, 스프링 부트 프레임워크를 사용하여 마이크로서비스를 구축하는 방법을 실제로 시연해 보일 것입니다.
전통적인 접근법에서는 애플리케이션들이 WAR 파일로 패키징되며, 실행을 위해 Tomcat, Jetty, Netty, Undertow와 같은 서버의 존재가 필요하고 이 모든 것은 JVM(Java Virtual Machine) 위에서 동작합니다.
반면에, 현대적인 접근법에서는 애플리케이션들이 자체 포함 JAR(Java ARchive)로 패키징되며, 이는 'Fat-JAR' 또는 'uber-JAR'라고도 불립니다. 이 JAR 파일들은 애플리케이션 자체, 필요한 모든 종속성(dependencies), 그리고 내장된 서버(embedded server)를 포함합니다. 이렇게 패키징된 마이크로서비스들은 별도의 서버 없이 JVM 위에서 독립적으로 실행될 수 있습니다.
이러한 접근 방식의 장점은 개발자가 서버 설정이나 유지보수에 대해 신경 쓸 필요 없이, 애플리케이션 개발에 집중할 수 있다는 것입니다. 또한 배포 과정이 간소화되어 빠르고 효율적으로 이루어질 수 있으며, 마이크로서비스 아키텍처의 독립성과 확장성 요구사항을 더 잘 충족시킬 수 있습니다.

마이크로서비스란?

마이크로서비스는 다른 API나 외부 UI 애플리케이션에 비즈니스 로직을 노출하는 서비스입니다. REST API를 통해 이러한 비즈니스 로직에 대한 접근을 제공합니다.

REST 서비스

정의와 특징: REST 서비스는 HTTP 프로토콜을 기반으로 동작하며, SOAP 기반 웹 서비스와 비교해 가볍습니다. JSON과 같은 가벼운 데이터 포맷을 사용할 수 있기 때문입니다. 이러한 특징으로 인해 웹 앱 간의 통신을 위한 가장 일반적인 접근 방식 중 하나로 여겨집니다.
동작 방식: 웹 애플리케이션은 클라이언트 애플리케이션이 요청을 보내서 호출할 수 있는 여러 엔드포인트를 노출합니다. 이는 백엔드 서버 간의 통신 또는 UI 프레임워크(예: Angular, React)와 백엔드 서버 간의 데이터 교환을 위해 사용됩니다.

REST 서비스 구현 시 필요한 표준

HTTP 메소드 활용: CRUD(생성, 읽기, 업데이트, 삭제) 작업을 지원하는 REST API를 구축할 때, 적절한 HTTP 메소드(POST, GET, PUT/PATCH, DELETE)를 사용해야 합니다.
입력 검증: REST API는 다양한 클라이언트 애플리케이션으로부터 요청을 받을 수 있으므로, 외부 시스템에서 수행되는 검증에 의존하지 않고, 자체적으로 입력 검증을 수행해야 합니다.
예외 처리: 런타임 예외나 비즈니스 예외에 대해 적절히 처리하고, 클라이언트에게 의미 있는 응답을 반환해야 합니다. 이는 클라이언트가 API의 문제를 이해하고 대처할 수 있게 해줍니다.
서비스 문서화: 수백에서 수천 개의 REST 서비스를 구축할 때, OpenAPI 스펙이나 Swagger와 같은 표준을 사용하여 서비스를 문서화하는 것이 중요합니다. 이는 서비스를 소비하는 클라이언트가 요청 형식, 유효성 검사, 응답 형식, 지원하는 작업 등에 대해 이해하는 데 도움이 됩니다.

마치며

강사는 이러한 기본 사항을 바탕으로 Spring Boot 프레임워크를 사용하여 실제 프로젝트에서 프로덕션 준비가 완료된 서비스를 구축하는 방법을 안내할 것입니다. 이후 강의에서는 메시지 큐와 Kafka를 예로 들어 비동기 마이크로서비스 구축 방법도 소개할 예정입니다.

프로젝트 시작하기

1.
start.spring.io 방문: Spring Boot 프로젝트를 시작할 때 이 사이트를 사용하여 프로젝트 사양(사용할 언어, 빌드 도구, Spring Boot 버전 등)을 선택합니다.
2.
프로젝트 설정: Maven을 빌드 도구로, Java를 언어로 선택합니다. 현재 가장 안정적인 Spring Boot 버전은 3.1.1입니다. 그룹 ID는 com.eazybytes로, 아티팩트 ID와 이름은 accounts로 설정합니다. 이는 Easy Bank의 계정 관련 마이크로서비스를 의미합니다.
3.
의존성 추가: 웹 애플리케이션 및 REST 서비스 구축을 위한 필요한 의존성을 추가합니다. 여기에는 Spring Web, H2 데이터베이스, Spring Data JPA, Spring Boot Actuator, Spring Boot DevTools, Lombok, 그리고 Validation이 포함됩니다.

개발 환경 설정

Maven 설정: 제공된 기본 구성에 따라 Maven 프로젝트를 설정합니다. Java 버전은 17로 설정하며, Spring Boot 3 이상 버전을 사용할 때는 최소 Java 17이 필요합니다.
IDE로 프로젝트 가져오기: 다운로드한 프로젝트 ZIP 파일을 압축 해제한 후, IntelliJ IDEA와 같은 IDE로 프로젝트를 가져옵니다.

첫 번째 REST API 생성

강의의 이 부분에서는 실제로 코드를 작성하여 Hello World REST API를 구현할 준비를 합니다. 이는 다음 강의의 주제가 될 것입니다.
이 과정을 통해 마이크로서비스를 구축하기 위한 기본 환경 설정과 초기 단계가 완료됩니다. 강사는 이 프로세스를 따라하는 것이 중요하다고 강조하며, 같은 네이밍 컨벤션을 사용하여 문제 발생 시 쉽게 해결할 수 있도록 조언합니다. 또한, 각 단계를 세심하게 설명하여 학습자가 스스로 따라 할 수 있도록 안내합니다. 이후 강의에서는 실제로 REST API를 구현하는 방법을 다룰 예정입니다.

REST API 추가하기

1.
컨트롤러 생성: com.eazybytes.accounts.controller 패키지 안에 AccountsController 클래스를 생성합니다. 이 클래스 안에 모든 계정 관련 REST API를 작성할 것입니다.
2.
@RestController 어노테이션: 클래스에 @RestController 어노테이션을 추가하여 스프링 부트 프레임워크에 이 클래스의 메소드들이 REST API로 노출되어야 함을 지시합니다.
3.
메소드 생성: "Hello World" 메시지를 반환하는 sayHello라는 메소드를 작성합니다. 이 메소드 위에 @GetMapping 어노테이션을 추가하여 HTTP GET 요청을 처리하도록 합니다.

애플리케이션 실행 및 API 테스트

애플리케이션 실행: 애플리케이션을 디버그 모드로 실행하여 포트 8080에서 서비스를 시작합니다. H2 데이터베이스와 Actuator에 대한 자동 구성이 완료됩니다.
API 호출: 브라우저에서 localhost:8080/sayHello로 요청을 보내 "Hello World" 응답을 받습니다.

IntelliJ IDEA 활용

DevTools를 통한 빠른 재시작: 소스 코드 변경 후 빌드를 하면 Spring Boot의 DevTools가 애플리케이션을 빠르게 재시작합니다. 이를 통해 변경 사항을 즉시 반영할 수 있습니다.
테마 및 폰트 설정: IntelliJ IDEA에서 File > Settings > Plugins를 통해 원하는 테마(예: Dark Purple)를 설치하여 사용자의 선호에 맞는 개발 환경을 구성할 수 있습니다.
Lombok 설정: Lombok을 사용하기 위해 Settings > Build, Execution, Deployment > Compiler > Annotation Processors에서 어노테이션 처리를 활성화해야 합니다.

YML 파일 설정

application.properties 파일을 application.yml로 이름을 바꾸어 YAML 형식으로 설정을 정의합니다. YAML은 읽기 쉽고 직관적인 형식이며, Docker, Kubernetes, 다양한 클라우드 서비스 제공업체에서 널리 사용됩니다.
YAML에서는 들여쓰기를 사용하여 설정을 구조화합니다. 이를 통해 설정을 더 명확하게 구분하고 관리할 수 있습니다.

데이터베이스 설정

application.yml에 서버 포트, 데이터베이스 연결 정보, H2 콘솔 활성화, JPA 및 Hibernate 설정을 포함하여 필요한 모든 데이터베이스 관련 설정을 정의합니다.
schema.sql 파일을 생성하여 데이터베이스 스키마를 정의하고, 필요한 경우 data.sql 파일을 사용하여 데이터베이스에 초기 데이터를 삽입합니다.

H2 데이터베이스와 상호 작용

Spring Boot 애플리케이션이 시작될 때, application.yml에서 정의한 설정을 바탕으로 내부 H2 데이터베이스에 자동으로 연결합니다.
H2 콘솔을 활성화하여 브라우저를 통해 데이터베이스에 접속하고 테이블을 확인할 수 있습니다.

개발 환경 개선

IntelliJ IDEA에서 YAML 파일과 관련된 플러그인을 설치하여 YAML 파일을 쉽게 관리하고 편집할 수 있습니다.
Spring Boot의 DevTools를 사용하여 코드 변경 사항이 있을 때 자동으로 애플리케이션을 재시작하여 개발 효율성을 높일 수 있습니다.

엔티티 클래스 생성

1.
기본 엔티티(BaseEntity) 클래스: 모든 테이블에 공통적으로 존재하는 메타데이터 필드(생성 시간, 생성자, 업데이트 시간, 업데이트한 사람)를 가진 기본 클래스를 생성합니다. Lombok 어노테이션(@Getter, @Setter, @ToString)을 사용하여 코드의 반복을 줄입니다.
2.
엔티티 클래스: 각 데이터베이스 테이블을 대표하는 엔티티 클래스를 생성합니다(Customer, Accounts). 이 클래스들은 BaseEntity를 확장하여 메타데이터 필드를 상속받습니다. @Entity 어노테이션을 사용하여 클래스가 엔티티임을 명시하고, @Id@GeneratedValue 어노테이션을 사용하여 기본 키가 자동으로 생성되도록 합니다.
최신 jpa에서 native 전략은 제거되었습니다. 그러므로 @GenetratedValue(strategy = GenerationType.IDENTITY)를 사용하세요
원래는 GeneratedValue(strategy=GenerationType.AUTO, generator=”native”)라고 명시됨

레포지토리 인터페이스 정의

1.
레포지토리 인터페이스: 각 엔티티 클래스에 대한 CRUD 작업을 수행할 수 있는 레포지토리 인터페이스를 생성합니다(CustomerRepository, AccountsRepository). 이 인터페이스는 JpaRepository를 확장하며, 엔티티 타입과 해당 엔티티의 기본 키 타입을 매개변수로 받습니다.
2.
Spring Data JPA 활용: JpaRepository 인터페이스를 확장함으로써, Spring Data JPA는 레포지토리 인터페이스의 구현체를 자동으로 생성하며, 이를 통해 데이터베이스와의 상호작용을 위한 다양한 메서드(예: save, findAll, deleteById 등)를 제공받게 됩니다.
이 과정을 통해 개발자는 데이터베이스 테이블과 상호 작용하기 위한 Java 코드를 효율적으로 작성할 수 있게 되며, Spring Data JPA의 강력한 기능을 활용하여 데이터 접근 로직을 간소화할 수 있습니다. 다음 강의에서는 이 레포지토리 인터페이스를 사용하여 실제 데이터베이스 작업을 수행하는 방법을 다룰 예정입니다.

주요 단계:

1.
RestController 수정: 이전에 만든 sayHello API를 삭제하고 AccountsController에 새 REST API를 추가합니다. 모든 API에 공통적으로 사용될 /api 접두사를 포함하는 @RequestMapping 어노테이션을 클래스에 추가합니다.
2.
새 계정 생성 API 구현: createAccount 메소드를 추가하여 새 계정 생성을 지원합니다. 이 메소드는 CustomerDto를 입력으로 받고, 성공적인 계정 생성시 ResponseEntity를 통해 ResponseDto를 반환합니다.
3.
DTO 클래스 사용: 입력된 데이터를 처리하기 위해 CustomerDto를 사용합니다. @RequestBody 어노테이션을 통해 클라이언트로부터 받은 JSON 데이터를 CustomerDto 객체로 변환합니다.
4.
서비스 계층 생성: 비즈니스 로직을 컨트롤러와 분리하기 위해 서비스 인터페이스(IAccountsService)와 구현체(AccountServiceImpl)를 생성합니다. 이 서비스 계층에서 실제 계정 생성 로직을 구현합니다.
5.
레포지토리 클래스 활용: AccountRepositoryCustomerRepository를 서비스 계층에 주입하여 데이터베이스와의 상호작용을 관리합니다.
6.
Mapper 클래스 생성: 엔티티 객체와 DTO 객체 간의 데이터 변환을 위해 AccountsMapperCustomerMapper 클래스를 만듭니다. 이 클래스들은 엔티티 객체를 DTO 객체로, 그리고 그 반대로 변환하는 메소드를 포함합니다.
7.
ModelMapper 라이브러리 언급: 자동으로 엔티티와 DTO 간의 매핑을 수행할 수 있는 ModelMapperMapStruct와 같은 라이브러리가 있지만, 이 강의에서는 직접 매핑 로직을 구현하여 더 많은 제어권을 가집니다.

주요 단계 요약:

1.
AccountsController 수정: 새로운 메소드 fetchAccountDetails를 추가하여 휴대폰 번호를 입력으로 받고, 고객 DTO를 응답으로 반환합니다. 이 메소드에는 @RequestParam@GetMapping 어노테이션을 사용하여 휴대폰 번호를 쿼리 파라미터로 받고 /fetch 경로로 데이터를 조회합니다.
2.
IAccountService 인터페이스에 메소드 추가: 휴대폰 번호를 입력으로 받아 고객 DTO를 반환하는 fetchAccount 추상 메소드를 추가합니다.
3.
AccountServiceImpl에 로직 구현: fetchAccount 메소드에서 휴대폰 번호를 사용하여 데이터베이스에서 고객 및 계정 정보를 조회하고, 해당 정보를 DTO로 변환하여 반환합니다. 데이터가 존재하지 않는 경우, ResourceNotFoundException을 발생시킵니다.
4.
예외 처리: 존재하지 않는 리소스에 대해 ResourceNotFoundException 커스텀 예외를 생성하고, GlobalExceptionHandler에서 이를 처리하여 적절한 오류 메시지와 HTTP 상태 코드를 클라이언트에 반환합니다.
5.
DTO 변환: 조회된 엔티티 객체를 DTO로 변환하기 위해 CustomerMapperAccountsMapper를 사용합니다. 고객 정보에 계정 정보를 포함시키기 위해 CustomerDto 내에 AccountsDto 필드를 추가합니다.
6.
API 테스트: Postman을 사용하여 생성한 API를 테스트하고, 휴대폰 번호에 따라 올바른 고객 및 계정 정보가 반환되는지 확인합니다. 존재하지 않는 휴대폰 번호로 요청할 경우, 적절한 오류 응답이 반환되는지도 확인합니다.

주요 구현 단계:

1.
IAccountService 인터페이스에 메소드 추가: 삭제 기능을 지원하는 deleteAccount 메소드를 추가합니다. 이 메소드는 휴대폰 번호를 입력으로 받고, 삭제 작업이 성공적으로 수행되었는지 여부를 나타내는 boolean 값을 반환합니다.
2.
AccountServiceImpl에서 비즈니스 로직 구현: 주어진 휴대폰 번호를 기반으로 고객 정보를 조회하고, 조회된 고객 ID를 사용하여 계정 및 고객 정보를 삭제합니다. 삭제 작업은 CustomerRepositoryAccountRepository를 통해 수행됩니다.
3.
AccountsController에 삭제 API 메소드 추가: deleteAccountDetails 메소드를 추가하여 /api/delete 경로로 DELETE 요청을 받습니다. 이 메소드는 휴대폰 번호를 요청 파라미터에서 받아 서비스 계층의 deleteAccount 메소드를 호출하고, 응답으로 삭제 성공 여부에 따라 적절한 HTTP 상태 코드와 메시지를 반환합니다.
4.
예외 처리: 삭제하려는 리소스가 데이터베이스에 존재하지 않을 때 발생하는 ResourceNotFoundException 커스텀 예외를 처리합니다. GlobalExceptionHandler에서 이 예외를 캐치하고 적절한 HTTP 상태 코드와 오류 메시지를 클라이언트에 반환합니다.
5.
API 테스트: Postman을 사용하여 삭제 API를 테스트합니다. 삭제하려는 고객의 휴대폰 번호를 포함하여 요청을 보내고, 요청에 성공했다는 응답을 받습니다. 또한, 삭제된 정보를 다시 조회하려고 시도할 때 적절한 오류 응답이 반환되는지 확인합니다.

@Transactional

@Transactional 어노테이션은 해당 메소드가 트랜잭션의 일부임을 스프링 프레임워크에 알립니다.
이 어노테이션은 메소드 실행을 하나의 연속된 작업으로 처리하도록 하여, 모든 작업이 성공적으로 완료되면 변경 사항을 데이터베이스에 반영(commit)하고, 하나라도 실패하면 모든 변경 사항을 롤백합니다.
따라서 데이터의 일관성을 유지하면서 안전하게 데이터를 변경하거나 삭제할 수 있습니다.

@Modifying

@Modifying 어노테이션은 JPA 쿼리 메소드가 데이터를 수정(업데이트 또는 삭제)하는 작업을 수행함을 나타냅니다.
기본적으로 스프링 데이터 JPA의 쿼리 메소드는 데이터를 조회하는 데 사용되며, 데이터 변경 작업을 명시적으로 표시하기 위해 @Modifying 어노테이션을 사용합니다.
이 어노테이션을 사용하면 스프링 데이터 JPA가 해당 메소드를 실행할 때 엔티티 관리자(Entity Manager)를 통해 데이터베이스의 상태를 변경하는 쿼리를 실행할 준비가 됩니다.

GlobalExceptionHandler 내 예외 처리

GlobalExceptionHandler는 스프링 프레임워크에서 제공하는 @ControllerAdvice 어노테이션을 사용하여 정의됩니다. 이 클래스 내에서 특정 예외 유형에 대한 핸들러 메서드를 정의할 수 있으며, 각 메서드는 @ExceptionHandler 어노테이션으로 주석이 달립니다.
사용자 정의 예외 처리: 이미 ResourceNotFoundExceptionCustomerAlreadyExistsException과 같은 비즈니스 예외를 처리하는 로직을 포함하고 있습니다.
전역 예외 처리: 모든 종류의 예외를 처리하기 위해 Exception.class를 인자로 받는 @ExceptionHandler 메서드를 추가합니다. 이는 체크 예외와 언체크 예외 모두를 포함하는 Java의 Exception 클래스를 나타냅니다.

handleGlobalException 메서드

handleGlobalException 메서드는 모든 예외 유형을 처리하며, API 경로, HTTP 상태 코드(500 Internal Server Error), 오류 메시지, 발생 시간 등의 정보를 포함하는 ErrorResponseDto를 반환합니다.
@ExceptionHandler 어노테이션에 Exception.class를 지정함으로써, 스프링 부트는 특정 예외 유형에 대한 핸들러가 없을 때 이 메서드를 호출하여 예외를 처리합니다.

런타임 예외 테스트

런타임 예외를 의도적으로 발생시켜 예외 처리 로직을 테스트할 수 있습니다. 예를 들어, AccountsController 내의 @Autowired로 주입된 IAccountService 인스턴스가 null일 경우 NullPointerException이 발생하며, 이는 handleGlobalException 메서드에 의해 처리됩니다.

입력 데이터 검증의 필요성

입력 데이터 검증은 클라이언트로부터 받은 데이터가 기대하는 형식과 일치하는지 확인하는 중요한 과정입니다. 예를 들어, 10자리의 전화번호, 올바른 이메일 형식, 이름의 최소 길이 등을 검증할 수 있습니다.
잘못된 데이터를 사전에 거부함으로써 데이터베이스에 불필요한 쿼리를 방지하고 애플리케이션의 안정성을 높일 수 있습니다.

Spring Boot 검증 기능 사용하기

1.
의존성 추가: pom.xmlspring-boot-starter-validation 의존성을 추가하여 Spring Boot의 검증 기능을 사용할 수 있습니다.
2.
검증 어노테이션 사용: @NotEmpty, @Email, @Size, @Pattern 등과 같은 검증 어노테이션을 DTO 클래스의 필드에 적용하여 특정 조건을 충족하는지 검증할 수 있습니다.
예를 들어, @NotEmpty는 필드가 비어있지 않아야 함을, @Email은 필드가 이메일 형식을 따라야 함을 나타냅니다.
@Pattern은 정규 표현식을 사용하여 필드 값이 특정 패턴을 따라야 함을 지정합니다.
3.
Controller 내 검증 적용: @Valid 또는 @Validated 어노테이션을 사용하여 컨트롤러의 메소드 파라미터로 받은 DTO 객체에 대한 검증을 활성화합니다.

전역 예외 처리기 확장

ResponseEntityExceptionHandler 클래스를 확장하여 유효성 검증 실패 시 처리할 로직을 정의합니다.
handleMethodArgumentNotValid 메소드를 오버라이드하여 유효성 검증 실패 시 클라이언트에 반환할 메시지를 커스터마이즈할 수 있습니다.

검증 실패 시 응답 처리

검증 실패 시 ResponseEntity를 사용하여 HTTP 상태 코드(예: 400 Bad Request), 검증 실패 메시지 등을 클라이언트에 전송합니다.
이를 통해 클라이언트는 어떤 입력 데이터가 문제인지 명확하게 인지하고 수정할 수 있습니다.
이 강의에서는 Spring Data JPA의 감사 기능(Auditing)을 사용하여 자동으로 생성 및 수정 시간과 사용자를 관리하는 방법을 다룹니다. 이 기능을 통해 데이터가 생성되거나 수정될 때 그 시점과 해당 작업을 수행한 사용자를 자동으로 데이터베이스 테이블에 기록할 수 있습니다. 이 과정은 데이터의 변경 내역을 추적하고 관리하는 데 매우 유용합니다.

주요 단계 요약:

1.
메타데이터 컬럼 정의: BaseEntity 클래스에 생성 및 수정 시간, 사용자를 위한 메타데이터 컬럼(createdAt, createdBy, updatedAt, updatedBy)을 정의합니다.
2.
감사 어노테이션 적용:
@CreatedDate, @CreatedBy 어노테이션을 생성 시간 및 사용자 필드에 적용합니다.
@LastModifiedDate, @LastModifiedBy 어노테이션을 수정 시간 및 사용자 필드에 적용합니다.
3.
AuditorAware 구현: Spring Data JPA에 현재 사용자 정보를 제공하기 위해 AuditorAware 인터페이스를 구현합니다. 이 예제에서는 ACCOUNTS_MS라는 하드코드된 값을 반환합니다. 실제 애플리케이션에서는 Spring Security 등을 통해 동적으로 현재 사용자 정보를 가져오는 로직을 구현할 수 있습니다.
4.
감사 활성화: 애플리케이션의 메인 클래스에 @EnableJpaAuditing(auditorAwareRef = "auditAwareImpl") 어노테이션을 추가하여 JPA 감사 기능을 활성화하고, AuditorAware 구현체를 지정합니다.
5.
EntityListener 적용: BaseEntity에 @EntityListeners(AuditingEntityListener.class) 어노테이션을 추가하여 감사 기능이 해당 엔티티에 적용되도록 합니다.

실습 결과:

이 설정을 통해, 엔티티가 생성되거나 수정될 때 createdAt, createdBy, updatedAt, updatedBy 필드가 자동으로 관리됩니다. 이는 데이터의 무결성을 보장하고, 데이터 변경 내역을 추적하는 데 도움이 됩니다.

참고 사항:

실제 애플리케이션에서는 현재 사용자 정보를 동적으로 가져오기 위해 Spring Security와 같은 보안 프레임워크와 통합하는 것이 일반적입니다. 이를 통해 사용자의 인증 및 권한 정보를 기반으로 createdByupdatedBy 필드를 적절히 설정할 수 있습니다.

주요 어노테이션과 클래스:

1.
@RestController: 클래스 레벨에서 사용되며, 해당 클래스의 모든 메소드가 HTTP 요청을 처리하고 RESTful 응답을 반환하도록 합니다.
2.
@Controller: @RestController와 유사하지만, Spring MVC의 컨트롤러로 사용될 때 주로 사용됩니다. @ResponseBody와 함께 사용하여 RESTful 응답을 반환할 수 있습니다.
3.
@ResponseBody: 메소드 레벨에서 사용되며, 메소드의 반환값을 HTTP 응답 본문으로 사용하도록 지정합니다.
4.
ResponseEntity: HTTP 응답 본문, 상태 코드, 헤더 등을 포함하는 객체를 반환할 때 사용됩니다. 제네릭을 사용하여 반환 타입을 명시할 수 있습니다.
5.
@ControllerAdvice: 전역 예외 처리를 위해 사용됩니다. 어플리케이션의 모든 컨트롤러에 적용되는 예외 처리 로직을 정의할 수 있습니다.
6.
@ExceptionHandler: @ControllerAdvice 또는 @RestControllerAdvice와 함께 사용되어 특정 예외를 처리하는 메소드를 지정합니다.
7.
@RestControllerAdvice: @ControllerAdvice와 @ResponseBody의 기능을 합친 것으로, 예외 처리 메소드가 JSON 또는 XML과 같은 RESTful 응답을 반환하도록 합니다.
8.
RequestEntity: HTTP 요청의 본문과 헤더 등을 포함하는 객체를 메소드 파라미터로 받을 때 사용됩니다.
9.
@RequestHeader: HTTP 요청 헤더를 메소드의 파라미터로 직접 받고 싶을 때 사용됩니다.
10.
@RequestBody: HTTP 요청 본문을 메소드의 파라미터로 직접 매핑할 때 사용됩니다.

Accounts 마이크로서비스

역할: 사용자의 계정 정보를 관리합니다. 이는 사용자가 은행에 보유하고 있는 다양한 계좌(예: 저축 계좌, 체크 계좌)의 정보를 포함할 수 있습니다.
기능: 계좌 생성, 조회, 업데이트, 삭제 등의 기능을 제공합니다. 사용자가 은행 서비스에 접속하여 자신의 계좌를 관리할 수 있게 해줍니다.

Loans 마이크로서비스

역할: 대출 관련 서비스를 담당합니다. 사용자가 은행으로부터 받은 다양한 대출(예: 주택 대출, 자동차 대출, 개인 대출)의 정보를 관리합니다.
기능: 대출 신청, 대출 상태 조회, 대출 상환 등의 기능을 제공합니다. 사용자는 이 서비스를 통해 자신의 대출 상태를 확인하고 관리할 수 있습니다.
Accounts와의 관계: Loans 서비스는 사용자의 계좌 정보(예: 대출금 입금 계좌)를 Accounts 서비스로부터 가져올 수 있습니다. 대출 상환 등의 금융 활동은 해당 계좌를 통해 이루어질 수 있습니다.

Cards 마이크로서비스

역할: 사용자의 신용카드 및 직불카드 관련 정보를 관리합니다. 카드 발급, 사용 한도, 결제 내역 등의 정보가 포함됩니다.
기능: 카드 발급 신청, 사용 한도 변경, 카드 사용 내역 조회 등의 기능을 제공합니다. 사용자는 자신의 카드를 효율적으로 관리할 수 있습니다.
Accounts와의 관계: 카드 결제나 청구 금액은 사용자의 특정 계좌에서 처리될 수 있으며, 이러한 계좌 정보는 Accounts 서비스를 통해 관리됩니다.

마이크로 서비스의 사이즈 조절

마이크로서비스 크기 결정 및 서비스 경계 식별 방법:

1.
도메인 주도 크기 조정(Domain-Driven Sizing):
비즈니스 도메인과 역량에 밀접하게 연결된 마이크로서비스의 크기와 경계를 정의합니다.
조직 내의 다양한 도메인(예: 계정, 카드, 대출)을 기반으로 마이크로서비스를 구축합니다.
비즈니스 니즈에 따라 마이크로서비스를 조정하며, 도메인 전문가와의 상의를 통해 이루어집니다.
2.
이벤트 스토밍 크기 조정(Event-Storming Sizing):
제품 소유자, 개발자, 테스터, 클라이언트 등 이해관계자 간의 상호작용적인 세션을 통해 진행됩니다.
스티커 노트를 사용하여 가능한 모든 이벤트를 식별하고, 해당 이벤트에 대한 명령과 반응을 정의합니다.
이벤트, 명령, 반응을 도메인별로 분류하여 마이크로서비스의 크기와 경계를 결정합니다.
비즈니스 프로세스를 기반으로 마이크로서비스를 식별하고 구조화하는 데 도움이 됩니다.
이벤트 스토밍은 비교적 빠르고 효과적인 방법으로, 기술적 지식이 없는 이해관계자도 참여할 수 있는 장점이 있습니다. 이 과정을 통해 비즈니스의 모든 측면을 포괄하는 마이크로서비스를 설계할 수 있습니다.

마이크로서비스의 적절한 크기 결정의 중요성:

마이크로서비스의 크기와 경계를 올바르게 결정하는 것은 효율적인 시스템 구축, 유지보수의 용이성, 운영상의 오버헤드 최소화 등에 중요합니다.
너무 크거나 너무 작은 마이크로서비스는 각각 고유의 문제를 야기할 수 있습니다. 적절한 크기 결정은 시스템의 성능과 확장성에 직접적인 영향을 미칩니다.
마이크로서비스의 적절한 크기 결정과 서비스 경계 식별은 복잡한 과정이지만, 이 과정을 통해 강력하고 유연한 마이크로서비스 아키텍처를 구축할 수 있습니다. 이 강의에서 소개된 두 가지 접근 방식을 통해 프로젝트의 요구사항과 조직의 구조에 가장 적합한 전략을 선택할 수 있습니다.

팀 1의 제안:

저축 계좌와 트레이딩 계좌 관련 비즈니스 로직을 하나의 마이크로서비스로 합칩니다.
카드와 대출 관련 제품도 하나의 마이크로서비스로 묶습니다.

팀 2의 제안:

저축 계좌와 트레이딩 계좌를 각각 별도의 마이크로서비스로 분리합니다.
카드와 대출도 각각 별도의 마이크로서비스로 제안합니다.

팀 3의 제안:

저축 계좌와 트레이딩 계좌를 별도로 분리하고, 카드(신용 카드와 직불 카드) 및 대출(주택 대출, 차량 대출, 개인 대출)을 각각 별도의 마이크로서비스로 제안합니다.
각 팀의 제안을 검토한 후, 은행의 CEO 또는 CTO로서 선택해야 합니다. 팀 1의 제안은 카드와 대출, 저축 계좌와 트레이딩 계좌가 너무 밀접하게 연결되어 있어 유연성이 떨어질 수 있습니다. 팀 3의 제안은 마이크로서비스가 너무 많아져 운영상의 오버헤드가 발생할 수 있습니다. 반면, 팀 2의 제안은 각 비즈니스 도메인을 독립적인 마이크로서비스로 구성하여 적절한 수준의 결합도와 유연성을 제공합니다.
마이크로서비스의 크기와 경계를 결정하는 과정은 단순하지 않으며, 조직의 요구사항과 비즈니스 로직에 따라 지속적으로 조정되어야 합니다. 초기에 완벽한 크기를 결정하는 것은 어렵지만, 경험을 통해 지속적으로 개선하고 최적의 서비스 경계를 찾아나가야 합니다. 이 과정은 조직 내에서 다양한 이해관계자와의 긴밀한 협업과 피드백을 통해 이루어집니다.
이 강의에서는 전자상거래 스타트업이 모놀리식 아키텍처에서 마이크로서비스 아키텍처로 이전하는 사례를 통해 마이크로서비스의 적절한 크기 조정이 조직에 어떻게 도움이 되는지를 설명합니다. 처음에는 모놀리식 서버 내에 여러 모듈(예: 인증, 카탈로그, 주문, 인보이스, 판매, 마케팅 등)이 포함되어 있으며, 단일 관계형 데이터베이스를 사용합니다.
시간이 지나면서 이 전자상거래 애플리케이션은 복잡성이 증가하고, 팀이 전체 애플리케이션을 이해하기 어려워지며, 변경 사항을 적용하는 데에 많은 시간이 소요되고, 단일 불안정한 구성 요소가 전체 시스템을 중단시킬 위험이 증가합니다. 이러한 문제를 해결하기 위해 이 전자상거래 스타트업은 모놀리식 아키텍처에서 마이크로서비스 아키텍처로 전환하기로 결정합니다.
기술 팀은 모바일 애플리케이션과 웹 사이트가 REST API를 소비할 수 있도록 아키텍처를 재구성하고, API 게이트웨이를 통해 마이크로서비스(예: 인증, 카탈로그, 주문, 인보이스, 판매, 마케팅 등)에 액세스할 수 있도록 합니다. 각 마이크로서비스는 자체 데이터베이스를 가지며, 다양한 프로그래밍 언어나 프레임워크를 사용할 수 있습니다. 또한, Kafka나 RabbitMQ와 같은 이벤트 버스를 사용하여 이벤트 스트리밍을 구현하여, 비동기적으로 SMS나 이메일을 보낼 수 있습니다.
이 마이크로서비스 아키텍처로 전환함으로써, 전자상거래 스타트업은 각 팀이 자신의 마이크로서비스를 독립적으로 개발하고 배포할 수 있는 유연성을 얻게 되며, 이는 더 빠른 시장 출시 시간과 더 나은 시스템 안정성을 의미합니다. 마이크로서비스의 크기 조정은 조직에 따라 다르며, 시간이 지남에 따라 조정될 수 있습니다. 중요한 것은 각 마이크로서비스가 비즈니스의 필요에 맞게 적절한 크기와 책임을 가지고 있다는 것입니다.

클라우드 네이티브

클라우드 네이티브 애플리케이션의 정의

여러분은 프로젝트나 블로그, 팟캐스트, 유튜브 비디오에서 이 용어를 많이 들어봤을 것입니다. 클라우드 네이티브 애플리케이션은 클라우드 컴퓨팅 원칙을 활용하여 설계 및 개발된 소프트웨어 애플리케이션입니다. 즉, 이 애플리케이션들은 스케일러빌리티, 탄력성, 유연성과 같은 클라우드의 장점을 활용하여 클라우드 환경에서 최적화되어 운영됩니다.
간단히 말해서, 클라우드 네이티브 애플리케이션은 조직이 클라우드 제공업체의 서비스와 기술을 최대한 활용할 수 있도록 클라우드 환경을 위해 구축됩니다.

클라우드 네이티브 컴퓨팅 재단의 공식 정의

클라우드 네이티브 기술은 조직이 공공, 사설 및 하이브리드 클라우드와 같은 현대적인 동적 환경에서 확장 가능한 애플리케이션을 구축하고 운영할 수 있게 해줍니다. 클라우드 환경은 자체 데이터 센터, GCP, Azure 또는 사설 클라우드와 공공 클라우드의 하이브리드 조합일 수 있습니다.

기술

클라우드 네이티브 애플리케이션 구축 시 활용하는 기술에는 컨테이너, 서비스 메시, 마이크로서비스, 불변 인프라 및 선언적 API가 포함됩니다. 이러한 기술은 애플리케이션을 어떤 클라우드에서든 실행할 수 있도록 하며, 특정 클라우드 환경에 종속되지 않습니다.

결론

이 모든 새로운 기술은 견고한 자동화와 함께 클라우드 네이티브 애플리케이션을 통해 엔지니어가 자주, 예측 가능하게, 최소한의 노력으로 큰 영향을 미칠 수 있는 변경을 개발할 수 있도록 합니다. 이는 조직과 개발자가 작은 변경이나 개선을 매우 빠르게 수행할 수 있는 자유를 제공합니다.

클라우드 네이티브 애플리케이션의 주요 특성

1.
마이크로서비스
클라우드 네이티브 애플리케이션의 가장 중요한 특성 중 하나는 마이크로서비스를 기반으로 한다는 것입니다. 마이크로서비스는 서로 느슨하게 결합되어 있고 작은 단위로 구성되어, 개발과 배포, 확장을 독립적으로 수행할 수 있는 유연성을 제공합니다.
2.
컨테이너화
비즈니스 로직을 분리한 후, 도커나 다른 컨테이너화 소프트웨어를 사용하여 애플리케이션을 컨테이너화합니다. 컨테이너는 애플리케이션을 실행하기 위한 가벼우면서 일관된 환경을 제공하며, 다양한 클라우드 플랫폼과 인프라에서의 높은 이식성을 가능하게 합니다.
3.
확장성 및 탄력성
마이크로서비스와 컨테이너의 도움으로 애플리케이션은 수평적으로 쉽게 확장될 수 있습니다. 이는 애플리케이션으로 향하는 어떤 종류의 트래픽도 처리할 수 있게 하며, 쿠버네티스와 같은 컨테이너 오케스트레이션 플랫폼을 사용하여 서비스 인스턴스를 쉽고 자동으로 추가할 수 있습니다.
4.
DevOps 관행
클라우드 네이티브 애플리케이션은 개발과 운영 팀 간의 협력 문화를 촉진하면서 DevOps 원칙을 채택합니다. 이러한 관행을 통해 연속적인 통합, 연속적인 배포 및 자동화된 배포 파이프라인이 소프트웨어 개발 및 배포 과정을 간소화합니다.
5.
회복력 및 내고장성
클라우드 네이티브 원칙을 활용하여 개발된 애플리케이션은 어떠한 실패에도 견딜 수 있어 회복력이 있으며, 분산 아키텍처, 부하 분산 및 자동 실패 복구 기술을 사용하여 높은 가용성과 내고장성을 보장합니다.
6.
클라우드 네이티브 서비스 활용
클라우드 네이티브 애플리케이션은 클라우드 환경을 최대한 활용하여 개발됩니다. 조직이나 애플리케이션은 이러한 클라우드 네이티브 서비스를 사용함으로써 인프라에 대한 관심을 덜어내고 애플리케이션 로직 및 비즈니스 로직의 향상에 더 집중할 수 있습니다.

클라우드 네이티브 애플리케이션과 전통적인 애플리케이션의 주요 차이점

1.
예측 가능한 행동
클라우드 네이티브 애플리케이션은 예측 가능한 행동을 보여줍니다. 예를 들어, 마이크로서비스 환경에서 문제가 발생하면, 비즈니스 로직이 여러 마이크로서비스로 느슨하게 결합되어 분리되어 있기 때문에 예외가 발생한 위치를 쉽게 추적할 수 있습니다. 반면, 전통적인 모놀리식 애플리케이션에서는 모든 비즈니스 로직이 함께 묶여 있어 예외 발생 위치를 알기 어렵습니다.
2.
운영 체제 독립성
클라우드 네이티브 애플리케이션은 운영 체제에 종속되지 않습니다. 도커 컨테이너와 이미지를 사용하여 운영 체제를 추상화하기 때문에 어떤 운영 체제에서도 작동할 수 있습니다. 반면, 전통적인 엔터프라이즈 애플리케이션은 특정 운영 체제에 의존합니다.
3.
적절한 크기 조정
클라우드 네이티브 애플리케이션은 적절한 크기와 용량으로 독립적으로 작동합니다. 전통적인 애플리케이션은 비즈니스 로직이 단일 애플리케이션 또는 코드베이스 내에 모두 포함되어 있어 과도한 용량이 될 수 있습니다.
4.
지속적인 배포 지원
클라우드 네이티브 애플리케이션은 DevOps 원칙과 자동화를 활용하여 지속적인 배포를 지원합니다. 반면, 전통적인 엔터프라이즈 애플리케이션은 워터폴 개발을 따르며 애자일 방식을 지원하지 않습니다.
5.
빠른 회복 및 자동 확장
클라우드 네이티브 애플리케이션은 예를 들어, 마이크로서비스 인스턴스가 제대로 작동하지 않을 경우, 쿠버네티스가 자동으로 새 인스턴스를 생성하고 자동으로 회복을 시도합니다. 또한 트래픽에 따라 애플리케이션을 자동으로 확장할 수 있습니다. 반면, 전통적인 애플리케이션은 도커 컨테이너를 사용하지 않기 때문에 이러한 플랫폼의 지원을 받을 수 없어 회복이 느리고 자동화된 회복 및 확장이 불가능합니다.

15가지 클라우드 애플리케이션 요소

첫 번째 원칙은 "하나의 애플리케이션에 하나의 코드 베이스"입니다. 이 원칙에 따르면, 각 애플리케이션 또는 마이크로서비스는 자체 전용 코드 베이스를 가져야 합니다. 예를 들어, 이 강좌에서 세 개의 다른 마이크로서비스를 구축하지만 실제 세계에서는 각 마이크로서비스가 자신의 GitHub 저장소 또는 버전 관리 시스템 내의 자체 코드 베이스를 가져야 합니다. 공통 코드가 있는 경우 별도로 관리되어야 합니다.
두 번째 원칙은 "API 우선 접근"입니다. 클라우드 네이티브 가이드라인에서도 API 우선을 추천하며, 이는 클라우드 네이티브 애플리케이션의 설계부터 API를 통해 가능한 많은 로직을 작성해야 함을 의미합니다. 이 접근 방식은 다른 API나 마이크로서비스가 백엔드 서비스로서 비즈니스 로직을 호출할 수 있는 유연성을 제공합니다.
세 번째 원칙은 "의존성 관리"입니다. 의존성은 명시적으로 선언되어야 하며, 단일 매니페스트 파일에 모든 의존성이 표시되어야 합니다. 예를 들어 자바 애플리케이션에서는 Maven이나 Gradle 같은 도구가 의존성을 중앙 저장소에서 가져오도록 관리합니다. 이는 패키징 과정에서 모든 의존성 라이브러리가 단일 아티팩트로 패키지되도록 합니다.
네 번째 원칙은 "설계, 구축, 출시, 실행"입니다. 이 원칙에 따르면, 코드 베이스는 설계에서 생산에 이르기까지 다양한 단계를 거쳐야 합니다. 각 단계는 엄격하게 분리되어야 하며, 빌드 단계가 완료된 후에는 런타임 코드 수정이 허용되지 않습니다.
다섯 번째 원칙은 "구성, 자격 증명 및 코드"입니다. 이 원칙에 따르면, 환경 간에 변경될 수 있는 모든 구성 요소는 코드 베이스와 분리되어야 하며, 배포 단계에서 특정 환경에 관련된 구성을 주입할 수 있어야 합니다. 예를 들어, 데이터베이스 자격 증명이나 서버 관련 속성과 같은 생산 환경 관련 구성은 불변의 출시 구성 요소와 결합되어야 하며, 이는 고유 식별자와 함께 중앙 저장소에 저장되어야 합니다.
6 전통적인 단일체 애플리케이션에서는 로그를 서버의 파일 및 폴더 위치에 기록합니다. 하지만 이와 같은 방식은 마이크로서비스나 클라우드 네이티브 애플리케이션에서는 효과적이지 않습니다. 왜냐하면 수백 개의 서로 다른 마이크로서비스에서 로그를 각기 다른 서버나 위치에 기록할 경우, 문제를 진단하기 위해 모든 로그 위치를 검색해야 하기 때문입니다.
따라서 15요소 방법론에 따르면, 애플리케이션은 로그를 로그 폴더나 위치에 기록하는 대신 표준 출력으로 리디렉션하여 시간에 따라 순차적으로 정렬된 이벤트로 처리하는 것이 좋습니다. 로그 저장과 관리는 외부 도구인 로그 집계기(log aggregator)에 의해 수행됩니다. 이 도구는 로그를 검색하고 수집하여 디버깅 목적으로 접근을 제공합니다.
이 강좌에서는 로그 집계 도구를 사용하여 모든 마이크로서비스에서 로그를 수집하고 단일 UI 로그 집계 도구에서 모든 마이크로서비스의 로그를 검색하는 방법을 배웁니다.
7 다음으로 '일회용성' 원칙을 살펴봅니다. 클라우드 환경이나 마이크로서비스에서는 단일체 애플리케이션이 항상 실행되어야 하는 전통적인 필요성과는 달리, 여러 인스턴스가 실행되고 있기 때문에 특정 마이크로서비스가 응답하지 않을 경우 쿠버네티스 같은 플랫폼을 통해 자동으로 새 인스턴스로 교체할 수 있습니다. 이는 고가용성과 탄력성을 보장하는 데 중요합니다.
8 이어서 '백엔드 서비스' 원칙입니다. 마이크로서비스는 데이터베이스, SMTP 서버, FTP 서버, 캐싱 시스템, 메시지 브로커와 같은 다양한 외부 자원에 의존할 수 있습니다. 이러한 자원은 애플리케이션 코드 변경 없이 수정하거나 교체할 수 있도록 '연결된 자원'으로 처리해야 합니다.
9 마지막으로 '환경 일치' 원칙입니다. 애플리케이션의 다양한 환경 간 차이를 최소화하고 비용이 많이 드는 단축 방법을 피하는 것이 좋습니다. 이 원칙은 코드 변경이 프로덕션 배포로 이어지는 시간을 줄이고, 개발자와 운영자 간의 협력을 촉진하며, 모든 환경에서 동일한 도구와 서비스를 사용하여 환경 간 일관성을 유지하는 데 중점을 둡니다.
10 번째 원칙은 포트 바인딩입니다. 클라우드 네이티브 애플리케이션은 자체적으로 완결되어야 하며 포트 바인딩을 통해 서비스를 제공해야 합니다. 예를 들어, 전통적인 Java 웹 애플리케이션은 톰캣(Tomcat)과 같은 서버 컨테이너 내에서 실행되지만, 클라우드 네이티브 애플리케이션은 이러한 외부 서버에 의존하지 않고 내장된 서버를 사용합니다. 이를 통해 각 애플리케이션은 독립적으로 자신의 포트를 통해 서비스를 외부에 노출할 수 있습니다.
11 번째 원칙은 **무상태 프로세스(Stateless Process)**입니다. 클라우드 네이티브 애플리케이션은 높은 확장성을 염두에 두고 무상태로 설계되어야 합니다. 이는 각 인스턴스가 상태 정보를 공유하지 않고 독립적으로 작동해야 함을 의미합니다. 필요한 데이터는 외부 데이터 스토어(예: 데이터베이스, Redis 캐시)에 저장하여 애플리케이션이 무상태를 유지할 수 있도록 합니다.
12 번째 원칙은 **동시성(Concurrency)**입니다. 확장성을 달성하기 위해 애플리케이션은 동시에 여러 사용자의 요청을 처리할 수 있어야 합니다. 이를 위해 애플리케이션은 동시 처리를 지원하고, 필요에 따라 프로세스를 수평적으로 확장하여 다양한 머신에서 작업을 분산시킬 수 있어야 합니다.
13 번째 원칙은 **텔레메트리(Telemetry)**입니다. 클라우드 네이티브 애플리케이션은 다수의 컨테이너와 서비스가 실행되는 환경에서 효과적인 모니터링을 가능하게 하는 관측 가능성을 갖추어야 합니다. 이는 로그, 메트릭스, 추적, 상태 확인 및 이벤트 데이터를 포함한 다양한 텔레메트리 데이터를 수집하여 시스템의 행동을 원격으로 모니터링하고 관리하는 데 필수적입니다.
14 **인증 및 권한 부여(Authentication and Authorization)**입니다. 모든 통신과 상호작용이 보안 표준을 준수하면서 이루어져야 합니다. 개발자는 사용자의 신원을 확인(인증)하고, 필요한 권한이 있는지를 판단(권한 부여)하는 데 필요한 시스템을 구현해야 합니다. 이는 클라우드 네이티브 애플리케이션과 마이크로서비스의 보안을 강화하는 데 중요한 역할을 합니다.