피처 플래그 란? 새벽 3시 장애에서 배포 없이 되돌리기

요약

피처 플래그는 코드 안에서 실행 시점에 값을 읽어 코드 경로를 켜고 끄는 분기점입니다. 빌드나 배포 없이 장애 중인 변경을 끌 수 있어 릴리스의 영향 범위를 조절하는 다이얼 역할을 합니다. 종류별 수명 관리와 제거 계획이 함께 있어야 안전합니다.

피처 플래그 토글 스위치가 놓인 어두운 제어 패널과 야간 운영 데스크

새벽 3시 12분입니다. 결제 오류율이 방금 4%를 넘었습니다. 문제의 변경은 여섯 시간 전에 배포됐습니다. 같은 릴리스에 무관한 수정 두 개가 함께 들어 있어서 전체를 되돌리고 싶은 사람은 없습니다. 이 상황에서 피처 플래그 란 무엇일까요? 피처 플래그는 코드 안의 조건문입니다. 실행 시점에 외부 값을 읽어서 어떤 코드 경로가 실행될지 결정합니다. 플래그를 끄면 새 경로는 빌드도 배포도 없이 실행을 멈춥니다. 개념은 이것이 전부입니다. 나머지는 운영의 일입니다.

피처 플래그는 정확히 무엇이고, 무엇이 아닌가

피처 플래그는 결정 지점입니다. 코드 어딘가에 if가 있고, 그 값은 바이너리 바깥에서 옵니다. 설정 서비스, 데이터베이스 행, 벤더 SDK, 재시작 없이 바꿀 수 있는 환경 변수가 그 출처입니다.

const useNewPricing = await flags.isEnabled("new-pricing-engine", {
  userId: user.id,
  plan: user.plan,
  region: request.region,
});

return useNewPricing
  ? newPricingEngine.quote(cart)
  : legacyPricing.quote(cart);

이 코드에서 세 가지가 따라옵니다. 첫째, 이전 경로도 여전히 존재해야 하고 제대로 동작해야 합니다. 둘째, 누가 요청했는지 알려 주는 문맥이 있어야 단순한 켜기와 끄기보다 똑똑한 판단이 가능합니다. 셋째, 플래그 평가는 요청의 핫 패스에 놓이므로 평가 지연 시간과 실패 방식이 이제 여러분의 문제가 됩니다.

'피처 토글'과 '피처 플래그'를 섞어 쓰는 사람이 많은데, 용어는 중요하지 않습니다. 중요한 것은 동작입니다. 코드 배포와 기능 릴리스를 분리하는 것입니다. 코드는 비활성 상태로 프로덕션에 올라가고, 누구에게 보여줄지는 나중에 사람이나 시스템이 정합니다.

플래그에는 네 가지 종류가 있고, 섞으면 아프다

플래그 때문에 생기는 고통 대부분은 모든 플래그를 같은 것으로 취급하는 데서 옵니다. Martin Fowler의 피처 토글 분류는 플래그가 얼마나 오래 살고 결정이 얼마나 동적인지를 기준으로 나눕니다. 실무에서도 잘 맞습니다.

릴리스 토글은 과도기적입니다. 완성되지 않은 작업을 플래그 뒤에 숨겨서 매일 트렁크에 병합할 수 있게 합니다. Fowler는 이런 토글이 1~2주를 넘기지 않아야 한다고 권합니다. 결정은 정적입니다. 같은 릴리스에 대한 모든 요청은 같은 답을 받습니다.

실험 토글은 사용자마다 다른 변형으로 보냅니다. 통계적 유의성에 도달할 만큼만 살아 있어야 하며, 기간은 몇 시간에서 몇 주입니다. 결정은 요청마다 이뤄집니다.

운영 토글은 운영 동작을 제어합니다. 부하가 걸리면 중요하지 않은 기능을 끄고, 대체 의존성으로 전환하고, 비싼 쿼리를 비활성화합니다. 그중 일부는 오래 살아남는 킬 스위치가 됩니다. 이들은 몇 초 안에 뒤집혀야 하므로 릴리스가 필요한 방식은 쓸 수 없습니다.

