Google Cloud에서의 Twelve-Factor App 개발

Last reviewed 2023-09-14 UTC

이 문서에서는 널리 사용되는 Twelve-Factor 앱 방법론과 Google Cloud에서 실행되는 앱을 개발할 때 이 방법론을 적용하는 방법을 설명합니다. 이 방법론을 사용할 경우 확장성과 복원력이 우수한 앱을 가장 빠르게 지속적으로 배포할 수 있습니다.

이 문서는 Google Cloud, 버전 제어, 지속적 통합, 컨테이너 기술에 익숙한 개발자를 대상으로 합니다.

소개

개발자들은 앱을 클라우드로 이전하며 그 과정에서 클라우드 기반 앱의 설계 및 배포와 관련된 경험을 쌓게 됩니다. 이러한 경험을 바탕으로 일반적으로 Twelve-Factor로 알려져 있는 일련의 권장사항이 제시되었습니다. 이러한 요소를 염두에 두고 앱을 설계하면 새 리소스를 프로비저닝하는 데 시간이 오래 걸리는 온프레미스 환경에 앱을 배포할 때와 비교하여 이식성과 복원력이 더욱 우수한 앱을 클라우드에 배포할 수 있습니다.

하지만 최신 클라우드 기반 앱을 설계하려면 온프레미스 환경용 앱을 설계할 때와 비교하여 소프트웨어 엔지니어링, 구성, 배포에 대한 관점을 바꿔야 합니다. 이 문서는 Twelve-Factor를 앱 설계에 적용하는 방법을 이해할 수 있도록 지원합니다.

Twelve Factor 앱의 이점

Twelve-Factor 설계를 활용하면 앱 구성요소를 분리할 수 있으므로 각 구성요소를 쉽게 바꾸거나 원활하게 확장 또는 축소할 수 있습니다. 이러한 요소는 모든 프로그래밍 언어 또는 소프트웨어 스택과는 별개이므로 Twelve-Factor 설계를 다양한 앱에 적용할 수 있습니다.

Twelve-Factor

1. 코드베이스

Git 또는 Mercurial과 같은 버전 제어 시스템에서 앱 코드를 추적해야 합니다. 로컬 개발 환경으로 코드를 체크아웃하여 앱에 작업을 수행합니다. 코드를 버전 제어 시스템에 저장하면 코드 변경사항에 대한 감사 추적이 가능하고, 병합 충돌을 체계적으로 해결할 수 있으며, 이전 버전으로 코드를 롤백할 수 있어 팀원들의 협업이 가능해집니다. 또한 지속적 통합(CI)과 지속적 배포(CD)도 수행할 수 있습니다.

개발자는 개발 환경에서 다양한 버전의 코드로 작업할 수 있지만 코드의 근원은 버전 제어 시스템에 있는 코드입니다. 저장소의 코드는 빌드, 테스트, 배포되며 저장소 수는 환경 수와 관계가 없습니다. 저장소의 코드는 단일 빌드를 생성하는 데 사용됩니다. 빌드는 환경별 구성과 결합되어 변경 불가능한 출시 버전(구성을 비롯하여 변경할 수 없는 출시 버전)를 생성하고 이 출시 버전이 환경에 배포됩니다. 출시 버전에 요구되는 모든 변경사항은 새로운 출시 버전이 됩니다.

Cloud Source Repositories를 사용 설정하면 모든 기능을 갖추고 확장 가능한 비공개 Git 저장소에서 코드를 공동작업 및 관리할 수 있습니다. 모든 저장소에서 코드 검색 기능이 제공됩니다. 또한 다른 Google Cloud 제품인 Cloud Build, App Engine, Cloud Logging, Pub/Sub와 연결할 수 있습니다.

2. 종속 항목

Twelve-Factor 앱의 종속 항목에는 종속 항목 선언과 종속성 격리라는 두 가지 고려사항이 있습니다.

Twelve-Factor 앱에는 암시적 종속 항목이 절대 없어야 합니다. 종속 항목을 명시적으로 선언하고 이러한 종속 항목을 버전 제어로 체크인해야 합니다. 이렇게 하면 반복 가능한 방법으로 코드를 빠르게 시작할 수 있으며 종속 항목의 변경사항을 쉽게 추적할 수 있습니다. 많은 프로그래밍 언어에서 Python용 PIP와 Ruby용 Bundler와 같은 종속 항목을 명시적으로 선언할 수 있습니다.

