← 모든 글

feature flag 는 왜 죽지 않는가

플래그를 만들 때는 치울 생각을 안 한다. 그 이유와 잔존 패턴 정리.

플래그를 만든 날, 치울 날짜를 적어둔 팀이 얼마나 될까. 우리 팀은 적어두지 않았다. 그래서 지금 코드베이스에 플래그가 31개 있고, 그 중 내가 켜진 이유를 설명할 수 있는 건 절반이 안 된다.

만들기는 쉽고 지우기는 무섭다

플래그를 추가하는 건 2분이다. 환경 변수 하나, 분기 한 줄. 반면 지우는 건 “혹시 아직 누가 false 로 쓰고 있으면?” 이 질문이 발목을 잡는다.

실제로 이런 일이 있었다. 작년에 결제 플로우 A/B 테스트용으로 만든 payment_v2_enabled 플래그가 있었다. 테스트 종료 후 v2 가 default 가 됐는데도 플래그를 안 지웠다. 6개월 뒤 신규 입사한 팀원이 이 플래그를 보고 “이걸 끄면 v1 으로 롤백되나?” 라고 물었다. 그때서야 코드를 따라가봤더니, false 분기 코드는 이미 반쯤 죽어있었다. API 엔드포인트가 deprecated 된 것도 있었고, 일부는 DB 스키마가 바뀌어서 실제로 false 로 바꾸면 500 이 났다. 무서워서 그냥 냅뒀다. 그게 지금 31개의 시작이다.

오너십이 없으면 플래그는 고아가 된다

플래그를 만든 사람이 팀을 떠나면, 그 플래그는 사실상 고아다. README 에 “누가 받고 / 누가 백업”을 적어두는 것처럼 플래그에도 오너가 있어야 하는데, 우리는 그냥 코드 속에 묻어뒀다.

ENABLE_NEW_ONBOARDING 이라는 플래그가 대표적이다. 이걸 만든 팀원은 이미 다른 팀으로 이동했고, flag management 도구에 description 도 없다. 켜진 지 14개월이 됐다. 플래그 이름만 보면 켜야 할 것 같고, 코드를 열어보면 false 분기에 로직이 아직 남아있다. 결국 아무도 손을 못 댄다. 고아 플래그의 수명은 무한에 수렴한다.

청소 회의는 열리지 않는다

분기마다 “플래그 정리 회의” 하자고 말한다. 이번 분기도 말했다. 안 열렸다.

이유는 단순하다. 우선순위 싸움에서 항상 진다. 신규 기능, 버그, 온콜 대응 — 이것들이 다 끝나면 플래그 정리를 하겠다는 말은 “영원히 안 하겠다”의 다른 표현이다. 한 번은 진짜로 정리 시간을 스프린트에 박아봤다. 4시간 블록. 실제로 쓴 시간은 45분이었고, 지운 플래그는 3개였다. 나머지 시간은 “이거 지워도 되나” 확인하는 데 사라졌다. 확인이 이렇게 오래 걸리는 이유는 플래그가 만들어질 때 컨텍스트를 안 적어뒀기 때문이다. 닭이 먼저냐 달걀이 먼저냐 같은 문제다.

플래그가 플래그를 낳는다

막상 해보면, 플래그 하나를 지우다가 새 플래그가 필요해지는 상황이 온다. 이게 생각보다 자주 일어난다.

dark_mode_beta 를 지우려고 코드를 정리하다 보니, 이 플래그가 analytics_v3_enabled 와 맞물려 있었다. dark_mode_beta 가 true 일 때만 v3 이벤트를 찍고 있었던 거다. 이걸 정리하면 analytics 가 깨지니까, 정리 전에 analytics 분리 작업이 먼저 필요했다. 분리 작업을 안전하게 하려면? 플래그 하나 더. 결국 지우러 갔다가 하나 더 생겼다. 31개가 줄지 않는 이유가 여기 있다.

자동화로 막으려 했던 것

이 문제를 코드 리뷰로 막으려는 시도도 했다. PR 에 feature flag 가 추가되면 expiry_date 필드를 필수로 달도록 린트 룰을 만들었다. 처음 두 달은 잘 됐다. 그다음부터는 expiry_date: 9999-12-31 이 기본값처럼 쓰이기 시작했다.

사람은 강제를 피하는 방법을 찾는다. 린트를 통과하는 게 목적이 돼버리면, 의미 있는 날짜를 적는 게 아니라 통과하는 날짜를 적는다. 결국 자동화는 형식만 남았다. 숫자가 있으면 된다는 착각. 지금은 그 필드를 살려두되, CI 에서 expiry 를 넘긴 플래그 목록을 슬랙에 주 1회 뿌리는 방식으로 바꿨다. 알림이 오면 최소한 한 번은 눈에 띄니까. 그게 지금 가장 잘 작동하는 방법이다.

다음 한 가지

플래그를 새로 만들 때, PR description 첫 줄에 “이 플래그는 언제 지운다 / 누가 지운다” 한 줄을 의무화한다 — 자동화 말고, 리뷰어가 없으면 merge 를 안 하는 방식으로.


🛒 이 글과 어울리는 추천 상품

위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.