1. 개요

이 사용방법(예제)에서는 12 단계 앱 방법론을 이해 합니다 .

또한 Spring Boot의 도움으로 마이크로 서비스를 개발하는 방법도 이해할 것입니다. 이 과정에서 이러한 마이크로 서비스를 개발하기 위해 12 단계 방법론을 적용하는 방법을 살펴 보겠습니다.

2. 12 단계 방법론이란 무엇입니까?

12 단계 방법론은 서비스로 실행되도록 개발 된 애플리케이션을 개발하기위한 12 가지 모범 사례의 집합입니다 . 이것은 원래 Heroku가 2011 년에 클라우드 플랫폼에 서비스로 배포 된 애플리케이션을 위해 초안 한 것입니다. 시간이 지남에 따라 이것은 모든 SaaS (Software -as-a- Service) 개발에 충분히 일반적임이 입증되었습니다 .

그렇다면 SaaS (Software-as-a-Service) 란 무엇을 의미할까요? 전통적으로 우리는 소프트웨어 솔루션을 설계, 개발, 배포 및 유지하여 비즈니스 가치를 창출합니다. 그러나 반드시 동일한 결과를 얻기 위해이 프로세스에 참여할 필요는 없습니다. 예를 들어, 적용 가능한 세금을 계산하는 것은 많은 영역에서 일반적인 기능입니다.

이제이 서비스를 직접 구축하고 관리하거나 상용 서비스 제공에 가입 할 수 있습니다. 이러한 서비스 제공은 우리가 서비스로서의 소프트웨어라고 알려진 것 입니다.

SaaS (Software-as-a-Service)는 개발 된 아키텍처에 제한을 두지 않습니다. 몇 가지 모범 사례를 채택하는 것은 매우 유용합니다.

현대 클라우드 플랫폼에서 모듈 식, 이식 가능 및 확장 가능하도록 소프트웨어를 설계하면 서비스 제공에 상당히 적합합니다. 이것이 12 단계 방법론이 도움이되는 부분입니다. 사용방법(예제)의 뒷부분에서 작동 방식을 살펴 보겠습니다.

3. Spring Boot를 사용하는 마이크로 서비스

마이크로 서비스 는 소프트웨어를 느슨하게 결합 된 서비스로 개발하기위한 아키텍처 스타일입니다. 여기서 핵심 요구 사항은 서비스가 비즈니스 도메인 경계를 중심으로 구성되어야한다는 것 입니다. 이것은 종종 식별하기 가장 어려운 부분입니다.

또한 여기의 서비스는 데이터에 대한 유일한 권한을 가지며 작업을 다른 서비스에 노출합니다. 서비스 간의 통신은 일반적으로 HTTP와 같은 경량 프로토콜을 통해 이루어집니다. 그 결과 독립적으로 배포 및 확장 가능한 서비스가 제공됩니다.

이제 마이크로 서비스 아키텍처와 SaaS (Software-as-a-Service)는 서로 의존하지 않습니다. 그러나 SaaS (Software-as-a-Service)를 개발할마이크로 서비스 아키텍처를 활용하는 것이 매우 유익 하다는 것을 이해하는 것은 어렵지 않습니다 . 모듈화 및 확장 성과 같이 앞서 논의한 많은 목표를 달성하는 데 도움이됩니다.

Spring Boot 는 엔터프라이즈 애플리케이션 개발과 관련된 많은 상용구를 제거하는 Spring 기반 애플리케이션 프레임 워크입니다. 마이크로 서비스를 개발할 수있는 매우 신중하지만 유연한 플랫폼을 제공합니다. 이 사용방법(예제)에서는 Spring Boot를 활용하여 12 단계 방법론을 사용하여 마이크로 서비스를 제공합니다.

4. 12 단계 방법론 적용

이제 방금 논의한 도구와 사례를 사용하여 개발할 간단한 애플리케이션을 정의하겠습니다. 우리는 모두 영화를 보는 것을 좋아하지만 이미 본 영화를 추적하는 것은 어렵습니다.

이제 누가 영화를 시작하고 나중에 포기할까요? 우리에게 필요한 것은 우리가 본 영화를 녹화하고 쿼리하는 간단한 서비스입니다.

이것은 데이터 저장소와 REST 엔드 포인트가있는 매우 간단하고 표준적인 마이크로 서비스입니다. 지속성에도 매핑 할 모델을 정의해야합니다.

@Entity
public class Movie {
    @Id
    private Long id;
    private String title;
    private String year;
    private String rating;
    // getters and setters
}

우리는 ID와 몇 가지 다른 속성으로 JPA 엔티티를 정의했습니다. 이제 REST 컨트롤러의 모습을 살펴 보겠습니다.