또한 앱과 패키지 종속 항목을 컨테이너에 패키징하여 격리해야 합니다. 컨테이너를 사용하면 앱과 종속 항목을 환경으로부터 격리하여 개발 환경과 스테이징 환경 간에 차이점이 있더라도 앱이 균일하게 작동하도록 할 수 있습니다.

Artifact Registry는 컨테이너 이미지, 언어 패키지(예: Maven 및 npm), OS 패키지(예: RPM)와 같은 다양한 유형의 아티팩트를 지원하는 완전 관리형 비공개 아티팩트 관리 서비스입니다. CI/CD 빌드 결과와 해당 종속 항목을 관리하는 데 도움이 되도록 세분화된 액세스 제어로 Artifact Registry에서 Cloud IAM을 사용할 수 있습니다. Artifact Analysis는 Artifact Registry에 푸시된 컨테이너 이미지에서 취약점을 감지하여 컨테이너 이미지를 안전하게 배포할 수 있게 해줍니다.

또한 기존 CI/CD 통합을 사용하면 완전 자동화된 파이프라인을 설정하여 의견을 빠르게 얻을 수 있습니다. 이미지를 레지스트리에 내보내고 Compute Engine 인스턴스 또는 자체 하드웨어에 관계없이 HTTP 엔드포인트를 사용하여 모든 머신에서 이미지를 가져올 수 있습니다.

3. 구성

모든 최신 앱에는 몇 가지 형식의 구성이 필요합니다. 일반적으로 개발, 테스트, 프로덕션 등 환경마다 서로 다른 구성을 사용합니다. 이러한 구성에는 일반적으로 데이터베이스와 같은 지원 서비스에 대한 서비스 계정 사용자 인증 정보와 리소스 핸들이 포함됩니다.

각 환경의 구성은 코드 외부에 있어야 하며 버전 제어에 체크인하면 안 됩니다. 모두가 코드 버전 하나에만 작업하지만 구성은 여러 개 있을 수 있습니다. 사용할 구성은 배포 환경에 따라 결정됩니다. 따라서 한 버전의 바이너리를 환경마다 배포할 수 있습니다. 여기서는 런타임 구성만 다를 뿐입니다. 구성이 올바르게 외부화되었는지 쉽게 확인할 수 있는 방법은 사용자 인증 정보를 공개하지 않고 코드를 공개할 수 있는지 여부를 확인하는 것입니다.

구성을 외부화하는 한 가지 방법은 구성 파일을 만드는 것입니다. 하지만 구성 파일은 일반적으로 특정 언어 또는 개발 프레임워크에 관련됩니다.

더 좋은 방법은 구성을 환경 변수에 저장하는 것입니다. 환경 변수는 런타임 시 각 환경별로 변경되기 쉽고, 버전 제어에 체크인될 가능성이 낮으며, 프로그래밍 언어 및 개발 프레임워크와 독립적입니다. Google Kubernetes Engine(GKE)에서는 ConfigMaps를 사용할 수 있습니다. 이를 통해 런타임 시 환경 변수, 포트 번호, 구성 파일, 명령줄 인수, 기타 구성 아티팩트를 Pod 컨테이너와 시스템 구성요소에 binding할 수 있습니다.

Cloud FunctionsCloud Run은 환경 변수 사용을 지원합니다. Google Cloud 콘솔에서 또는 Google Cloud SDK를 사용하여 구성을 외부화하고 수정할 수 있습니다.

4. 지원 서비스

파일 시스템, 데이터베이스, 캐싱 시스템, 메시지 큐와 같은 일반 작업의 일부로 앱에서 사용하는 모든 서비스는 서비스로 액세스되고 구성을 통해 외부화되어야 합니다. 이러한 지원 서비스는 기본 리소스의 추상화라고 여겨야 합니다. 예를 들어 앱이 데이터를 스토리지에 쓸 때 스토리지를 지원 서비스로 취급하면 스토리지가 앱에서 분리되므로 기본 스토리지 유형을 원활하게 변경할 수 있습니다. 그런 다음 앱 코드를 변경하지 않고 로컬 PostgreSQL 데이터베이스에서 PostgreSQL용 Cloud SQL로 전환과 같은 변경을 수행할 수 있습니다.

5. 빌드, 출시, 실행

