Abseil LTS vs HEAD 릴리스 모델 분석
한 줄 요약: Abseil의 HEAD는 Google이 사내에서 쓰는 모델이고, LTS는 외부 사용자를 위한 1년 두 번의 snapshot이다. 두 모델은 API 변경 정책과 마이그레이션 부담이 다르다.
#어떤 문제를 푸는가
라이브러리 사용자는 “내가 의존하는 코드가 언제 바뀌는가”를 알고 싶다. 두 가지 극단이 있다.
- 고정 버전 모델 — 정해진 버전을 박제하고, 사용자가 명시적으로 올릴 때만 변경.
- Live at Head 모델 — 항상 최신 commit을 따라가고, 변경이 들어오면 사용자 코드도 같이 고침.
Google은 후자를 신봉한다. monorepo + 사내 빌드 인프라가 있기 때문에 가능하다. 외부 사용자는 그렇지 않다. 그래서 두 모델이 공존한다.
#HEAD 모델
HEAD는 abseil-cpp의 main 브랜치 그 자체다. Google 사내 코드와 동일한 commit이 올라온다.
# Bazel WORKSPACE — HEAD를 추적http_archive( name = "com_google_absl", strip_prefix = "abseil-cpp-master", urls = ["https://github.com/abseil/abseil-cpp/archive/refs/heads/master.zip"],)#HEAD를 쓰는 프로젝트
- Google 사내 (당연)
- TensorFlow, gRPC, Protocol Buffers, Envoy — Google이 주도하거나 깊이 협력하는 프로젝트
- 일부 large-scale 인프라 (Kubernetes의 일부)
이들은 자체 CI에서 매일 또는 매주 Abseil HEAD를 끌어와 빌드하고, 깨지면 즉시 고친다.
#HEAD의 정책
breaking change는 사전 공지와 함께 일어난다. deprecation 후 일정 기간 후 제거.
- 새 API 추가는 언제든 가능
- 기존 API 변경은 deprecation period 후
- 일부 변경은 자동 마이그레이션 도구(clang-tidy, abseil-fix)와 함께 배포
#HEAD의 비용
- 매 commit이 깨질 가능성 — CI가 필수
- 자체 마이그레이션 책임 — Google이 사내를 고쳐도 외부는 자기 코드를 자기가 고쳐야 함
- documentation 부족 — 변경 사항이 commit message에만 있을 수 있음
#LTS 모델
LTS는 6개월~1년에 한 번 main을 잘라 태그를 붙인 snapshot이다.
20240722.0 ← 2024년 7월 22일20240116.0 ← 2024년 1월 16일20230802.0 ← 2023년 8월 2일20230125.0 ← 2023년 1월 25일날짜 형식 자체가 버전이다. semver를 따르지 않는다. 이유는 “API 변경의 종류를 미리 분류하지 않는다”는 정책 때문이다.
#LTS의 정책
한 LTS 안에서는 patch만 들어간다. API는 동결.
- 같은 LTS에 대한 패치는 보안 수정과 critical bug fix만
- 새 LTS는 1년에 두 번 정도 잘림
- 새 LTS에서는 breaking change가 일어날 수 있음
#LTS를 쓰는 프로젝트
- vcpkg, Conan, apt, brew의 모든 사용자
- monorepo가 아닌 일반 enterprise 프로젝트
- 외부 dependency 정책상 버전 pin이 필수인 환경
#모델 비교
| 항목 | HEAD | LTS |
|---|---|---|
| 추적 대상 | main 브랜치 | 날짜 태그 (예: 20240722.0) |
| 갱신 빈도 | 매 commit | 6~12개월 |
| API 변경 | 언제든 (deprecation 후) | 같은 LTS 내에서는 없음 |
| CI 필요성 | 매일 빌드 권장 | 새 LTS 도입 시점에만 |
| 자동 마이그레이션 도구 | 일부 제공 | LTS 간에는 직접 처리 |
| 외부 패키지 매니저 | 미지원 | 지원 |
| 적합한 프로젝트 | Google, monorepo, 인프라 | 일반 enterprise, 외부 라이브러리 |
#어느 쪽을 골라야 하는가
세 가지 질문으로 답할 수 있다.
- CI에 매일 Abseil HEAD를 빌드할 인프라가 있는가? 없다면 LTS.
- breaking change가 들어왔을 때 코드를 24시간 안에 고칠 수 있는가? 없다면 LTS.
- TensorFlow / gRPC 같은 HEAD-기반 라이브러리를 직접 의존하는가? 그렇다면 HEAD.
일반적인 답은 LTS다. HEAD를 쓰는 외부 프로젝트는 인프라 비용이 상당하다.
#LTS 간 마이그레이션
LTS에서 다음 LTS로 올라갈 때 무엇이 일어나는가. 예를 들어 20240116.0에서 20240722.0 사이의 주요 변경은 다음과 같다.
absl::Hash의 internal state layout 변경 — ABI 영향absl::flat_hash_map의 default size 변경 — 성능 영향absl::LogSink인터페이스에 새 메서드 추가 — virtual override 영향- 일부 deprecation 제거 (이전 LTS에서 deprecate된 것)
마이그레이션 비용은 다음에 비례한다.
- 코드베이스에서 Abseil API 사용 빈도
- 사용자 코드가 deprecated API를 얼마나 의존하는지
- 다른 third-party (gRPC 등)가 같은 Abseil 버전에 동의하는지
#breaking change 패턴
Abseil이 API를 deprecate하는 방식은 일관적이다.
// Step 1: 새 API 도입absl::Status NewAPI();ABSL_DEPRECATED("Use NewAPI()") absl::Status OldAPI();
// Step 2: 일정 기간 후 — Google 사내 마이그레이션 완료// 외부 사용자에게는 next LTS까지 시간을 줌
// Step 3: 다음 LTS에서 제거// 또는 HEAD에서 즉시 제거ABSL_DEPRECATED macro는 컴파일러의 [[deprecated("...")]] attribute로 확장된다.
#코드 리뷰 포인트
# 리뷰 질문 1: 어느 모델을 쓰는가?FetchContent_Declare(absl GIT_TAG 20240722.0) # LTSFetchContent_Declare(absl GIT_TAG master) # HEAD — CI 가능?// 리뷰 질문 2: deprecated API를 쓰는가?absl::Status s = OldAPI();// 컴파일러 경고 무시하지 말 것. 다음 LTS에서 제거될 수 있음.
// Good — 권장 API로 옮기기absl::Status s = NewAPI();# 리뷰 질문 3: HEAD를 쓰는데 lock이 없는가?git_repository(name = "absl", branch = "master") # 매 빌드마다 다른 commit리뷰에서 모델 선택이 명시되어야 한다. 의도 없이 HEAD를 따라가는 프로젝트가 가장 위험하다.
#자주 보는 안티패턴
# 회피 — LTS를 쓰는데 sha256를 빼먹음FetchContent_Declare( absl GIT_REPOSITORY https://github.com/abseil/abseil-cpp.git GIT_TAG 20240722.0)# 위 코드는 동작하지만 reproducibility가 약하다. commit이 force-push되면?
# Good — 가능하면 commit hash 또는 archive sha256FetchContent_Declare( absl URL https://github.com/abseil/abseil-cpp/releases/download/20240722.0/abseil-cpp-20240722.0.tar.gz URL_HASH SHA256=f50e5ac311a81382da7fa75b97310e4b9006474f9560ac46f54a9967f07d4ae3)// 회피 — version detection을 컴파일러에서 #if로 분기#if defined(ABSL_LTS_RELEASE_VERSION) && ABSL_LTS_RELEASE_VERSION >= 20240722 // ...#endif// 가능은 하지만 권장하지 않음. 한 LTS 안에서 일관된 코드 쓰는 게 낫다.#두 모델의 미래
Abseil 팀은 LTS를 “권장” 모델로 점차 자리잡게 하고 있다. 외부 ecosystem이 LTS에 묶여 있어 사실상 그쪽이 default다. HEAD는 Google 사내와 일부 깊은 협력 프로젝트의 것으로 남는다.
#정리
- HEAD는 main을 직접 추적. Google 사내, TF, gRPC 등.
- LTS는 6~12개월에 한 번 잘리는 snapshot. 외부 사용자 대부분.
- 한 LTS 안에서는 patch만, 다음 LTS에서는 breaking change 가능.
- 리뷰에서는 모델 선택이 명시적인지, 버전 pin이 sha256까지 내려가는지 확인.
#다음 편
Part 1-05에서 versioning과 ABI 호환성을 깊이 본다. inline namespace로 어떻게 빌드 옵션을 인코딩하는지, ABI break를 컴파일 시점에 잡는 메커니즘을 다룬다.
#관련 항목
Abseil Code Review · 5 of 79
- 1 Abseil Code Review — Google production-grade C++ 라이브러리 분석
- 2 Abseil 개요 — Google이 std를 보완한 이유
- 3 Abseil 설계 철학 — std 호환과 추가 기능의 균형
- 4 Abseil 빌드와 의존성 — Bazel vs CMake
- 5 Abseil LTS vs HEAD 릴리스 모델 분석
- 6 Abseil Versioning과 ABI 호환성 정책
- 7 Abseil 매크로 — ABSL_HAVE_*·ABSL_ATTRIBUTE_*
- 8 Abseil ABSL_PREDICT_TRUE/FALSE — branch hint
- 9 absl::LogSeverity — 로그 레벨 타입
- 10 Abseil type_traits — negation·conjunction·void_t
- 11 Abseil Conformance·Policy 분석
- 12 Abseil Memory utilities 분석
- 13 Abseil raw_logging — heap-free 로깅
- 14 Abseil thread_annotations — clang TSA 통합
- 15 absl::Status — exception-free error handling
- 16 absl::StatusOr<T> — 값 또는 에러
- 17 absl status_macros — ASSIGN_OR_RETURN·RETURN_IF_ERROR
- 18 absl::Status payload — 구조화된 에러 컨텍스트
- 19 absl::Status ↔ exception 변환 패턴
- 20 absl::string_view — non-owning 문자열 참조
- 21 absl::string_view 함정 — dangling·c_str·임시 객체
- 22 absl::StrCat — 가변 인자 문자열 연결과 AlphaNum
- 23 absl::StrSplit — Delimiter·Predicate·컨테이너 변환
- 24 absl::StrJoin — 컨테이너 결합과 Formatter
- 25 absl::StrFormat — type-safe printf·FormatSpec
- 26 Abseil ASCII 함수 — locale-free 분류·대소문자 변환
- 27 Abseil Escape — CEscape·HexEscape·Base64
- 28 absl::flat_hash_map — Swiss Table 기반 hash map
- 29 absl::flat_hash_set — set 버전 Swiss Table
- 30 absl::node_hash_map — stable pointer가 필요할 때
- 31 absl::btree_map — sorted·cache-friendly B-tree
- 32 absl::FixedArray — 런타임 크기 stack 배열
- 33 absl::InlinedVector — small buffer optimization
- 34 Abseil Swiss Table internals — control byte·SIMD probing
- 35 absl::Mutex — reader-writer·fairness·deadlock 검출
- 36 absl::Mutex Conditional Critical Section — Await로 cv 없애기
- 37 absl::Notification — once-only signal
- 38 absl::BlockingCounter·Barrier — 다중 thread 조율
- 39 absl::Mutex annotations — clang thread-safety로 race를 컴파일 타임에
- 40 absl::Time·Duration 분석 — 단단한 type
- 41 absl::Time Format·Parse
- 42 absl::CivilTime 분석
- 43 absl::time_zone 분석
- 44 absl::Time mocking — 테스트 친화 시간
- 45 absl::BitGen — 모던 난수 생성기
- 46 Abseil Random Distributions — Uniform·Exponential
- 47 Abseil Mocking Random — 테스트 결정성
- 48 Abseil Random Seeding·Entropy
- 49 absl::int128·uint128 분석
- 50 absl::bits — popcount·countl_zero
- 51 absl::optional vs std::optional
- 52 absl::variant 분석
- 53 absl::span 분석
- 54 absl::any 분석
- 55 absl::compare — three-way 비교
- 56 Abseil utility — apply·in_place
- 57 Abseil AbslHashValue 분석
- 58 Abseil HashState chaining
- 59 Abseil Custom hashable 구현
- 60 Abseil LOG·VLOG·CHECK 분석
- 61 Abseil LogSink 분석
- 62 Abseil LogEntry·structured logging
- 63 Abseil Stack trace·failure_signal_handler
- 64 ABSL_FLAG 정의 분석
- 65 Abseil ParseCommandLine 동작
- 66 Abseil Flag introspection·validation
- 67 Google 스타일의 Abseil 사용 패턴
- 68 Abseil 자주 보는 anti-pattern
- 69 std → absl 마이그레이션 전략
- 70 absl::Cleanup — 함수 종료 시 실행 보장
- 71 Abseil algorithm container 확장 — c_sort·c_find_if·c_count_if
- 72 absl::function_ref와 any_invocable — 함수 객체 전달의 두 축
- 73 absl::bind_front와 Overload — 함수 객체 보조 도구
- 74 absl::Cord — 분산 시스템용 대용량 문자열
- 75 absl::from_chars·SimpleAtoi — 빠른 숫자 변환
- 76 absl::Cord vs std::string — 선택 기준과 메모리 프로파일
- 77 absl::GetStackTrace와 Symbolize — crash 시 readable stack
- 78 absl::ComputeCrc32c — 하드웨어 가속 체크섬
- 79 absl::PeriodicSampler — 적응형 샘플링·jitter 회피
관련 글
Abseil Versioning과 ABI 호환성 정책
Part 1-05: Abseil의 versioning 정책 — inline namespace, ABI 호환 범위, prebuilt 사용 시 함정.
같은 시리즈에서 이어 읽기
absl::PeriodicSampler — 적응형 샘플링·jitter 회피
absl::profiling_internal::PeriodicSampler — sampling rate를 동적으로 조정, geometric distribution으로 jitter 회피. 메모리 할당 추적·profiling 인프라의 기반.
같은 시리즈에서 이어 읽기
absl::ComputeCrc32c — 하드웨어 가속 체크섬
absl::ComputeCrc32c — SSE4.2 CRC32, ARM CRC 명령어로 가속된 CRC32C 구현. iSCSI·Btrfs·protobuf에서 표준화된 무결성 검사.
같은 시리즈에서 이어 읽기
이 글을 참조하는 글 (6)
- Abseil Conformance·Policy 분석 — Abseil Code Review
- Abseil Versioning과 ABI 호환성 정책 — Abseil Code Review
- Abseil 빌드와 의존성 — Bazel vs CMake — Abseil Code Review
- Abseil 설계 철학 — std 호환과 추가 기능의 균형 — Abseil Code Review
- Folly production validation 문화 — peta-scale에서 단련된 코드 — Folly Code Review
- Folly API stability 정책 — 어떤 보장도 없다는 솔직함 — Folly Code Review