Abseil Tip 90 Retired Flags(사용 중단된 플래그)

주간 팁 #90: Retired Flags(사용 중단된 플래그)

원래 게시일: 2015년 3월 19일
작성자: Titus Winters


소개

명령줄 플래그(command-line flags)를 잘못 사용하면 플래그를 바이너리 및 프로덕션 서버에서 안전하게 제거하는 것이 어려워집니다. (주간 팁 #45에서 다룬 플래그의 잘못된 사용 사례를 참고하세요.)

문제는 무엇일까요? 정의되지 않은 플래그를 지정하면 바이너리가 시작되지 않기 때문에, 플래그를 제거하려면 C++ 코드와 작업 실행 스크립트 및 구성 간의 조정이 필요할 수 있습니다.

일부 경우에는 이러한 조정이 상당히 어려울 수 있습니다(예: 바이너리 버전에 따라 프로덕션 코드를 조건부로 처리하는 경우). 더 나은 방법이 있다면 좋겠죠? 다행히 있습니다!

C++ 명령줄 플래그 시스템에 “Retired Flags”(ABSL_RETIRED_FLAG)이라는 개념이 추가되었습니다.


Retired Flag란 무엇인가요?

Retired Flag는 다음과 같은 특징을 가집니다:

  • C++에서 심볼을 생성하지 않습니다(FLAGS_some_flag 같은 전역 변수를 생성하지 않음).
  • --help에 표시되지 않습니다.
  • 명령줄에서 지정해도 허용되지만, ERROR가 로그로 기록됩니다.

이 방식으로 더 이상 코드에서 사용되지 않는 플래그를 “Retired(사용 중단)” 상태로 전환할 수 있습니다. 이렇게 하면 C++ 코드 변경과 프로덕션 구성 변경을 분리할 수 있습니다. 프로덕션 구성 변경이 완료되면, 해당 플래그를 완전히 제거할 수 있습니다.

Retired Flag는 다양한 상황에서 사용되도록 설계되었습니다(예: 저장소 간 비원자적 커밋 요구 사항이 있는 경우). 아래는 간단한 플래그를 사용 중단하는 단계별 절차입니다.


플래그 사용 중단 단계별 절차

  1. 코드에서 FLAGS_frobber의 사용을 제거합니다.
    명령줄 플래그를 주로 main()에서 사용하도록 권장한 주간 팁 #45를 따랐다면, 플래그 사용을 제거하는 작업이 간단하고 확인하기도 쉬울 것입니다.

  2. 플래그 정의를 “Retired” 상태로 변경합니다.
    기존 플래그 정의가 다음과 같다면:
    ABSL_FLAG(type, frobber, "default", "Which frobber to use?");
    

    이를 다음과 같이 변경합니다:

    ABSL_RETIRED_FLAG(type, frobber, "default", "retired");
    
  3. 바이너리 릴리스를 기다립니다.
    모든 작업이 새로운 바이너리를 사용하도록 업데이트되면 다음 단계로 진행할 수 있습니다.

  4. 프로덕션 구성에서 플래그를 제거합니다.
    관련 프로덕션 구성에서 frobber 플래그가 더 이상 사용되지 않는 것을 확인한 후 다음 단계로 진행합니다.

  5. Retired Flag를 제거합니다.
    이제 플래그를 완전히 제거할 수 있습니다.

복잡한 플래그 제거의 성공 사례

Retired Flag 시스템은 매우 복잡한 플래그 제거 작업에도 성공적으로 사용되었습니다. 이 기능의 동기는 레거시 내부 파일 시스템에서 정의된 플래그를 제거하는 데서 비롯되었습니다. 이 플래그는 라이브러리에 정의되어 있어 여러 바이너리에서 사용되었습니다. 우리가 경험한 바로는, 이 시스템을 사용하면 가장 복잡한 플래그 제거 작업도 안전하게 수행할 수 있습니다.

다음에 플래그를 안전하게 제거하는 방법을 고민한다면, 먼저 플래그를 “Retire” 상태로 전환하고 단계별로 진행하는 것을 고려해 보세요.