소프트웨어 배포 프로세스를 빌드, 출시, 실행 등의 3단계로 구분하는 것이 중요합니다. 각 단계별로 고유하게 식별 가능한 아티팩트가 생성되어야 합니다. 각 배포는 환경 구성을 빌드와 결합한 결과인 특정 출시 버전에 연결되어야 합니다. 이렇게 하면 각 프로덕션 배포를 쉽게 롤백할 수 있고 배포 기록의 시각적인 감사 추적이 가능해집니다.

빌드 단계를 수동으로 트리거할 수 있지만 일반적으로는 모든 필수 테스트를 통과한 코드를 커밋하면 빌드 단계가 자동으로 트리거됩니다. 빌드 단계에서는 코드, 필수 라이브러리, 애셋을 가져와 자체 포함 바이너리 또는 컨테이너로 패키징합니다. 빌드 단계의 결과물은 빌드 아티팩트입니다.

빌드 단계가 완료되면 출시 단계에서 빌드 아티팩트가 특정 환경의 구성과 결합됩니다. 이를 통해 출시 버전이 생성됩니다. 이 출시 버전은 지속적 배포 앱을 통해 환경에 자동으로 배포될 수 있습니다. 또는 동일한 지속적 배포 앱을 통해 출시를 트리거할 수 있습니다.

마지막으로 실행 단계가 출시 버전을 시작합니다. 예를 들어 GKE에 배포할 경우 Cloud Build는 gke-deploy 빌드 단계를 호출하여 GKE 클러스터에 배포할 수 있습니다. Cloud Build는 YAML 또는 JSON 형식의 빌드 구성 파일을 사용하여 여러 언어와 환경에서 빌드, 출시, 실행 단계를 관리하고 자동화할 수 있습니다.

또한 GKE, Cloud Run, GKE Enterprise에 지속적 배포를 제공하는 완전 관리형 서비스인 Cloud Deploy를 사용할 수 있습니다. Cloud Deploy를 사용하면 승인 단계와 여러 환경으로의 원활한 승격을 포함하는 배포 파이프라인을 만들 수 있습니다. 또한 Cloud Deploy는 모든 대상에서 배포된 애플리케이션의 1단계 롤백을 지원합니다.

6. 프로세스

환경에서 Twelve-Factor 앱을 프로세스 하나 이상으로 실행합니다. 이 프로세스는 스테이트리스(Stateless)여야 하고 서로 데이터를 공유해서는 안 됩니다. 이를 통해 프로세스를 복제하여 앱을 확장할 수 있습니다. 스테이트리스(Stateless) 앱을 만들면 컴퓨팅 인프라에서 프로세스를 이식할 수 있습니다.

'고정' 세션의 개념에 익숙하다면 데이터 처리 및 유지에 대한 관점을 바꿔야 합니다. 프로세스는 언제든지 중단될 수 있으므로 사용 가능한 로컬 스토리지의 콘텐츠에 의존해서는 안 되며 이후 요청이 동일한 프로세스에서 처리되지 않을 수 있습니다. 따라서 데이터베이스와 같은 외부 지원 서비스에서 재사용해야 하는 모든 데이터를 명시적으로 유지해야 합니다.

데이터를 유지해야 하는 경우 MemorystoreFilestore를 지원 서비스로 사용하여 앱 상태를 캐시하고 프로세스 간에 공통 데이터를 공유하여 느슨하게 결합할 수 있습니다.

7. 포트 결합

클라우드가 아닌 환경에서는 웹 앱이 GlassFish, Apache Tomcat, Apache HTTP 서버와 같은 앱 컨테이너에서 실행되도록 작성되는 경우가 많습니다. 이와 달리 Twelve-Factor 앱은 외부 앱 컨테이너를 사용하지 않습니다. 대신 앱 자체의 일부로 웹 서버 라이브러리를 번들로 묶습니다.

PORT 환경 변수에 지정된 포트 번호를 노출하는 서비스의 아키텍처 권장사항입니다.

포트 결합을 내보내는 앱은 Platform as a Service 모델을 사용할 때 포트 결합 정보를 환경 변수로 외부에서 사용할 수 있습니다. Google Cloud에서는 Compute Engine, GKE, App Engine 또는 Cloud Run과 같은 플랫폼 서비스에 앱을 배포할 수 있습니다.

이러한 서비스에서 라우팅 레이어는 공개 호스트 이름의 요청을 포트가 결합된 웹 프로세스로 라우팅합니다. 예를 들어 앱을 App Engine에 배포할 때 종속 항목을 선언하여 Express(Node.js용), Flask 및 Gunicorn(Python용) 또는 Jetty(자바용)와 같은 웹 서버 라이브러리를 앱에 추가합니다.

