Published on

pulumi awsx로 AWS 인프라를 간결하게 정의하는 방법

Authors
  • avatar
    Name
    Indo Yoon
    Twitter

pulumi awsx는 Pulumi가 제공하는 AWS Crosswalk 패키지로, VPC나 컨테이너 서비스처럼 매번 비슷하게 반복되는 AWS 구성을 짧은 코드로 완성해 주는 상위 수준 컴포넌트 모음입니다. 기본 AWS 프로바이더가 서브넷과 보안 그룹을 하나씩 직접 선언하게 한다면, awsx는 검증된 기본값을 미리 묶어 두고 필요한 부분만 조정하게 해 줍니다. 이 글은 서버 운영과 배포를 담당하는 백엔드 개발자가 awsx를 언제 쓰고 언제 내려와야 하는지 스스로 판단할 수 있도록 개념과 도입 절차를 정리합니다.

한눈에 보기

pulumi awsx를 한 문장으로 줄이면 "자주 쓰는 AWS 조합을 미리 만들어 둔 상위 수준 컴포넌트"입니다. 기본 AWS 프로바이더가 EC2, 보안 그룹, 서브넷, 라우팅 테이블을 각각 선언하게 만든다면, awsx는 그 조합 자체를 하나의 컴포넌트로 감싸고 합리적인 기본값을 채워 넣습니다. 그래서 인프라 코드의 줄 수가 줄고, 네트워크 구성에서 빠뜨리기 쉬운 연결 작업이 자동으로 채워집니다.

  • 패키지 이름은 언어마다 다릅니다. TypeScript와 JavaScript는 @pulumi/awsx, Python은 pulumi-awsx를 사용합니다.
  • awsx 컴포넌트는 내부에서 기본 AWS 프로바이더 리소스를 생성합니다. 두 패키지는 한 스택에서 함께 쓸 수 있습니다.
  • 네트워크, 컨테이너, 로드밸런서, 데이터베이스처럼 형태가 반복되는 구간에서 효과가 큽니다.
  • 세밀한 튜닝이 필요한 구간은 기본 프로바이더 리소스로 내려가 직접 정의하는 편이 낫습니다.
  • 컴포넌트가 만든 하위 리소스는 상태 파일에 부모와 자식 관계로 기록되므로, 나중에 추적하고 참조하기가 수월합니다.

awsx와 기본 AWS 프로바이더 비교

두 패키지는 경쟁 관계가 아니라 계층 관계입니다. 아래 표는 같은 인프라를 만들 때 어느 쪽이 어떤 성격을 갖는지 정리한 것입니다.

항목pulumi awsx기본 AWS 프로바이더
추상화 단위VPC, 클러스터, 서비스 같은 조합 단위서브넷, 보안 그룹, 리스너 같은 개별 리소스
초기 코드 분량적음많음
기본값미리 정해진 합리적인 기본값거의 비어 있음
제어 수준컴포넌트가 노출하는 옵션 범위거의 모든 속성을 직접 제어
변경 영향 범위컴포넌트 단위로 묶여 있음리소스 단위로 분리됨
잘 맞는 상황표준적인 웹 서비스 배포특수한 네트워크·권한·규정 대응

표에서 보이듯 awsx는 "빠르게 표준 형태를 만드는 도구"이고, 기본 프로바이더는 "원하는 형태를 정확히 만드는 도구"입니다. 실무에서는 awsx로 뼈대를 세우고, 정책상 손봐야 하는 리소스만 기본 프로바이더로 내려가 세밀하게 조정하는 조합이 가장 흔합니다.

단계별로 도입하는 방법

패키지 설치와 프로젝트 준비

TypeScript 프로젝트라면 기존 Pulumi 프로젝트 디렉터리에서 다음처럼 설치합니다.

npm install @pulumi/awsx

Python 프로젝트라면 pip install pulumi-awsx를 사용합니다. 이미 @pulumi/aws를 쓰고 있던 프로젝트라면 굳이 제거할 필요가 없습니다. awsx는 기본 프로바이더를 감싸는 구조이므로 두 패키지가 같은 스택 안에 함께 있어도 문제가 되지 않습니다. 오히려 컴포넌트가 감싸지 못하는 리소스를 직접 정의할 때 기본 프로바이더가 그대로 필요합니다.

네트워크부터 만들기

가장 먼저 손대는 것은 대개 VPC입니다. awsx의 VPC 컴포넌트는 서브넷 배치, 라우팅, NAT 구성을 기본값으로 채워 주기 때문에 네트워크 담당자가 아닌 개발자도 표준적인 형태를 빠르게 만들 수 있습니다.

import * as awsx from "@pulumi/awsx";

const vpc = new awsx.ec2.Vpc("app-vpc", {
  numberOfAvailabilityZones: 2,
});

여기서 짚어야 할 점은 vpc가 단순한 문자열이 아니라 컴포넌트 리소스라는 사실입니다. 서브넷 ID 목록이나 VPC ID 같은 값은 컴포넌트가 노출하는 속성으로 꺼내 쓰고, 내부 리소스에 추가 설정을 붙여야 할 때는 컴포넌트가 공개하는 하위 리소스를 참조합니다. 이 구조 덕분에 "네트워크는 컴포넌트로, 예외 설정은 개별 리소스로" 라는 분리가 자연스럽게 됩니다.

컨테이너 서비스 배포

ECS 파게이트 기반 서비스는 awsx에서 코드가 가장 크게 줄어드는 구간입니다. 클러스터, 태스크 정의, 서비스가 하나의 컴포넌트로 묶여 만들어집니다.

import * as awsx from "@pulumi/awsx";

const cluster = new awsx.ecs.Cluster("app-cluster");