권한 토글은 플랜이나 자격에 따라 기능을 막습니다. 몇 년씩 살 수 있고, 결정은 매 요청마다 사용자 단위로 이뤄집니다.

실수는 네 가지 모두에게 같은 수명 주기를 주는 것입니다. 권한 토글에는 영원히 소유자와 감사 기록이 필요합니다. 릴리스 토글은 만드는 날 삭제 날짜가 필요합니다. 이름만 보고 플래그의 종류를 알 수 없다면, 어떤 플래그를 안전하게 지워도 되는지도 알 수 없습니다.

어두운 제어 캐비닛의 빨간 킬 스위치 레버를 당기는 손

플랫폼 팀이 보는 것: 폭발 반경을 조절하는 장치

플랫폼 팀에게 흥미로운 속성은 A/B 테스트가 아닙니다. 플래그가 릴리스를 사건에서 다이얼로 바꾼다는 점입니다.

플래그가 없으면 배포 한 번에 트래픽 100%가 변경에 노출됩니다. 유일한 되돌리기는 또 다른 배포이고, 그 시간은 파이프라인이 걸리는 시간에 사람이 확신을 얻는 시간을 더한 것입니다. 플래그가 있으면 사용자 1%에게만 노출하고, 오류율과 p99를 지켜본 뒤 5, 25, 50으로 올릴 수 있습니다. 폭발 반경은 여러분이 고른 비율이고, 되돌리기는 몇 초 안에 전파되는 설정 변경입니다.

이 속성은 대부분의 도구 투자보다 평균 복구 시간(MTTR)을 더 크게 바꿉니다. 사후 분석의 질문은 "롤백에 왜 40분이 걸렸나"에서 "왜 이것을 플래그 뒤에 두지 않았나"로 바뀝니다.

다만 롤아웃 다이얼에는 함정이 있습니다. 누군가는 신호를 보고 다이얼을 돌려야 합니다. 새벽 3시에 그 사람은 지쳐 있습니다. 쓸 만한 플래그 시스템은 다이얼을 서비스 수준 목표(SLO)에 묶습니다. 오류율이 정해진 예산 비율을 태우면 사람의 개입 없이 롤아웃이 멈추고 되돌아갑니다. 대부분의 팀은 알림 도구에서 플래그 API로 가는 웹훅을 직접 만들어 이것을 구현합니다. 몇백 줄이면 되고, 처음 울리는 밤에 본전을 뽑습니다.

청구서가 도착합니다: 플래그 부채와 Knight Capital의 교훈

플래그를 하나 추가할 때마다 이론상 그 코드의 경로 수가 두 배가 됩니다. 실제로는 몇 가지 조합만 테스트하고 나머지는 운에 맡깁니다. Fowler는 플래그를 보유 비용이 있는 재고로 다루라고 권합니다. 플래그를 만들 때 제거 작업을 백로그에 올리고, 만료일을 붙이고, 가장 엄격한 팀은 만료된 플래그가 코드에 남아 있으면 빌드가 실패하도록 만듭니다.

이 교훈에서 가장 비싼 사례는 Knight Capital입니다. 2012년 8월 1일, 새 배포가 한때 퇴역한 기능을 제어하던 오래된 플래그 이름을 재사용했습니다. 한 서버는 배포를 놓쳐서 여전히 옛 코드를 돌리고 있었습니다. 개장 후 첫 45분 동안 회사의 라우터는 고객 주문 212건을 체결하려 하면서 400만 건이 넘는 주문을 시장에 보냈습니다. SEC의 Knight Capital 명령에 기록된 내용입니다. Fowler의 글도 이 사고의 손실 약 $460M을, 관리되지 않는 플래그에 대한 경고 사례로 언급합니다.