코드에 포트 번호를 하드 코딩해서는 안 됩니다. 대신 환경 변수와 같이 환경에 포트 번호를 제공해야 합니다. 이렇게 하면 Google Cloud에서 앱을 실행할 때 앱을 이식할 수 있습니다.

Kubernetes에는 서비스 검색 기능이 기본 제공되므로 서비스 포트를 컨테이너에 매핑하여 포트 결합을 추상화할 수 있습니다. 서비스 검색은 내부 DNS 이름을 사용하여 수행됩니다.

구성은 웹 서버가 리슨하는 포트를 하드 코딩하는 대신 환경 변수를 사용합니다. App Engine 앱의 다음 코드 스니펫은 환경 변수로 전달된 포트 값을 수락하는 방법을 보여줍니다.

const express = require('express')
const request = require('got')

const app = express()
app.enable('trust proxy')

const PORT = process.env.PORT || 8080
app.listen(PORT, () => {
  console.log('App listening on port ${PORT}')
  console.log('Press Ctrl+C to quit.')
})

8. 동시 실행

백그라운드, 웹, 작업자 프로세스와 같은 프로세스 유형에 따라 앱을 독립적인 프로세스로 분할해야 합니다. 이를 통해 개별 워크로드 요구사항에 따라 앱을 확장 및 축소할 수 있습니다. 대부분의 클라우드 기반 앱에서는 필요에 따라 확장 및 축소할 수 있습니다. 프로세스를 추가하여 독립적으로 작업 블록을 실행 및 수평 확장할 수 있는 여러 분산 프로세스로 앱을 설계해야 합니다.

다음 섹션에서는 앱 확장에 사용되는 몇 가지 구문을 설명합니다. 일회성 및 스테이트리스(Stateless) 원칙을 기반으로 빌드된 앱에서는 이러한 수평 확장 구성을 활용하기가 용이합니다.

Cloud Run 사용

Cloud Run은 Google 관리 인프라에서 직접 컨테이너를 실행할 수 있게 해 주는 컴퓨팅 플랫폼입니다. Cloud Run은 코드를 실행하는 두 가지 방법을 지원합니다. Cloud Run services는 서비스로 계속 실행됩니다. 일반적으로 웹 요청이나 이벤트에 응답하는 데 사용됩니다. Cloud Run jobs는 특정 작업 작업을 수행하고 작업이 완료되면 종료되는 코드를 실행합니다. 또한 Cloud Run은 일괄 작업이 실행되도록 Cloud Scheduler를 제공합니다. 이 구조는 동시 실행을 구현하고 가능한 서비스 아키텍처를 확장하는 데 매우 적합합니다.

Cloud Run에 대한 자세한 내용은 Cloud Run이란 무엇인가요?를 참조하세요.

Cloud Functions 사용

Cloud Functions는 Google Cloud에서 실행되는 스테이트리스(Stateless) 단일 용도 함수로, 실행되는 기본 아키텍처는 Google에서 관리됩니다. Cloud Functions는 Cloud Storage 버킷이나 Pub/Sub 메시지에 업로드와 같은 이벤트 트리거에 대응합니다. 각 함수 호출은 단일 이벤트 또는 요청에 대응하여 수행됩니다.

Cloud Functions는 수신 받은 요청을 함수의 인스턴스에 할당하여 처리합니다. 수신 요청 볼륨이 기존 인스턴스 수를 초과하면 Cloud Functions에서 요청을 처리할 새 인스턴스를 시작할 수 있습니다. 이러한 완전 관리형 자동 확장 동작을 통해 Cloud Functions는 함수의 다른 인스턴스를 사용하여 여러 요청을 동시에 처리할 수 있습니다.

App Engine 사용

Google Cloud의 관리형 인프라에서 App Engine을 사용하여 앱을 호스팅할 수 있습니다. 인스턴스는 App Engine에서 앱을 자동으로 확장하는 데 사용하는 컴퓨팅 단위입니다. 앱은 언제든지 인스턴스 하나 또는 여러 인스턴스에서 실행될 수 있으며 요청은 전체 인스턴스에 분산됩니다.

App Engine 스케줄러는 새 요청을 처리하는 방법을 결정합니다. 스케줄러는 기존 인스턴스(유휴 상태의 인스턴스 또는 동시 요청을 수락하는 인스턴스)를 사용하거나, 대기 요청 큐에 넣거나 또는 이 요청을 위한 새 인스턴스를 시작할 수 있습니다. 결정 시 사용할 수 있는 인스턴스 수, 앱의 요청 처리 속도(지연 시간), 새 인스턴스 시작에 걸리는 시간을 고려합니다.