const service = new awsx.ecs.FargateService("app-service", {
  cluster,
  taskDefinitionArgs: {
    containers: {
      app: { image: "my-app:latest", port: 8080 },
    },
  },
});

컴포넌트 옵션의 정확한 이름과 필수 여부는 패키지 버전에 따라 조금씩 달라집니다. 실제로 적용하기 전에 레지스트리 문서에서 현재 프로젝트가 사용하는 버전의 시그니처를 확인하는 편이 안전합니다. 로드밸런서를 붙일 때도 리스너와 타깃 그룹을 각각 선언하는 대신 컴포넌트 옵션으로 연결하는 방식이 기본입니다.

기존 리소스와 섞어 쓰기

이미 기본 프로바이더로 만든 리소스가 있다면 두 방향으로 연결할 수 있습니다. awsx 컴포넌트에 기존 리소스의 식별자를 넘겨 그 위에 서비스를 얹거나, 반대로 awsx가 만든 리소스의 ARN이나 ID를 기본 프로바이더 리소스의 입력으로 넘기는 방식입니다. 이때 Pulumi의 출력(Output) 값은 일반 문자열처럼 다룰 수 없고, 값이 확정된 뒤에 실행되는 방식으로 연결해야 합니다. 이 개념은 awsx를 쓰든 기본 프로바이더를 쓰든 동일하게 적용되는 기본기이므로, 처음 도입할 때 함께 익혀 두면 이후 디버깅이 훨씬 수월해집니다.

상황별 선택 기준

  • 새 서비스를 표준 형태로 빠르게 띄워야 한다면 awsx가 유리합니다. 네트워크와 컨테이너 구성을 짧은 코드로 끝낼 수 있습니다.
  • 사내망 연결, 피어링, 방화벽 정책처럼 네트워크를 정교하게 다뤄야 한다면 기본 프로바이더로 내려가는 편이 좋습니다.
  • 이미 운영 중인 인프라가 있다면 그대로 두고, 새로 추가하는 서비스에만 awsx를 적용하는 방식이 위험이 적습니다.
  • 여러 스택이 같은 네트워크를 공유한다면 네트워크는 별도 스택에서 기본 프로바이더로 관리하고, 애플리케이션 스택에서만 awsx를 쓰는 구성도 자주 쓰입니다.
  • 학습이나 실험이라면 awsx로 전체 흐름을 먼저 익히고, 필요한 부분을 하나씩 기본 프로바이더로 바꿔 보는 순서가 이해에 도움이 됩니다.

주의할 점

awsx의 가장 큰 장점이자 가장 큰 주의점은 기본값입니다. 컴포넌트는 편의를 위해 NAT 게이트웨이나 퍼블릭 서브넷 같은 리소스를 함께 만들 수 있는데, 이것이 조직의 보안 정책이나 비용 정책과 맞지 않을 수 있습니다. 도입 전에 어떤 하위 리소스가 함께 생성되는지 pulumi preview로 확인하는 습관이 필요합니다.

또 하나는 변경의 파급 범위입니다. 컴포넌트 이름을 바꾸거나 구조를 크게 바꾸면 하위 리소스가 새로 만들어져야 할 수 있고, 그 과정에서 서비스가 잠시 영향을 받을 수 있습니다. 운영 중인 스택에서는 항상 미리보기 결과를 읽고, 교체가 발생하는 리소스가 무엇인지 확인한 뒤 적용해야 합니다.

마지막으로 컴포넌트가 감싸지 못하는 영역은 반드시 존재합니다. 모든 AWS 서비스에 상위 컴포넌트가 있는 것은 아니므로, awsx와 기본 프로바이더를 함께 쓰는 것을 전제로 구조를 잡는 편이 현실적입니다.

자주 묻는 질문

awsx만 설치하면 기본 AWS 프로바이더는 필요 없나요?

아니요. awsx는 기본 프로바이더 위에 올라가는 상위 컴포넌트라서 내부적으로 기본 리소스를 생성합니다. 두 패키지를 함께 두고, 컴포넌트가 감싸지 못하는 부분은 기본 프로바이더로 직접 정의하는 구성이 일반적입니다.

awsx로 만든 리소스의 세부 설정을 바꿀 수 있나요?

컴포넌트가 노출하는 옵션 범위 안에서는 바꿀 수 있지만, 모든 속성이 열려 있지는 않습니다. 컴포넌트가 공개하는 하위 리소스를 참조해 추가 설정을 붙이거나, 해당 부분만 기본 프로바이더 리소스로 대체하는 방법을 씁니다.

기존에 기본 프로바이더로 만든 인프라를 awsx로 옮겨야 하나요?

꼭 그렇지는 않습니다. 이미 동작하는 인프라는 그대로 두고 새로 만드는 서비스에만 awsx를 적용하는 편이 위험이 적습니다. 컴포넌트로 교체하면 리소스 주소가 바뀌면서 재생성이 발생할 수 있기 때문입니다.

awsx가 모든 AWS 서비스를 감싸고 있나요?

아닙니다. awsx는 네트워크, 컨테이너, 로드밸런서, 데이터베이스처럼 반복되는 패턴을 중심으로 컴포넌트를 제공합니다. 그 밖의 서비스는 기본 AWS 프로바이더 리소스로 정의하는 것이 기본 방침입니다.

출처

인프라 코드를 운영에 붙이는 과정은 awsx만으로 끝나지 않습니다. 스택 분리와 상태 관리, 배포 파이프라인 구성, 롤백 절차까지 함께 봐야 실제 운영이 안정됩니다. 관련해서는 스택 설계와 배포 자동화를 다룬 운영 글, 컨테이너 서비스 무중단 배포를 정리한 글을 함께 읽어 보시면 이 글의 내용을 실제 파이프라인에 연결하기 수월합니다.