플래그만의 실패는 아니었습니다. 수동 배포, 킬 스위치의 부재, 느린 감지가 함께 작용했습니다. 하지만 죽은 플래그 이름을 재사용했다는 세부 사항은 모든 플랫폼 팀이 벽에 붙여 둘 만합니다. 플래그 이름은 절대 재사용하지 마십시오. 옛 플래그를 지우고 새로 만들며, 제거를 정식 단계로 만드십시오.

메모장에 손으로 그린 흐름도 옆에 키보드와 노트북이 놓인 나무 책상

직접 만들까, 플래그 플랫폼을 살까

직접 만든 플래그 시스템은 설정 파일과 불리언 하나로 시작합니다. 한 서비스의 첫 열 개 남짓한 릴리스 토글까지는 괜찮습니다. 사용자별로 고정되는 비율 롤아웃, 세그먼트별 타깃팅 규칙, 누가 무엇을 바꿨는지 남는 감사 로그, 그리고 설정 저장소에 몰리지 않으면서 몇 초 안에 모든 인스턴스에 닿는 플래그 변경이 필요해지면 더 이상 괜찮지 않습니다.

그 시점에는 측정 가능한 기준으로 플랫폼을 비교하게 됩니다. SDK 평가 지연 시간(로컬 평가 대 네트워크 호출), 업데이트 방식(스트리밍 대 폴링), 타깃팅 규칙의 세밀함, 다중 환경 지원, 그리고 트래픽에 따라 요금이 어떻게 늘어나는지를 봅니다.

요금 체계는 기능 목록보다 더 많이 다릅니다.

LaunchDarkly는 이 범주의 기준이 되는 구현입니다. 타깃팅이 성숙했고, 보호된 릴리스(guarded releases)와 깊은 연동 표면을 갖췄습니다. 사용량 기반 요금제는 서비스 연결 수와 클라이언트 측 월간 활성 사용자 천 명 단위로 과금합니다. 그래서 익명 사용자가 많은 소비자 앱은 백엔드 전용 팀이 겪지 않는 방식으로 청구서가 움직일 수 있습니다. 엔터프라이즈 규모의 거버넌스와 감사가 필요하다면, 가장 오랫동안 다듬어 온 제품이라는 장점은 실재합니다.

Statsig는 플래그를 실험 및 제품 분석과 묶어 제공하고, 이벤트 수를 기준으로 과금합니다. 플래그를 주로 실험 표면으로 쓰는 팀에게 맞습니다. 주로 운영 토글과 킬 스위치가 목적이라면, 읽지 않을 분석 기능에 돈을 내는 셈입니다. 이 벤더는 2025년 9월 이후 소유주가 두 번 바뀌었으니, 벤더 리스크 검토에 한 줄 적어 둘 만합니다.

어떤 것을 고르든 계약 전에 실패 방식을 테스트하십시오. 스테이징에서 SDK의 네트워크 접근을 차단하고 애플리케이션이 무엇을 하는지 확인하십시오. 좋은 SDK는 마지막으로 알려진 플래그 값을 캐시에서 제공하고, 크게 로그를 남깁니다. 나쁜 SDK는 요청 경로를 막습니다.

관측 가능성은 플래그 시스템의 절반입니다

텔레메트리 없는 플래그는 추측입니다. 최소한의 쓸 만한 설정은 요청의 모든 트레이스와 로그 줄에 플래그 상태를 붙이는 것입니다. 그래야 오류가 급증했을 때 플래그 변형별로 묶어서 새 경로가 원인인지 확인할 수 있습니다.

Datadog 같은 올인원 플랫폼은 SDK가 스팬에 태그를 붙이기만 하면 변형별 분석을 쉽게 만듭니다. 다만 플래그 키, 변형, 사용자 세그먼트처럼 카디널리티가 높은 태그를 더하면 호스트별, 시그널별 과금이 빠르게 늘어납니다. 어떤 차원을 태그로 붙일지 신중하게 고르십시오.