자동 확장을 사용할 경우 대상 CPU 사용률, 목표 처리량, 최대 동시 요청 수를 설정하면 성능과 비용 간의 균형을 맞출 수 있습니다.

app.yaml 파일에서 확장 유형을 지정할 수 있으며 이 파일을 서비스 버전용으로 업로드합니다. 이렇게 입력한 구성에 따라 App Engine 인프라는 동적 인스턴스 또는 상주 인스턴스를 사용합니다. 확장 유형에 대한 자세한 내용은 App Engine 문서를 참조하세요.

GKE 자동 확장 사용

확장 프로세스에 적용되는 몇 가지 핵심 Kubernetes 구조가 있습니다.

  • 수평 Pod 자동 확장(HPA). 표준 측정항목 또는 커스텀 측정항목에 따라 클러스터에서 실행 중인 Pod 수를 늘리거나 줄이도록 Kubernetes를 구성할 수 있습니다. 이는 GKE 클러스터에서 가변형 부하에 대응해야 하는 경우에 유용합니다.

  • 노드 자동 확장. 요청이 늘어날 경우 Pod를 추가로 수용할 수 있도록 클러스터를 확장해야 할 수도 있습니다. GKE에서는 클러스터가 확장되도록 선언적으로 구성할 수 있습니다. 자동 확장을 사용 설정하면 GKE는 추가 Pod 예약이 필요할 때와 기존 노드가 이를 수용할 수 없을 때 노드를 자동으로 확장합니다. 또한 GKE는 클러스터 부하가 감소하면 구성된 임곗값에 따라 노드를 축소합니다.

  • 작업. GKE는 Kubernetes 작업을 지원합니다. 작업은 태스크를 실행하기 위해 Pod 하나 이상이 필요한 태스크로 광범위하게 정의됩니다. 작업은 한 번 실행되거나 일정에 따라 실행될 수 있습니다. 작업이 실행되는 Pod는 작업 완료 시 삭제됩니다. 작업을 구성하는 YAML 파일은 오류 처리, 동시 로드, 다시 시작 처리 방법에 대한 세부정보를 지정합니다.

Compute Engine 사용

또는 Compute Engine에 앱을 배포하고 관리할 수 있습니다. 이렇게 하면 CPU 사용률, 처리 중인 요청 수 또는 앱의 기타 원격 분석 신호를 기반으로 관리형 인스턴스 그룹(MIG)을 사용하여 가변형 부하에 맞게 앱을 확장할 수 있습니다.

다음 그림은 관리형 인스턴스 그룹에서 제공하는 주요 기능을 보여줍니다.

MIG 기능과 일반적인 워크로드의 개요

관리형 인스턴스 그룹을 사용하면 앱이 들어오는 요청에 맞게 확장되고 가용성이 높아집니다. 이 개념은 웹 프런트엔드와 같은 스테이트리스(Stateless) 앱과 일괄 처리 고성능 워크로드에 유용합니다.

9. 일회성

클라우드 인프라에서 실행되는 앱의 경우 앱과 기본 인프라를 일회성 리소스로 취급해야 합니다. 앱에서 기본 인프라의 일시적인 손실을 처리할 수 있어야 하며 올바르게 종료한 후 다시 시작할 수 있어야 합니다.

