Infrastructure as Code · 상태 관리 · 이론
상태 파일이 만드는 것과 부수는 것
한 줄 요약
상태 파일은 코드와 실제 인프라를 잇는 유일한 다리이자, 잘못 다루면 팀 전체를 멈추게 하는 단일 실패 지점이다.
왜 이게 필요했나
상태 파일이 존재하는 이유는 네 가지다. 첫째 매핑이다. 코드에 적은 리소스 이름과 실제로 만들어진 리소스의 식별자를 이어 준다. 둘째 의존성 추적이다. 무엇을 먼저 지우고 무엇을 나중에 만들어야 하는지 알려면 관계를 기억해야 한다. 셋째 성능이다. 매번 모든 리소스를 조회하면 API 호출이 폭발하므로 마지막으로 본 값을 캐시처럼 쓴다. 넷째 협업이다. 팀원 사이에 같은 사실을 공유하는 기준점이 된다.
문제는 이 파일이 민감 정보를 평문으로 담을 수 있다는 점이다. DB 비밀번호나 인증서가 그대로 들어간다. 그래서 암호화된 원격 백엔드가 사실상 필수다. 출력에 sensitive = true 를 붙이는 것은 화면 마스킹일 뿐이고 상태 파일 안에서는 값이 그대로 보인다. 이 둘을 혼동하면 "가렸으니 안전하다"고 착각하게 된다.
어떻게 동작하나
동시 적용을 막는 장치가 잠금이다. apply 를 시작할 때 잠금 항목을 조건부로 생성하고, 다른 사람이 이미 잡고 있으면 충돌 에러가 난다. 여기서 자주 놀라는 지점이 대기 시간의 기본값이 0초, 즉 즉시 실패라는 것이다. 조용히 매달리는 것보다 빨리 실패해 사람이 상황을 보는 편이 낫다는 설계다.
잠금은 남기도 한다. 네트워크가 끊기거나, CI 러너가 타임아웃으로 죽거나, 누군가 Ctrl+C 로 강제 중단하면 잠금만 남는다. 강제 해제 명령이 있지만 다른 사용자가 실제로 작업 중이면 상태가 깨질 수 있으므로 최후의 수단이다. 먼저 그 잠금을 누가 언제 잡았는지 확인하는 절차가 있어야 한다.
상태는 손으로 고치는 게 아니라 전용 명령으로 다룬다. state mv 로 옮기고, state rm 으로 관리에서 빼고, import 로 이미 존재하는 리소스를 가져오고, 리팩터링은 moved 블록으로 표현한다. 특히 state rm 은 관리에서만 빼는 것이고 실제 리소스는 지워지지 않는다는 점을 정확히 알아야 한다. 이걸 삭제 명령으로 오해하면 정반대의 사고가 난다.
규모가 커지면 상태를 쪼개야 한다. 모든 것을 한 파일에 몰면 plan 이 10분 이상 걸리고 API rate limiting 이 걸린다. 네트워킹·컴퓨트·DB·모니터링처럼 컴포넌트별로 나눠 blast radius, 즉 폭발 반경을 최소화한다. 환경 분리 방식도 선택지가 있다. 워크스페이스는 코드 중복이 없지만 격리가 약하고 폭발 반경이 넓다. 디렉터리 분리는 일부 중복이 생기지만 환경별로 별도 백엔드와 IAM 을 둘 수 있어 폭발 반경이 좁다. 그래서 프로덕션은 디렉터리 분리, 단기 테스트 환경은 워크스페이스가 기본 공식이다.
현장에서 만나는 모습
드리프트는 세 유형으로 나뉜다. 속성이 바뀐 구성 드리프트, 코드 밖에서 만들어지거나 삭제된 존재 드리프트, 참조 관계가 깨진 종속성 드리프트다. 원인도 정해져 있다. 콘솔 수동 변경, 오토스케일링 같은 시스템 자동 변경, 프로바이더 업그레이드로 인한 기본값 변경, 병렬 apply.
감지는 최소 하루 한 번은 돌리고, 심각도 규칙을 붙인다. 보안그룹이나 IAM 정책 변경은 CRITICAL, 삭제나 교체 액션은 무조건 HIGH 이상이다. 다만 모든 드리프트를 감지하려 하면 false positive 가 넘쳐난다. 오토스케일러가 관리하는 desired_capacity 나 desired_size 같은 필드는 ignore_changes 로 빼야 알림이 신호로 남는다.
마지막은 문화다. 긴급 장애 대응에서 콘솔 접속을 완전히 금지하는 것은 비현실적이다. 대신 긴급 변경 후 24시간 이내에 코드를 동기화하는 문화를 정착시키고 자동 감지가 이를 감시하게 한다. 규칙으로 막는 대신 되돌아오게 만드는 설계다.
다음 확인에서 볼 것
이 모듈은 실습 없이 개념을 확인하는 퀴즈로 마친다. 앞 모듈에서 이미 상태 파일과 드리프트 감지, 잠금을 직접 만들어 봤기 때문이다. 상태 파일의 존재 이유, 민감 정보 취급, 잠금의 기본 동작과 강제 해제의 위험, 상태 분할과 폭발 반경, 드리프트 유형과 false positive 관리를 하나씩 점검한다. 헷갈리는 항목이 있다면 앞 실습의 state.json 과 apply-lock.sh 를 다시 열어 보면 좋다.