@RestController
public class MovieController {
 
    @Autowired
    private MovieRepository movieRepository;
    @GetMapping("/movies")
    public List<Movie> retrieveAllStudents() {
        return movieRepository.findAll();
    }

    @GetMapping("/movies/{id}")
    public Movie retrieveStudent(@PathVariable Long id) {
        return movieRepository.findById(id).get();
    }

    @PostMapping("/movies")
    public Long createStudent(@RequestBody Movie movie) {
        return movieRepository.save(movie).getId();
    }
}

이것은 우리의 간단한 서비스의 기초를 다룹니다. 다음 하위 섹션에서 12 단계 방법론을 구현하는 방법을 논의하면서 나머지 애플리케이션을 살펴 보겠습니다.

4.1. 코드베이스

12 단계 앱의 첫 번째 모범 사례는 버전 제어 시스템에서 추적하는 것입니다. Git 은 오늘날 가장 많이 사용되는 버전 제어 시스템이며 거의 유비쿼터스입니다. 원칙 은 앱이 단일 코드 저장소에서 추적되어야하며 해당 저장소를 다른 앱과 공유해서는 안된다는 것 입니다.

Spring Boot는 명령 줄 도구 및 웹 인터페이스를 포함하여 애플리케이션을 부트 스트랩하는 여러 가지 편리한 방법을 제공합니다 . 부트 스트랩 애플리케이션을 생성하면이를 git 저장소로 변환 할 수 있습니다.

git init

이 명령은 응용 프로그램의 루트에서 실행해야합니다. 이 단계의 애플리케이션에는 생성 된 파일이 버전 제어되는 것을 효과적으로 제한하는 .gitignore 파일이 이미 포함되어 있습니다. 따라서 바로 초기 커밋을 만들 수 있습니다.

git add .
git commit -m "Adding the bootstrap of the application."

마지막으로 원격을 추가하고 원하는 경우 커밋을 원격으로 푸시 할 수 있습니다 (엄격한 요구 사항은 아닙니다).

git remote add origin https://github.com/<username>/12-factor-app.git
git push -u origin master

4.2. 의존성

다음으로, 12 단계 앱은 항상 모든 의존성을 명시 적으로 선언해야합니다 . 의존성 선언 매니페스트를 사용하여이를 수행해야합니다. Java에는 Maven 및 Gradle과 같은 여러 의존성 관리 도구가 있습니다. 이 목표를 달성하기 위해 그중 하나를 사용할 수 있습니다.

따라서 간단한 애플리케이션은 REST API를 용이하게하고 데이터베이스에 연결하는 라이브러리와 같은 몇 가지 외부 라이브러리에 의존합니다. Maven을 사용하여 선언적으로 정의하는 방법을 살펴 보겠습니다.

Maven에서는 일반적으로 POM ( Project Object Model) 으로 알려진 XML 파일에서 프로젝트의 의존성을 설명해야합니다 .

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

단순하고 단순 해 보이지만 이러한 의존성에는 일반적으로 다른 전이 의존성이 있습니다. 이것은 어느 정도 복잡해 지지만 우리의 목표를 달성하는 데 도움이됩니다. 이제 우리 애플리케이션에는 명시 적으로 설명되지 않은 직접적인 의존성이 없습니다.

4.3. 구성

응용 프로그램에는 일반적으로 많은 구성이 있으며, 그중 일부는 배포마다 다를 수 있지만 나머지는 동일하게 유지됩니다.

이 예에서는 영구 데이터베이스가 있습니다. 연결할 데이터베이스의 주소와 자격 증명이 필요합니다. 이는 배포간에 변경 될 가능성이 가장 큽니다.

12 단계 앱은 배포마다 다른 모든 구성을 외부화해야합니다 . 여기서 권장 사항은 이러한 구성에 환경 변수를 사용하는 것입니다. 이로 인해 구성과 코드가 완전히 분리됩니다.

Spring은 이러한 구성을 선언하고 환경 변수에 첨부 할 수있는 구성 파일을 제공합니다.

spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/movies
spring.datasource.username=${MYSQL_USER}
spring.datasource.password=${MYSQL_PASSWORD}

여기에서 데이터베이스 URL과 자격 증명을 구성으로 정의하고 환경 변수에서 선택할 실제 값을 매핑했습니다.

Windows에서는 애플리케이션을 시작하기 전에 환경 변수를 설정할 수 있습니다.

set MYSQL_HOST=localhost
set MYSQL_PORT=3306
set MYSQL_USER=movies
set MYSQL_PASSWORD=password