고려해야 할 주요 원칙은 다음과 같습니다.

  • 지원 서비스를 사용하는 상태 관리 및 트랜잭션 데이터 스토리지와 같은 기능을 분리합니다. 자세한 내용은 이 문서 앞부분의 지원 서비스를 참조하세요.
  • 런타임 시 사용할 수 있도록 앱 외부에 있는 환경 변수를 관리합니다.
  • 시작 시간이 최소화되었는지 확인합니다. 즉, 공개 이미지와 커스텀 이미지와 같은 가상 머신을 사용할 때 이미지에 빌드할 레이어 수를 결정해야 합니다. 이 결정은 각 앱별로 지정되며 시작 스크립트가 수행할 태스크를 기준으로 삼아야 합니다. 예를 들어 시작 중에 여러 패키지 또는 바이너리를 다운로드하여 초기화할 경우 시작 시간의 상당 부분이 이러한 태스크를 완료하는 데 사용됩니다.
  • Google Cloud의 기본 기능을 사용하여 인프라 태스크를 수행합니다. 예를 들어 GKE에서 순차적 업데이트를 사용하고 Cloud Key Management Service(Cloud KMS)를 사용하여 보안 키를 관리할 수 있습니다.
  • SIGTERM 신호(사용 가능한 경우)를 사용하여 완전한 종료를 시작합니다. 예를 들어 App Engine Flex는 인스턴스를 종료할 때 일반적으로 앱 컨테이너에 STOP(SIGTERM) 신호를 전송합니다. 앱은 이 신호를 사용하여 컨테이너가 종료되기 전에 정리 작업을 수행할 수 있습니다. 앱이 SIGTERM 이벤트에 응답할 필요는 없습니다. 정상 조건에서 시스템은 앱이 중지할 때까지 최대 30초까지 기다린 후 KILL(SIGKILL) 신호를 전송합니다.

    App Engine 앱의 다음 스니펫은 SIGTERM 신호를 가로채서 열린 데이터베이스 연결을 닫는 방법을 보여줍니다.

    const express = require('express')
    const dbConnection = require('./db')
    
    // Other business logic related code
    
    app.listen(PORT, () => {
      console.log('App listening on port ${PORT}')
      console.log('Press Ctrl+C to quit.')
    })
    
    process.on('SIGTERM', () => {
      console.log('App Shutting down')
      dbConnection.close()  // Other closing of database connection
    })
    

10. 환경 패리티

엔터프라이즈 앱은 개발 수명 주기 동안 개발, 테스트, 스테이징, 프로덕션 등 다양한 환경으로 이동합니다. 이러한 환경을 최대한 유사하게 유지하는 것이 좋습니다.

환경 패리티는 대부분의 개발자가 당연하게 여기는 기능입니다. 그럼에도 불구하고 기업이 성장하고 IT 생태계가 진화함에 따라 환경 패리티를 유지하기가 더욱 어려워지게 됩니다.

하지만 개발자들이 소스 제어, 구성 관리, 템플릿 구성 파일을 채용함에 따라 지난 몇 년 동안 환경 패러티를 더욱 쉽게 유지할 수 있게 되었습니다. 이를 통해 앱을 다양한 환경에 일관성 있게 쉽게 배포할 수 있습니다. 예를 들어 Docker와 Docker Compose를 사용하면 앱 스택이 여러 환경에서 모양과 계측을 유지하도록 할 수 있습니다.

다음 표에는 Google Cloud에서 실행할 앱을 설계할 때 사용할 수 있는 Google Cloud 서비스와 도구가 나와 있습니다. 이들 구성요소는 각각 다른 용도로 사용되지만 함께 사용하면 환경 간 일관성을 유지하는 워크플로를 빌드할 수 있습니다.

Google Cloud 구성요소 목적
Cloud Source Repositories 팀이 코드를 한곳에서 저장, 관리, 추적할 수 있습니다.
Artifact Registry 모든 빌드 아티팩트 및 종속 항목에 대한 범용 패키지 관리자입니다.
Cloud Build Google Cloud 인프라에서 빌드를 실행하는 완전 관리형 서비스입니다.
Cloud KMS 다른 클라우드 리소스와 애플리케이션에서 직접 사용할 수 있도록 암호화 키를 중앙 클라우드 서비스 하나에 저장합니다.
Cloud Storage Cloud Storage에 저장된 소스 디스크, 이미지, 스냅샷 또는 이미지에서 만든 커스텀 이미지를 저장합니다. 이 이미지를 사용하면 앱에 맞춤설정된 가상 머신(VM) 인스턴스를 만들 수 있습니다.
Cloud Deploy 정의된 시퀀스에 따라 일련의 여러 대상 환경에 애플리케이션을 자동으로 제공합니다.

11. 로그

로그를 사용하면 앱 상태를 확인할 수 있습니다. 앱의 핵심 로직에서 로그 수집, 처리, 분석을 분리하는 것이 중요합니다. 로깅 분리는 앱에 동적 확장이 필요하고 앱이 퍼블릭 클라우드에서 실행되는 경우에 특히 유용합니다. 분산된 (그리고 종종 임시인) VM의 집계와 로그의 스토리지 위치를 관리하는 부담이 사라지기 때문입니다.

