[인프라를 소프트웨어처럼 1/5] Infrastructure as Code, 그리고 그다음

terraform plan은 "바뀌는지"는 보여주지만 "되는지"는 모릅니다
인프라를 코드로 다뤄 본 사람이라면 익숙한 장면이 있습니다. 한 줄을 고치고 terraform plan을 돌립니다. 수십 초를 기다려 초록색과 빨간색의 diff를 읽습니다. ~ 12 to change, 3 to add, 1 to destroy 같은 요약을 보며 우리는 잠깐 안심합니다. plan은 무엇이 바뀔지를 정확히, 빠짐없이 알려 줍니다. 그런데 정작 우리가 알고 싶은 질문은 따로 있습니다 — "이게 실제로 동작할까?"
plan은 그 질문에 답하지 못합니다. plan이 비교하는 것은 두 개의 의도입니다. 코드가 선언한 상태와 state 파일이 기억하는 상태, 그 둘의 차이를 계산할 뿐입니다. 보안 그룹의 포트가 정말 트래픽을 흘려보내는지, 새로 붙인 IAM 정책이 의도한 것만 허용하는지, 라우팅 한 줄이 살아 있는 서비스로 패킷을 데려가는지 — plan은 그중 어느 것도 모릅니다. apply를 하고, 클러스터에 붙고, 실제 요청이 흘러 봐야 압니다. diff가 초록색이라는 것과 시스템이 살아 있다는 것은, 슬프게도 같은 말이 아닙니다.
plan은 두 개의 의도(코드와 state)의 차이만 계산합니다. 점선 너머의 "실제로 동작하는가"는 apply 이후에야 드러나는 빈칸입니다.
이 빈칸이 불편한 이유는, 우리가 그것을 "코드"라고 부르기 때문입니다. 소프트웨어에서 우리는 당연하게 누리던 것들이 있습니다. 단위 테스트, 짧은 피드백 루프, 컴파일러가 미리 잡아 주는 실수, 리팩터링을 받쳐 주는 안전망. 그런데 인프라에는 그 대부분이 없었습니다. 한 줄을 고치고 결과를 확인하는 가장 빠른 길이 "프로덕션에 apply해 보는 것"인 세계는, 아무리 텍스트로 쓰여 있어도 소프트웨어라고 부르기 어렵습니다.
한 번은 이런 일이 있었습니다. 어떤 변경 한 건의 plan이 깔끔하게 통과했습니다. 추가 한 줄, 변경 두 줄. 리뷰어도 무리 없이 승인했습니다. 그런데 apply 이후 한 환경에서만 특정 트래픽이 조용히 끊겼습니다. 코드도, plan도, state도 모두 "정상"이었습니다. 문제는 코드 바깥, 즉 그 변경이 실제로 부딪치는 환경의 형상에 있었습니다. plan이 보여 준 diff는 끝까지 초록색이었지만, 시스템은 그 초록색과 무관하게 멈춰 있었습니다. diff와 동작 사이의 그 거리가, 이 연재가 메우려는 빈칸입니다.
IaC는 인프라를 "코드처럼" 만들었습니다. 그다음이 비어 있었습니다
Infrastructure as Code(IaC)는 분명한 진보였습니다. 인프라를 텍스트로 옮긴 덕분에 버전 관리가 되고, Pull Request로 리뷰가 되고, 같은 선언으로 같은 환경을 다시 세울 수 있게 되었습니다. 클릭으로 만든 리소스가 누구의 기억 속에만 남던 시절과 비교하면 거대한 도약입니다.
하지만 IaC는 종종 "코드처럼 보이는 설정"에서 멈춥니다. HCL이든 YAML이든, 그것이 텍스트라는 사실만으로 소프트웨어의 미덕이 따라오지는 않습니다. 설정 파일은 테스트되지 않고, 의존성은 타입으로 강제되지 않으며, 한 환경에서 통과한 변경이 다른 환경에서 같게 동작한다는 보장도 그 자체로는 없습니다. 설정은 코드를 닮았을 뿐, 소프트웨어가 되지는 않았던 것입니다.
그래서 이 연재는 한 걸음 더 들어간 개념을 큰 맥락으로 둡니다 — Infrastructure as Software(IaS). 인프라를 코드로 적는 데서 멈추지 않고, 소프트웨어가 누리는 두 가지 성질을 인프라에도 똑같이 요구하는 태도입니다. 이름이 거창하지만 요구하는 바는 단순합니다. 우리는 애플리케이션 코드에 대해서는 "테스트 없이 머지하지 않는다", "같은 입력이면 같은 출력이어야 한다"를 의심 없이 지킵니다. IaS는 그 두 규율을 인프라에도 그대로 들이대자는 것뿐입니다.
테스트 가능할 것(Testable) — apply 전에, 그리고 운영 중에도, 동작을 검증할 수 있어야 한다.
재현 가능할 것(Reproducible) — 같은 선언이 언제 어디서 돌든 같은 결과를 만든다.
IaC가 인프라에 버전 관리와 리뷰를 주었다면, IaS는 거기에 테스트 가능성과 재현 가능성을 더합니다. 두 성질이 합쳐질 때 비로소 설정은 소프트웨어가 됩니다.
이미 다섯 축을 깎아 둔 사람들
flex 기술블로그의 연재는 이 경계를 이미 한 번 넘었습니다. 「코드가 환경을 모르는 구조」 시리즈에서 내건 한 문장은 이것이었습니다 — "코드는 '무엇을'만 정의하고, '어디서·언제·어떤 환경'은 바깥에서 주입한다." 그리고 이 한 원리를, 성격이 전혀 다른 다섯 개의 축에 똑같이 적용했습니다. 핵심은 매번 같았습니다. 불변하는 계약은 안에 두고, 환경마다 달라지는 접점만 바깥에서 갈아 끼운다.
| 축 | 불변(계약) | 교체되는 접점 |
|---|---|---|
| 배포 | 같은 Helm 템플릿 | values 파일 (base/env) |
| 클라우드 | 같은 product 모듈 | Cloud Adapter (spec=Port) |
| 시간 | 같은 비즈니스 코드 | Clock |
| 공간 | 같은 Gateway | 라우팅 타깃 (Rewrite Host) |
| 테스트 | 같은 테스트 코드 | test variant (컨테이너 계열) |
표를 한 줄로 읽으면 이렇습니다. 배포는 템플릿을 고정하고 values만 바꿉니다. 클라우드는 도메인 모듈을 고정하고 어댑터만 바꿉니다. 테스트는 테스트 코드를 고정하고 컨테이너 계열만 바꿉니다. 「IaC에도 헥사고날이 관통한다」는 여기서 한 발 더 나아가 "변경의 명세(spec)는 Port, 클라우드는 Adapter"라고 못박으며 IaC를 설정 더미가 아닌 아키텍처로 끌어올렸습니다. 그 글들이 "어떻게 설계할 것인가"를 다뤘다면, 이 연재는 그 설계를 실제 클러스터와 CI 파이프라인에 올렸을 때 무슨 일이 벌어지는가를 다룹니다. 코드를 짜는 사람의 자리에서, 그 코드가 만든 환경을 운영하는 사람의 자리로 옮겨 앉는 셈입니다.
우리가 더하는 것 — 환경 그 자체
지난 시리즈들의 다섯 축은 모두 "코드가 환경을 모르게" 만드는 방법이었습니다. 코드는 자신이 dev에 있는지 prod에 있는지 묻지 않고, 그 답은 바깥에서 주입됩니다. 그렇다면 자연스럽게 따라오는 질문이 하나 있습니다. 그 '바깥', 즉 환경 자체는 누가 만들까요.
공간 축을 다룬 「Rewrite Host」 편은 여기까지 갔습니다. 노트북에서 서비스 하나를 원격으로 갈아 끼워 첫 요청을 원하는 곳으로 흘려보내는 데까지요. 하지만 격리된 환경을 통째로 만들고 다 쓰면 회수하는 일은 숙제로 남겼습니다. 그 숙제가 이 연재의 한가운데에 있습니다. 브랜치 하나를 push하면 격리된 실행 환경이 통째로 태어나고, 브랜치를 지우면 환경도 사라집니다. 우리는 그것을 환경(Environment Variant)이라고 부릅니다.
다섯 축은 "코드가 환경을 모르게" 만들었습니다. 여섯 번째 축은 그 환경 자체를 깎습니다 — 공간 축이 숙제로 남긴 "격리된 환경 전체"를 운영 레벨에서 풀어냅니다.
용어 — 이 글의 variant는 그 variant가 아닙니다.
backend 연재 「Variant와 스냅샷 캐시」의 variant는 테스트 컨테이너 계열을 식별하는 값 객체(테스트 축)였습니다. 이 연재의 Environment Variant는 브랜치로 만드는 격리된 실행 환경(공간 축의 운영 확장)입니다. 이름은 같고 축은 다릅니다 — 그리고 둘 다 "교체 가능한 접점을 깎는다"는 같은 원리를 따릅니다.
AI가 진입장벽을 낮춘 시대, 플랫폼팀이 파는 가치
마침 인프라의 진입장벽이 빠르게 낮아지는 시대입니다. 명령어를 외우지 않아도, 문서를 처음부터 끝까지 읽지 않아도, 그럴듯한 Terraform과 매니페스트가 몇 초 만에 만들어집니다. "무엇이든 만들 수 있다"가 점점 흔한 능력이 되어 갑니다. 그렇다면 클라우드플랫폼팀이 파는 가치는 무엇이어야 할까요.
flex 클라우드플랫폼팀이 내린 답은 "안전하고 빠른 변경의 피드백 루프"입니다. 무엇이든 만들 수 있는 시대일수록, 정작 희소해지는 능력은 잘못된 변경을 빨리 잡아내고 안전하게 되돌리는 일입니다. 생성은 쉬워졌지만 검증과 회수는 여전히 어렵습니다. 그리고 검증과 회수야말로 테스트 가능성과 재현 가능성의 다른 이름입니다 — apply 전에 동작을 확인할 수 있어야 빨리 잡아내고, 같은 선언이 같은 결과를 만들어야 안전하게 되돌립니다. IaS는 그래서 취향이 아니라 시대의 요구입니다.
그렇다면 한 가지 질문이 끝까지 남습니다. 다섯 축은 환경을 "바깥에서 주입한다"고 했는데 — 그 바깥은, 누가 만들까요. 그리고 브랜치 하나를 push하면 환경이 통째로 태어나는 그 일은, 도대체 어떻게 가능해졌을까요.
이 연재는 그 질문을 처음부터 끝까지 따라갑니다. 그런데 그 출발점은 의외로 소박합니다. 거창한 클러스터도, 화려한 파이프라인도 아니라 토픽 한 줄입니다.
다음 화 ▸ 코드가 모르는 그 '환경'은 누가 만드는가 — 다섯 축이 바깥으로 밀어낸 '환경'의 빈칸에 누가 서 있는지 들여다봅니다. 그리고 그 시작이 어쩌다 토픽 한 줄이었는지, 환경을 "요청"이 아니라 "선언"으로 바꾸는 일이 거기서 어떻게 출발했는지 이야기합니다.
🚀플렉스팀 채용페이지 바로가기
☕flex Private Talk 신청하기