이미 Prometheus와 OpenTelemetry를 운영하고 있다면 Grafana가 더 저렴한 길입니다. 플래그를 인식하는 대시보드는 직접 만들어야 하므로 엔지니어링 시간이 들지만, 내보내는 레이블을 완전히 통제할 수 있습니다. 플랫폼 그룹이 있는 50~500명 규모의 조직이라면 이 교환이 맞는 경우가 많습니다.

파란색과 호박색 조명이 켜진 서버 랙 통로를 걸어가는 엔지니어

첫 플래그를 프로덕션에 올리는 짧은 런북

플래그가 없는 팀에 플래그를 도입한다면, 첫 롤아웃은 지루하게 진행하십시오.

  1. 결제 오류율이나 특정 엔드포인트의 p99 지연 시간처럼 성공 지표가 분명한 변경 하나를 고릅니다.

  2. 플래그 이름에 종류와 소유자를 담습니다. 예를 들어 release.checkout.new-tax-calc.owner-payments처럼 짓습니다.

  3. 지금 제거 티켓을 쓰고, 2주 이내의 만료일을 붙입니다.

  4. 1%에서 롤아웃하고, 트래픽 주기 한 바퀴를 온전히 지켜본 뒤 올립니다. 되돌릴 임계값은 미리 정합니다.

  5. 되돌리기는 명령 한 줄이나 버튼 하나로 만듭니다. 밤에 필요해지기 전에 스테이징에서 한 번 리허설합니다.

  6. 100%가 며칠 유지되면, 같은 변경에서 플래그와 옛 코드 경로를 함께 삭제합니다.

재미없는 부분은 6번입니다. 이 단계를 건너뛴 팀은 결국 수백 개의 플래그를 갖게 됩니다. 그중 절반이 무엇을 하는지 아는 사람이 없고, 저장소 안에는 Knight Capital 같은 위험이 자리 잡습니다.

마지막 장애가 플래그 뒤에 있었다면 어땠을까

팀이 마지막으로 정리한 프로덕션 장애를 떠올려 보십시오. 세 가지를 물어보십시오. 그 변경은 비활성 상태로 나갈 수 있었나요? 배포 없이 한 사람이 1분 안에 끌 수 있었나요? 어떤 변형이 실패하는지 알림이 알려 줬을까요?

답이 모두 아니오라면, 첫 번째 플래그 후보와 오늘 되돌리기에 드는 비용에 대한 첫 번째 정직한 추정치를 얻은 셈입니다. 사후 분석은 자기 할 말을 할 것입니다. 더 나은 질문은 온콜 알림이 울렸을 때, 그 피해를 얼마나 줄일 수 있었느냐입니다.

자주 묻는 질문

피처 플래그와 피처 토글은 같은 것인가요?
네, 같은 개념입니다. 중요한 것은 이름이 아니라 코드 배포와 기능 릴리스를 분리한다는 동작입니다.
플래그는 얼마나 오래 두어야 하나요?
릴리스 토글은 보통 1~2주를 넘기지 않아야 합니다. 권한 토글처럼 장기 플래그는 소유자와 감사 기록을 두고 관리합니다.
플래그를 끄면 바로 되돌아가나요?
설정 변경이 각 인스턴스에 전파되는 데 몇 초가 걸립니다. 옛 경로의 코드가 아직 배포되어 있어야 하므로, 코드를 제거하기 전까지만 즉시 되돌리기가 가능합니다.
직접 플래그 시스템을 만들어야 하나요?
불리언 몇 개와 설정 파일로 시작할 수 있습니다. 사용자별 고정 비율, 세그먼트 타깃팅, 감사 로그가 필요해지면 플랫폼 도입을 검토합니다.
플래그가 많아지면 어떤 위험이 있나요?
경로 조합이 늘어나 테스트가 어려워지고, 오래된 플래그 이름을 재사용하면 Knight Capital 사례처럼 큰 사고로 이어질 수 있습니다.