Google Cloud는 로그의 수집, 처리, 구조화 분석을 지원하는 도구 모음을 제공합니다. Compute Engine VM에 Cloud Logging 에이전트를 설치하는 것이 좋습니다. 기본적으로 에이전트는 App Engine 및 GKE VM 이미지에 사전 설치되어 있습니다. 에이전트는 사전 구성된 일련의 로깅 위치를 모니터링합니다. VM에서 실행 중인 앱에서 생성된 로그가 수집되어 Cloud Logging으로 스트리밍됩니다.

GKE 클러스터에 로깅을 사용 설정하면 클러스터에 속한 각 노드에 로깅 에이전트가 배포됩니다. 에이전트는 로그를 수집하여 관련 메타데이터로 보강하고 데이터 저장소에 보관합니다. Cloud Logging을 사용하여 이러한 로그를 검토할 수 있습니다. 로깅 대상 항목에 대한 보다 세밀한 제어가 필요하면 Fluentd DaemonSet을 사용하면 됩니다.

자세한 내용은 Logging 에이전트 구성을 참조하세요.

12. 관리 프로세스

관리 프로세스는 일반적으로 보고서 생성, 일괄 스크립트 실행, 데이터베이스 백업 시작, 스키마 마이그레이션과 같은 일회성 태스크 또는 시간 기준으로 반복되는 태스크로 구성됩니다. Twelve-Factor 선언에 있는 관리 프로세스 요소는 일회성 태스크를 염두에 두고 작성된 것입니다. 클라우드 기반 앱의 경우 이 요소는 반복되는 태스크를 만들 때 관련성이 더욱 높아지고 이 섹션에서는 이러한 태스크를 중심으로 설명합니다.

시간 기준 트리거는 종종 크론 작업으로 빌드되며 앱 자체에서 기본적으로 처리됩니다. 이 모델은 작동하지만 앱과 긴밀히 연결되어 있고 특히 앱이 여러 시간대에 분산된 경우에 유지보수 및 조정이 필요한 로직이 생성됩니다.

따라서 관리 프로세스를 설계할 때 이러한 태스크의 관리를 앱 자체에서 분리해야 합니다. 앱을 실행할 도구와 인프라에 따라 다음 권장사항을 따르세요.

  • GKE에서 앱을 실행할 경우 관리 태스크용으로 별도의 컨테이너를 시작합니다. GKE에서는 CronJobs을 활용하면 됩니다. CronJobs는 임시 컨테이너에서 실행되며 작업이 실패하거나 완료되는 데 시간이 너무 오래 걸릴 경우 타이밍, 실행 빈도, 재시도 횟수를 제어할 수 있게 해줍니다.
  • App Engine 또는 Compute Engine에서 앱을 호스팅할 경우 트리거 메커니즘을 외부화하고 호출할 트리거의 엔드포인트를 만들 수 있습니다. 이 방식은 엔드포인트의 단일 용도에 중점을 두는 것이 아닌 앱이 담당하는 범위의 경계를 정의하는 데 유용합니다. Cloud Tasks는 App Engine에서 이 패턴을 구현하는 데 사용할 수 있는 완전 관리형 비동기 태스크 실행 서비스입니다. 또한 Google Cloud의 엔터프라이즈급 완전 관리형 스케줄러인 Cloud Scheduler를 사용하여 시간 기준 작업을 트리거할 수 있습니다.

Twelve-Factor 그 이상

이 문서에 설명된 Twelve-Factor는 클라우드 기반 앱의 빌드 방식에 대한 지침을 제공합니다. 이러한 앱은 기업의 기본 구성요소입니다.

일반적인 기업에는 업무 처리 역량을 제공하기 위해 종종 여러 팀에서 공동으로 개발하는 이와 같은 앱이 많습니다. 앱 간의 통신 방식과 보안 및 액세스 제어 방식과 관련하여 앱 개발 후가 아닌 개발 수명 주기 동안 몇 가지 추가적인 원칙을 세우는 것이 중요합니다.

다음 섹션에서는 앱 설계 및 개발 중에 고려해야 할 몇 가지 추가적인 고려사항을 간략하게 설명합니다.

API를 우선적으로 고려

앱은 API를 사용하여 통신합니다. 앱을 빌드할 때는 앱의 생태계에서 앱을 어떻게 사용할지 생각해보고 API 전략을 설계하는 것으로 시작합니다. API 설계가 원활하면 앱 개발자와 외부 이해관계자가 API를 쉽게 사용할 수 있습니다. 코드를 구현하기 전에 OpenAPI 사양에 따라 API를 문서화하는 것으로 시작하는 것이 좋습니다.