Ansible 또는 Chef 와 같은 구성 관리 도구를 사용 하여이 프로세스를 자동화 할 수 있습니다.

4.4. 지원 서비스

백업 서비스는 애플리케이션이 작동에 의존하는 서비스입니다. 예를 들어 데이터베이스 또는 메시지 브로커. 12 단계 앱은 이러한 모든 지원 서비스를 연결된 리소스로 취급해야합니다. 이것이 효과적으로 의미하는 것은 호환되는 지원 서비스를 교체하기 위해 코드를 변경할 필요가 없다는 것입니다. 유일한 변경은 구성이어야합니다.

우리 애플리케이션에서는 MySQL 을 백업 서비스로 사용하여 지속성을 제공했습니다.

Spring JPA 는 코드가 실제 데이터베이스 공급자에 대해 매우 독립적입니다. 모든 표준 작업을 제공하는 저장소 만 정의하면됩니다.

@Repository
public interface MovieRepository extends JpaRepository<Movie, Long> {
}

보시다시피 이것은 MySQL에 직접 의존하지 않습니다. Spring은 클래스 경로에서 MySQL 드라이버를 감지하고이 인터페이스의 MySQL 전용 구현을 동적으로 제공합니다. 또한 구성에서 다른 세부 정보를 직접 가져옵니다.

따라서 MySQL에서 Oracle로 변경해야하는 경우 의존성에서 드라이버를 교체하고 구성을 교체하기 만하면됩니다.

4.5. 빌드, 릴리스 및 실행

12 단계 방법론 은 코드베이스를 실행중인 애플리케이션 으로 변환하는 프로세스 를 세 단계로 엄격하게 분리합니다 .

  • 빌드 단계 : 여기에서 코드베이스를 가져 와서 정적 및 동적 검사를 수행 한 다음 JAR과 같은 실행 가능한 번들을 생성합니다. Maven 과 같은 도구를 사용하면 매우 간단합니다.
     mvn clean compile test package
  • 릴리스 단계 : 실행 가능한 번들을 가져와 올바른 구성과 결합하는 단계입니다. 여기에서 Ansible 과 같은 프로비저닝 도구와 함께 Packer사용 하여 Docker 이미지를 만들 수 있습니다.
     packer build application.json
  • 실행 단계 : 마지막으로 대상 실행 환경에서 애플리케이션을 실행하는 단계입니다. Docker 를 컨테이너로 사용 하여 애플리케이션을 출시하면 애플리케이션 실행이 간단 할 수 있습니다.
     docker run --name <container_id> -it <image_id>

마지막으로 이러한 단계를 수동으로 수행 할 필요는 없습니다. Jenkins 가 선언적 파이프 라인으로 매우 편리하게 사용 되는 곳 입니다.

4.6. 프로세스

12 단계 앱은 실행 환경에서 상태 비 저장 프로세스로 실행될 것으로 예상됩니다. 즉, 요청간에 영구 상태를 로컬로 저장할 수 없습니다. 하나 이상의 상태 기반 백업 서비스에 저장해야하는 영구 데이터를 생성 할 수 있습니다.

예제의 경우 여러 엔드 포인트가 노출되었습니다. 이러한 엔드 포인트에 대한 요청은 이전 요청과 완전히 독립적입니다. 예를 들어 메모리 내에서 사용자 요청을 추적하고 해당 정보를 사용하여 향후 요청을 처리하는 경우 12 단계 앱을 위반합니다.

따라서 12 단계 앱은 고정 세션과 같은 제한을 두지 않습니다. 따라서 이러한 앱은 이식성이 뛰어나고 확장 가능합니다. 자동화 된 확장을 제공하는 클라우드 실행 환경에서는 애플리케이션에서 상당히 바람직한 동작입니다.

4.7. 포트 바인딩

Java의 기존 웹 애플리케이션은 WAR 또는 웹 아카이브로 개발됩니다. 이것은 일반적으로 의존성이있는 서블릿 모음이며 Tomcat과 같은 준수 컨테이너 런타임이 필요합니다. 반대로 12 단계 앱은 이러한 런타임 의존성을 기대하지 않습니다. 완전히 독립적이며 Java와 같은 실행 런타임 만 필요합니다.

우리의 경우 Spring Boot를 사용하여 애플리케이션을 개발했습니다. 다른 많은 이점과는 별도로 Spring Boot는 기본 임베디드 애플리케이션 서버를 제공합니다. 따라서 Maven을 사용하여 이전에 생성 한 JAR은 호환되는 Java 런타임 만 있으면 모든 환경에서 완전히 실행할 수 있습니다.

java -jar application.jar

