기능(피처) 플래그는 지우지 않으면 부채가 된다 — 정리 규칙
기능 플래그를 2년 쓰다 보니 200개가 됐고, 무엇이 켜져 있는지 아무도 몰라요. 지우자니 무섭고요. 플래그가 왜 안 지워지고 쌓이는지, 만들 때부터 지울 계획을 세우는 법을 정리했어요.
기능 플래그를 잘 쓰고 있었어요. 새 기능을 안전하게 켜고 끄고, 문제가 생기면 즉시 되돌리고요.
2년이 지났어요. 플래그가 200개예요.
무엇이 켜져 있고 무엇이 꺼져 있는지 아무도 몰라요. 어떤 건 만든 사람이 퇴사했고, 어떤 건 3년째 100% 로 켜져 있는데 코드에는 여전히 꺼진 경로가 남아 있어요.
지우자니 무서워요. 무엇에 걸려 있는지 확신이 없으니까요. 그래서 아무도 안 건드리고, 다음 사람도 안 건드립니다.
플래그를 지우는 일은 아무도 급하지 않아요. 그래서 안 지워지고, 쌓이고, 결국 코드를 읽을 수 없게 만듭니다.
왜 그런가
플래그가 부채가 되는 구조에는 이유가 있어요.
만드는 건 이득이 즉시 보여요. 안전하게 배포할 수 있고, 문제가 생기면 즉시 끌 수 있고요. 그래서 만들 동기가 충분해요.
지우는 건 이득이 안 보여요. 기능이 이미 잘 돌고 있는데 코드를 건드리는 거니까요. 위험만 있고 눈에 보이는 성과가 없어요. 그래서 항상 뒤로 밀려요.
그동안 비용은 조용히 쌓여요.
먼저 코드가 복잡해져요. 조건문마다 분기가 하나씩 늘고, 중첩되면 읽기 어려워져요. 플래그 열 개가 얽힌 함수는 어떤 경로가 실제로 도는지 추적이 안 돼요.
테스트도 문제예요. 앞 편에서 본 대로 플래그 열 개면 이론상 1,024가지 조합인데, 그중 테스트되는 건 몇 개뿐이에요. 나머지 조합에서만 나타나는 버그가 생기고요.
그리고 꺼진 경로는 썩어요. 3년간 아무도 안 쓴 코드는 그동안의 변경을 못 따라갔어요. 급할 때 그걸 켜면 동작 안 할 가능성이 높아요. 안전장치인 줄 알았는데 안전하지 않은 거죠.
마지막으로 인지 부담이 커요. 코드를 읽는 사람이 매번 "이 플래그는 지금 켜져 있나"를 확인해야 해요.
코드로 보면
만들 때 지울 계획을 같이 만든다:
· 플래그를 만들 때 함께 기록한다
목적 — 무엇을 위한 플래그인가
주인 — 누가 책임지는가
만료일 — 언제까지 살아 있을 것인가
종류 — 임시(출시용)인가 영구(운영 스위치)인가
· 만료일이 지나면 자동으로 드러나게 한다
만료 지난 플래그 목록을 주간 리포트로
또는 빌드 경고 · 정적 검사 실패
· 100% 로 켜진 지 오래된 것을 찾는다
30일 이상 100% → 지울 후보
30일 이상 0% → 아예 필요 없던 기능일 수 있다
임시 플래그와 영구 스위치를 섞지 마라
섞이면 '지울 것' 목록이 만들어지지 않는다✕ 문제 지점 · ✓ 해법 · 그대로 돌려 보기 전에 자기 환경에 맞게 고쳐 주세요.
실전에서는
가장 효과적인 건 임시와 영구를 구분하는 것이에요.
임시 플래그는 출시를 위한 거예요. 새 기능을 단계적으로 켜고, 다 켜지면 역할이 끝나요. 이건 반드시 지워야 해요.
영구 스위치는 운영을 위한 거예요. 부하가 높을 때 무거운 기능을 끄는 스위치, 특정 고객에게만 주는 기능, 앞 편에서 본 광고나 측정 스위치 같은 것들이요. 이건 계속 살아 있어야 해요.
둘을 섞어 두면 "지울 것" 목록이 안 만들어져요. 종류를 명시해 두면 임시만 골라 관리할 수 있어요.
만료일을 붙이는 것도 효과가 큽니다. 만들 때 "이건 6주 뒤에 지운다"고 적어 두고, 지나면 자동으로 드러나게 하는 거예요. 주간 리포트에 올리든 빌드 경고를 내든요. 사람의 의지에 맡기면 안 지워집니다.
사용 현황을 보는 것도 방법이에요. 30일 넘게 100% 로 켜져 있으면 꺼진 경로는 죽은 코드예요. 반대로 30일 넘게 0% 면 애초에 안 쓴 기능이고요. 둘 다 지울 후보입니다.
지우는 작업 자체는 대개 간단해요. 조건문을 없애고 살아남은 쪽만 남기면 돼요. 문제는 그걸 할 시간을 확보하는 거고, 그래서 정기적인 자리를 만드는 게 현실적이에요. 스프린트마다 한두 개씩 지우는 식으로요.
그리고 플래그 개수 자체를 지표로 삼으세요. 늘기만 하면 관리가 안 되고 있는 거예요.
처방
- 플래그를 만들 때 목적·주인·만료일·종류를 함께 기록하세요.
- 임시 플래그와 영구 스위치를 구분하세요. 섞이면 지울 목록이 안 만들어집니다.
- 만료일이 지나면 자동으로 드러나게 하세요. 사람의 의지에 맡기면 안 지워집니다.
- 30일 이상 100% 또는 0% 인 플래그를 정기적으로 찾으세요. 지울 후보입니다.
- 지우는 작업에 정기적인 자리를 만드세요. 스프린트마다 한두 개면 충분합니다.
- 플래그 개수를 지표로 삼으세요. 늘기만 하면 관리가 안 되는 겁니다.
- 오래 꺼져 있던 경로를 급할 때 켜지 마세요. 그동안 변경을 못 따라가 동작 안 할 가능성이 높습니다.
- 영구 스위치는 한곳에 모으세요. 흩어져 있으면 무엇이 있는지 아무도 모릅니다.
- 지우기 전에 실제 평가 결과를 확인하세요. 100% 인 줄 알았는데 특정 조건에서 꺼져 있을 수 있습니다.
- 플래그 평가 서비스가 죽었을 때의 기본값을 정해 두세요. 안 정하면 그 순간 전 서비스가 흔들립니다.
지금 확인해 보세요
플래그 재고를 센다:
· 전체 개수와 추세
늘기만 하면 관리되지 않고 있는 것이다
· 만료일이 지난 것
목록이 자동으로 나오는가 — 사람 의지에 맡기면 안 지워진다
· 30일 이상 100% 또는 0% 인 것
100% → 꺼진 경로는 죽은 코드
0% → 애초에 안 쓴 기능
· 주인이 없는 것 · 만든 사람이 떠난 것
· 평가 서비스가 죽었을 때의 기본값
안 정해 두면 그 순간 전 서비스가 예상 못 한 동작을 한다핵심 한 줄만들 이유는 즉시 보이고 지울 이유는 안 보인다. 그래서 쌓인다.