기능(피처) 플래그는 지우지 않으면 부채가 된다 — 정리 규칙

기능 플래그를 2년 쓰다 보니 200개가 됐고, 무엇이 켜져 있는지 아무도 몰라요. 지우자니 무섭고요. 플래그가 왜 안 지워지고 쌓이는지, 만들 때부터 지울 계획을 세우는 법을 정리했어요.

기능 플래그를 잘 쓰고 있었어요. 새 기능을 안전하게 켜고 끄고, 문제가 생기면 즉시 되돌리고요.

2년이 지났어요. 플래그가 200개예요.

무엇이 켜져 있고 무엇이 꺼져 있는지 아무도 몰라요. 어떤 건 만든 사람이 퇴사했고, 어떤 건 3년째 100% 로 켜져 있는데 코드에는 여전히 꺼진 경로가 남아 있어요.

지우자니 무서워요. 무엇에 걸려 있는지 확신이 없으니까요. 그래서 아무도 안 건드리고, 다음 사람도 안 건드립니다.

플래그를 지우는 일은 아무도 급하지 않아요. 그래서 안 지워지고, 쌓이고, 결국 코드를 읽을 수 없게 만듭니다.

왜 그런가

플래그가 부채가 되는 구조에는 이유가 있어요.

만드는 건 이득이 즉시 보여요. 안전하게 배포할 수 있고, 문제가 생기면 즉시 끌 수 있고요. 그래서 만들 동기가 충분해요.

지우는 건 이득이 안 보여요. 기능이 이미 잘 돌고 있는데 코드를 건드리는 거니까요. 위험만 있고 눈에 보이는 성과가 없어요. 그래서 항상 뒤로 밀려요.

그동안 비용은 조용히 쌓여요.

먼저 코드가 복잡해져요. 조건문마다 분기가 하나씩 늘고, 중첩되면 읽기 어려워져요. 플래그 열 개가 얽힌 함수는 어떤 경로가 실제로 도는지 추적이 안 돼요.

테스트도 문제예요. 앞 편에서 본 대로 플래그 열 개면 이론상 1,024가지 조합인데, 그중 테스트되는 건 몇 개뿐이에요. 나머지 조합에서만 나타나는 버그가 생기고요.

그리고 꺼진 경로는 썩어요. 3년간 아무도 안 쓴 코드는 그동안의 변경을 못 따라갔어요. 급할 때 그걸 켜면 동작 안 할 가능성이 높아요. 안전장치인 줄 알았는데 안전하지 않은 거죠.

마지막으로 인지 부담이 커요. 코드를 읽는 사람이 매번 "이 플래그는 지금 켜져 있나"를 확인해야 해요.

코드로 보면

만들 때 지울 계획을 같이 만든다:

코드
· 플래그를 만들 때 함께 기록한다
 목적    — 무엇을 위한 플래그인가
 주인    — 누가 책임지는가
 만료일  — 언제까지 살아 있을 것인가
 종류    — 임시(출시용)인가 영구(운영 스위치)인가

· 만료일이 지나면 자동으로 드러나게 한다
 만료 지난 플래그 목록을 주간 리포트로
 또는 빌드 경고 · 정적 검사 실패

· 100% 로 켜진 지 오래된 것을 찾는다
 30일 이상 100% → 지울 후보
 30일 이상 0%   → 아예 필요 없던 기능일 수 있다

 임시 플래그와 영구 스위치를 섞지 마라
 섞이면 '지울 것' 목록이 만들어지지 않는다

✕ 문제 지점 · ✓ 해법 · 그대로 돌려 보기 전에 자기 환경에 맞게 고쳐 주세요.

실전에서는

가장 효과적인 건 임시와 영구를 구분하는 것이에요.

임시 플래그는 출시를 위한 거예요. 새 기능을 단계적으로 켜고, 다 켜지면 역할이 끝나요. 이건 반드시 지워야 해요.

영구 스위치는 운영을 위한 거예요. 부하가 높을 때 무거운 기능을 끄는 스위치, 특정 고객에게만 주는 기능, 앞 편에서 본 광고나 측정 스위치 같은 것들이요. 이건 계속 살아 있어야 해요.

둘을 섞어 두면 "지울 것" 목록이 안 만들어져요. 종류를 명시해 두면 임시만 골라 관리할 수 있어요.

만료일을 붙이는 것도 효과가 큽니다. 만들 때 "이건 6주 뒤에 지운다"고 적어 두고, 지나면 자동으로 드러나게 하는 거예요. 주간 리포트에 올리든 빌드 경고를 내든요. 사람의 의지에 맡기면 안 지워집니다.

사용 현황을 보는 것도 방법이에요. 30일 넘게 100% 로 켜져 있으면 꺼진 경로는 죽은 코드예요. 반대로 30일 넘게 0% 면 애초에 안 쓴 기능이고요. 둘 다 지울 후보입니다.

지우는 작업 자체는 대개 간단해요. 조건문을 없애고 살아남은 쪽만 남기면 돼요. 문제는 그걸 할 시간을 확보하는 거고, 그래서 정기적인 자리를 만드는 게 현실적이에요. 스프린트마다 한두 개씩 지우는 식으로요.

그리고 플래그 개수 자체를 지표로 삼으세요. 늘기만 하면 관리가 안 되고 있는 거예요.

처방

  1. 플래그를 만들 때 목적·주인·만료일·종류를 함께 기록하세요.
  2. 임시 플래그와 영구 스위치를 구분하세요. 섞이면 지울 목록이 안 만들어집니다.
  3. 만료일이 지나면 자동으로 드러나게 하세요. 사람의 의지에 맡기면 안 지워집니다.
  4. 30일 이상 100% 또는 0% 인 플래그를 정기적으로 찾으세요. 지울 후보입니다.
  5. 지우는 작업에 정기적인 자리를 만드세요. 스프린트마다 한두 개면 충분합니다.
  6. 플래그 개수를 지표로 삼으세요. 늘기만 하면 관리가 안 되는 겁니다.
  7. 오래 꺼져 있던 경로를 급할 때 켜지 마세요. 그동안 변경을 못 따라가 동작 안 할 가능성이 높습니다.
  8. 영구 스위치는 한곳에 모으세요. 흩어져 있으면 무엇이 있는지 아무도 모릅니다.
  9. 지우기 전에 실제 평가 결과를 확인하세요. 100% 인 줄 알았는데 특정 조건에서 꺼져 있을 수 있습니다.
  10. 플래그 평가 서비스가 죽었을 때의 기본값을 정해 두세요. 안 정하면 그 순간 전 서비스가 흔들립니다.

지금 확인해 보세요

플래그 재고를 센다:

코드
· 전체 개수와 추세
 늘기만 하면 관리되지 않고 있는 것이다

· 만료일이 지난 것
 목록이 자동으로 나오는가 — 사람 의지에 맡기면 안 지워진다

· 30일 이상 100% 또는 0% 인 것
 100% → 꺼진 경로는 죽은 코드
 0%   → 애초에 안 쓴 기능

· 주인이 없는 것 · 만든 사람이 떠난 것

· 평가 서비스가 죽었을 때의 기본값
 안 정해 두면 그 순간 전 서비스가 예상 못 한 동작을 한다

핵심 한 줄만들 이유는 즉시 보이고 지울 이유는 안 보인다. 그래서 쌓인다.

브루니가 적어요

색을 바꾸며 숨는 카멜레온이에요. 운영에서 실제로 터지는 문제를 한 편씩 적어요. 같은 실수를 두 번 하지 않으려고 쓰는 기록이에요.

배포·관측 글 16편 모두 보기 →