여기서 간단한 애플리케이션은 HTTP 바인딩을 통해 8080과 같은 특정 포트에 대한 엔드 포인트를 노출합니다. 위에서 한 것처럼 애플리케이션을 시작하면 HTTP와 같은 내 보낸 서비스에 액세스 할 수 있습니다.

애플리케이션은 여러 포트에 바인딩하여 FTP 또는 WebSocket 과 같은 여러 서비스를 내보낼 수 있습니다 .

4.8. 동시성

Java는 애플리케이션에서 동시성을 처리하기위한 클래식 모델로 Thread제공 합니다. 스레드는 경량 프로세스와 같으며 프로그램에서 여러 실행 경로를 나타냅니다. 스레드는 강력하지만 애플리케이션 확장에 얼마나 도움이 될 수 있는지에 대한 제한이 있습니다.

12 단계 방법론은 앱이 확장을 위해 프로세스에 의존하도록 제안합니다. 이것이 효과적으로 의미하는 것은 애플리케이션이 여러 프로세스에 워크로드를 분산하도록 설계되어야한다는 것입니다. 그러나 개별 프로세스는 내부적으로 Thread 와 같은 동시성 모델을 자유롭게 활용할 수 있습니다.

Java 응용 프로그램이 시작되면 기본 JVM에 바인딩 된 단일 프로세스를 가져옵니다. 우리가 효과적으로 필요로하는 것은 애플리케이션의 여러 인스턴스를 지능적으로로드 분산하여 실행하는 방법입니다. 이미 애플리케이션을 Docker 컨테이너 로 패키징했기 때문에 Kubernetes 는 이러한 오케스트레이션을위한 자연스러운 선택입니다.

4.9. 일회용

응용 프로그램 프로세스는 의도적으로 또는 예기치 않은 이벤트를 통해 종료 될 수 있습니다. 두 경우 모두 12 단계 앱이이를 정상적으로 처리해야합니다 . 즉, 신청 프로세스는 원치 않는 부작용없이 완전히 일회용이어야합니다. 또한 프로세스는 빠르게 시작되어야합니다.

예를 들어, 애플리케이션에서 엔드 포인트 중 하나는 영화에 대한 새 데이터베이스 레코드를 만드는 것입니다. 이제 이러한 요청을 처리하는 응용 프로그램이 예기치 않게 충돌 할 수 있습니다. 그러나 이것은 응용 프로그램의 상태에 영향을주지 않습니다. 클라이언트가 동일한 요청을 다시 보낼 때 중복 레코드가 발생해서는 안됩니다.

요약하면 애플리케이션은 멱등 서비스를 노출해야 합니다. 이것은 클라우드 배포를위한 서비스의 또 다른 매우 바람직한 속성입니다. 이를 통해 다른 고려 사항없이 언제든지 새로운 서비스를 중지, 이동 또는 스핀 할 수있는 유연성을 제공합니다.

4.10. Dev / Prod 패리티

애플리케이션은 로컬 머신에서 개발하고 다른 환경에서 테스트 한 후 최종적으로 프로덕션에 배포하는 것이 일반적입니다. 이러한 환경이 다른 경우가 종종 있습니다. 예를 들어 개발 팀은 Windows 시스템에서 작업하는 반면 프로덕션 배포는 Linux 시스템에서 발생합니다.

12 단계 방법론은 개발 환경과 프로덕션 환경 사이의 간격을 최대한 최소화 할 것을 제안합니다. 이러한 격차는 긴 개발주기, 관련 팀 또는 사용중인 다른 기술 스택으로 인해 발생할 수 있습니다.

이제 Spring Boot 및 Docker와 같은 기술은 자동으로이 격차를 크게 해소합니다. 컨테이너화 된 애플리케이션은 실행 위치에 관계없이 동일하게 작동 할 것으로 예상됩니다. 데이터베이스와 같은 동일한 백업 서비스를 사용해야합니다.

또한 이러한 격차를 더욱 효과적으로 해소 할 수있는 지속적인 통합 및 제공과 같은 올바른 프로세스가 있어야합니다.

4.11. 로그

로그는 애플리케이션이 수명 동안 생성하는 필수 데이터입니다. 응용 프로그램 작동에 대한 귀중한 통찰력을 제공합니다. 일반적으로 응용 프로그램은 다양한 세부 정보를 사용하여 여러 수준에서 로그를 생성하고 여러 형식으로 ii를 출력 할 수 있습니다.

그러나 12 단계 앱은 로그 생성 및 처리와 분리됩니다. 이러한 앱의 경우 로그는 시간순 이벤트 스트림 일뿐입니다. 단순히 이러한 이벤트를 실행 환경의 표준 출력에 기록합니다. 이러한 스트림의 캡처, 저장, 큐 레이션 및 보관은 실행 환경에서 처리해야합니다.