API는 기본 앱 기능을 추상화합니다. 잘 설계된 API 엔드포인트는 서비스를 제공하는 앱 인프라에서 사용되는 애플리케이션을 격리하고 분리해야 합니다. 이렇게 분리하면 앱 사용자에게 영향을 주지 않고 기본 서비스와 인프라를 개별적으로 변경할 수 있습니다.

개발할 API를 카탈로그화, 문서화, 게시하여 API 사용자가 API를 검색하고 사용할 수 있도록 하는 것이 중요합니다. API 사용자가 직접 서비스를 제공하는 것이 가장 좋습니다. 이렇게 하려면 개발자 포털을 설정하면 됩니다. 개발자 포털은 기업 내부 사용자뿐만 아니라 파트너 생태계의 개발자와 같은 외부 사용자를 포함한 모든 API 사용자의 진입점 역할을 합니다.

Google API 관리 제품군인 Apigee를 사용하면 설계에서 빌드와 게시까지 전체 API 수명 주기를 관리할 수 있습니다.

보안

보안의 범위는 폭넓으며 운영체제, 네트워크와 방화벽, 데이터와 데이터베이스 보안, 앱 보안, ID 및 액세스 관리 등이 포함됩니다. 기업 생태계에서는 보안의 모든 측면을 다루는 것이 매우 중요합니다.

앱의 관점에서 API는 기업 생태계의 앱에 대한 액세스를 제공합니다. 따라서 앱 설계 및 빌드 프로세스 중에 이러한 구성요소에 대한 보안을 고려해야 합니다. 앱에 대한 액세스를 보호하기 위한 고려사항은 다음과 같습니다.

  • 전송 계층 보안(TLS). TLS를 사용하면 전송 중 데이터를 보호할 수 있습니다. 비즈니스 앱에 상호 TLS를 사용하려 할 수도 있습니다. Google Kubernetes Engine에서 Istio와 같은 서비스 메시를 사용하면 더욱 간편하게 이렇게 할 수 있습니다. 일부 사용 사례에서는 보안을 더욱 강화하기 위해 IP 주소를 기준으로 허용 목록과 거부 목록을 만드는 것이 일반적입니다. 또한 전송 보안에서 DDoS 및 봇 공격으로부터 서비스를 보호하는 것도 포함됩니다.
  • 앱 및 최종 사용자 보안. 전송 보안을 통해 전송 중 데이터를 보호하고 트러스트를 설정할 수 있습니다. 하지만 앱 사용자를 기준으로 앱에 대한 액세스를 제어하려면 앱 수준 보안을 추가하는 것이 가장 좋습니다. 앱 사용자는 다른 앱, 직원, 파트너 또는 기업의 최종 고객일 수 있습니다. API 키(앱 사용 시), 자격증 기반 인증 및 승인, JSON 웹 토큰(JWT) 교환 또는 보안 보장 마크업 언어(SAML)를 사용하여 보안을 강화할 수 있습니다.

기업 내 보안 환경이 끊임없이 진화하므로 앱에 보안 구조를 코딩하기가 점점 더 어려워지고 있습니다. Apigee와 같은 API 관리 제품은 이 섹션에 언급된 모든 레이어에서 보안 API를 지원합니다.

소프트웨어 공급망 보안은 해결하기 어려운 문제입니다. 예방 조치를 취하는 것이 중요합니다. Software Delivery Shield는 전체 소프트웨어 개발 수명 주기에서 소프트웨어 공급망 보안을 강화하는 데 도움이 되는 완전 관리형 엔드 투 엔드 솔루션입니다. 제공하는 서비스는 다음과 같습니다.

또한 소프트웨어 공급망의 안전을 향상시키는 데 도움이 되는 다양한 서비스와 기능이 준비되어 있습니다.

소프트웨어 공급망 보안에 대한 자세한 내용은 소프트웨어 공급망 보안을 참조하세요. Software Delivery Shield에 대한 자세한 내용은 Software Delivery Shield 개요를 참조하세요.

다음 단계

  • Twelve-Factor 앱 원칙을 도입하고 Google Cloud 제품 및 서비스를 사용하여 빌드된 마이크로서비스 데모 앱을 살펴보세요.
  • 클라우드 아키텍처 센터에 방문하여 Google Cloud에서 워크로드 빌드 또는 마이그레이션에 대한 참조 아키텍처, 가이드, 권장사항을 알아보세요.
  • Google Cloud에 대한 참조 아키텍처, 다이어그램, 권장사항 살펴보기 Cloud 아키텍처 센터 살펴보기