이 목적을 위해 우리가 사용할 수있는 몇 가지 도구가 있습니다. 우선 SLF4J사용 하여 애플리케이션 내에서 로깅을 추상적으로 처리 할 수 있습니다 . 또한 Fluentd 와 같은 도구를 사용하여 애플리케이션 및 백업 서비스에서 로그 스트림을 수집 할 수 있습니다 .

이를 Elasticsearch에 입력 하여 저장 및 인덱싱 할 수 있습니다 . 마지막으로 Kibana 에서 시각화를위한 의미있는 대시 보드를 생성 할 수 있습니다 .

4.12. 관리 프로세스

종종 우리는 응용 프로그램 상태로 일회성 작업이나 일상적인 절차를 수행해야합니다. 예를 들어, 불량 레코드 수정. 이제이를 달성 할 수있는 다양한 방법이 있습니다. 자주 필요하지 않을 수 있으므로 다른 환경과 별도로 실행하는 작은 스크립트를 작성할 수 있습니다.

이제 12 단계 방법론은 이러한 관리 스크립트를 애플리케이션 코드베이스와 함께 유지하도록 강력히 제안 합니다. 그렇게함으로써 우리가 메인 애플리케이션 코드베이스에 적용하는 것과 동일한 원칙을 따라야합니다. 또한 프로덕션 서버에서 이러한 스크립트를 실행하려면 실행 환경의 기본 제공 REPL 도구를 사용하는 것이 좋습니다.

이 예에서 지금까지 이미 본 영화로 애플리케이션을 어떻게 시드합니까? 우리는 우리의 작은 끝점을 사용할 수 있지만 그것은 비현실적으로 보일 수 있습니다. 우리에게 필요한 것은 일회성로드를 수행하는 스크립트입니다. 작은 Java 함수를 작성하여 파일에서 영화 List을 읽고 데이터베이스에 배치로 저장할 수 있습니다.

또한 Java 런타임 과 통합 된 Groovy 를 사용 하여 이러한 프로세스를 시작할 수 있습니다.

5. 실용적인 응용

이제 우리는 12 단계 방법론이 제시하는 모든 요인을 살펴 보았습니다. 애플리케이션을 12 단계 앱 으로 개발하는 것은 확실히 이점이 있습니다. 특히 클라우드에서 서비스로 배포하려는 경우 더욱 그렇습니다 . 그러나 다른 모든 지침, 프레임 워크, 패턴과 마찬가지로 우리는 이건 은색 총알입니까?

솔직히, 소프트웨어 설계 및 개발의 단일 방법론이 은색 총알이라고 주장하는 것은 없습니다. 12 단계 방법론도 예외는 아닙니다. 하지만 이러한 요소 중 일부는 매우 직관적 , 그리고 대부분 우리가 이미하고있어, 다른 사람들이 우리에게 적용되지 않을 수도 있습니다 . 목표를 배경으로 이러한 요소를 평가하고 현명하게 선택하는 것이 중요합니다.

이러한 모든 요소 는 모듈 식, 독립성, 이식성, 확장 성 및 관찰 가능한 애플리케이션을 개발하는 데 도움 이된다는 점에 유의해야합니다 . 응용 프로그램에 따라 다른 방법을 통해 더 잘 달성 할 수 있습니다. 또한 모든 요소를 ​​함께 채택 할 필요는 없습니다. 이러한 요소 중 일부를 채택하면 우리보다 더 나아질 수 있습니다.

마지막으로 이러한 요소는 매우 간단하고 우아합니다. 애플리케이션이 사실상 다운 타임과 장애없이 더 높은 처리량과 더 낮은 지연 시간을 갖도록 요구하는 시대에 더 중요합니다. 이러한 요소를 채택하면 처음부터 올바른 시작을 할 수 있습니다. 마이크로 서비스 아키텍처 및 애플리케이션 컨테이너화와 결합하면 적절한 위치에있는 것 같습니다.

6. 결론

이 사용방법(예제)에서는 12 단계 방법론의 개념을 살펴 보았습니다. 마이크로 서비스 아키텍처를 Spring Boot와 함께 활용하여 효과적으로 제공하는 방법에 대해 논의했습니다. 또한 각 요소를 자세히 살펴보고이를 애플리케이션에 적용하는 방법을 살펴 보았습니다. 또한 이러한 개별 요소를 효과적인 방식으로 성공적으로 적용하기위한 몇 가지 도구를 탐색했습니다.