코드의 영속성에 관하여: **지속 가능한 소프트웨어 개발: 장기 유지보수와 효율적인 운영 전략**의 조건
8 views
# 코드의 영속성에 관하여: 지속 가능한 소프트웨어의 조건
## 폐허가 된 시스템 앞에서
1977년에 발사된 보이저 1호의 통신 코드 일부가 1970년대 포트란(FORTRAN)으로 작성되었다는 사실은 종종 회자된다. 반세기가 흐른 지금도 그 코드는 성간 공간에서 신호를 보낸다. 같은 시기에 작성된 수많은 엔터프라이즈 시스템이 5년을 버티지 못하고 폐기된 것과는 사뭇 대조적이다.
이 격차는 어디서 비롯되었을까. 언어의 우수성도, 하드웨어의 견고함도 아니다. 핵심은 설계 단계에서 시간을 변수로 인식했는가에 있다. 보이저의 엔지니어들은 자신의 코드가 수십 년 뒤에도 누군가에게 읽히고 수정되어야 한다는 사실을 알았고, 그래서 단순함을 택했다.
오늘날의 개발 문화는 반대 방향으로 흐른다. 분기마다 새 프레임워크가 등장하고, 의존성 트리는 수천 개의 노드로 부풀며, 어제의 베스트 프랙티스가 내일의 안티 패턴이 된다. 이 가속의 한가운데서 지속 가능성이라는 단어는 점점 이질적으로 들린다.

## 부채의 본질: 시간이라는 채권자
'기술 부채(technical debt)'라는 개념은 워드 커닝햄이 1992년 OOPSLA 컨퍼런스에서 제시했다. 그의 비유는 정교했다. 부채 자체는 악이 아니지만 이자가 붙고, 갚지 않으면 원금이 불어난다. 문제는 이 채권자가 시간이라는 점이다. 시간은 협상하지 않는다.
> "코드를 빨리 작성하는 것은 빚을 지는 것과 같다. 약간의 부채는 개발을 가속시키지만, 갚지 않은 부채는 결국 모든 변경을 마비시킨다." — Ward Cunningham, 1992
2017년 영국 항공(British Airways)의 시스템 장애가 좋은 예다. 단 한 번의 정전이 7만 5천 명의 승객을 공항에 묶었다. 원인은 수십 년간 누적된 레거시 시스템과 그 위에 덧대어진 임시 패치들이었다. 단기적으로는 합리적이었던 결정들이 모여, 장기적으로는 재난의 부품이 된 것이다.
지속 가능성을 논할 때 우리는 흔히 환경적 지표를 떠올린다. 그러나 코드의 세계에서 지속 가능성은 훨씬 구체적이다. 3년 뒤의 자신이, 혹은 얼굴도 모르는 후임자가 이 코드를 두려움 없이 수정할 수 있는가. 그것이 질문의 전부다.
## 설계의 윤리: 도시계획자의 시선
좋은 코드를 짓는 일은 건물을 세우는 일보다 도시를 계획하는 일에 가깝다. 건물은 완성되면 끝나지만, 도시는 끝나지 않는다. 도로가 확장되고, 구획이 재편되고, 낡은 구역은 재개발된다. 도시계획자는 자신이 살아 있는 동안 완성되지 않을 질서를 설계한다.

### 첫째, 명료함이 영리함을 이긴다
도널드 크누스는 일찍이 "성급한 최적화는 모든 악의 근원"이라고 적었다. 영리한 코드는 작성자의 자아를 만족시키지만, 독자의 시간을 소모한다. 5년 뒤 이 코드를 읽을 사람—자신이든 타인이든—은 우아한 트릭보다 명백한 의도를 원한다.
리눅스 커널의 코딩 스타일 문서는 이 점을 단호하게 못 박는다. "코드의 들여쓰기가 세 단계를 넘어가면, 당신은 이미 망했고 프로그램을 고쳐야 한다." 명료함은 미학이 아니라 윤리다.
### 둘째, 의존성은 부채다
현대 자바스크립트 프로젝트의 평균 의존성 수는 수백 개에 달한다. 2016년 left-pad 사태는 단 11줄짜리 npm 패키지가 삭제되자 전 세계의 빌드 시스템이 멈춘 사건이었다. 의존성은 외주받은 신뢰이고, 신뢰는 언젠가 깨진다.
지속 가능한 시스템은 의존성을 최소화한다. 표준 라이브러리로 가능한 일을 외부 패키지에 맡기지 않는다. 추가되는 모든 의존성은 미래의 어느 시점에서 보안 패치, 호환성 검토, 혹은 마이그레이션의 비용으로 청구된다.
### 셋째, 문서는 코드의 일부다
"훌륭한 코드는 자기 자신을 설명한다"는 명제는 절반만 참이다. 코드는 *무엇을* 하는지 보여주지만, *왜* 그렇게 하는지는 보여주지 못한다. 비즈니스 맥락, 거부된 대안, 알려진 한계 같은 정보는 주석이나 ADR(Architecture Decision Record, 아키텍처 결정 기록)에만 살아남는다.
아마존이 내부에서 사용하는 '여섯 페이지 메모' 문화는 시사적이다. 결정의 맥락을 글로 남기지 않은 사람은 결정에 참여하지 못한다. 코드도 마찬가지다. 맥락 없는 코드는 다음 세대 개발자에게 고고학적 유물이 된다.
## 운영의 미학: 보이지 않는 것을 보는 일
코드는 작성되는 시간보다 운영되는 시간이 훨씬 길다. 일반적인 엔터프라이즈 시스템의 개발 기간이 1년이라면, 운영 기간은 7년에서 10년에 이른다. 그럼에도 개발자의 관심은 작성 시점에 편중되어 있다.

운영의 미학은 다른 곳에 있다. 그 출발점은 관측 가능성(observability)이다. 로그, 메트릭, 트레이스라는 세 기둥은 시스템이 자신의 상태를 스스로 증언하게 만든다. 장애 발생 시 원인을 찾는 데 걸리는 시간, 즉 MTTR(Mean Time To Recovery)은 관측 가능성에 정비례한다. Google SRE 팀이 강조하는 원칙은 단순하다. **측정되지 않는 것은 관리되지 않는다.**
그다음은 자동화다. 사람이 매번 같은 절차를 반복한다면 그것은 시스템의 결함이지 운영의 일부가 아니다. 배포, 롤백, 백업, 복구—모든 절차는 코드로 표현되어야 한다. 코드로 표현된 절차만이 검증 가능하고, 재현 가능하며, 개선 가능하다.
마지막은 점진적 변경의 원칙이다. 큰 변경은 큰 위험이다. 카나리 배포, 블루-그린 전환, 피처 플래그 같은 기법은 변화를 작은 단위로 쪼개어 통제 가능한 형태로 만든다. 한 번에 한 가지만 바꾼다는 규율은 운영의 가장 오래된 지혜다.
## 인간이라는 변수
지속 가능한 소프트웨어를 논할 때 우리는 종종 가장 큰 변수를 잊는다. 코드를 작성하고 유지하는 것은 결국 사람이다.
번아웃된 개발자가 유지하는 시스템은 지속 가능하지 않다. 매일 새벽 호출에 시달리는 운영자가 관리하는 서비스도, 신입이 들어와도 6개월 안에 떠나는 팀이 만드는 코드도 마찬가지다.
지속 가능성은 기술적 명제이기 이전에 노동의 명제다. 한 줄의 코드가 십 년을 견디려면, 그것을 돌볼 사람이 십 년을 견뎌야 한다. 노자는 일찍이 적었다.
> 治大國若烹小鮮 (치대국약팽소선) — 큰 나라를 다스리는 것은 작은 생선을 굽는 것과 같다.
작은 생선은 자주 뒤집으면 부서진다. 시스템도 그러하고, 그것을 굽는 손도 그러하다.
## 영속의 조건
지속 가능한 소프트웨어란 영원히 변하지 않는 코드가 아니다. 오히려 그 반대다. 변화를 두려워하지 않아도 되는 구조, 그것이 지속 가능성의 본질이다.

보이저 1호의 코드가 반세기를 견딘 것은 완벽했기 때문이 아니라 단순하고 명료하며 변경 가능했기 때문이다. 위대한 시스템은 견고함과 유연함을 동시에 갖춘다. 오랜 도시의 골목길처럼, 시간이 지날수록 정교해지되 본래의 질서는 잃지 않는다.
장자는 「양생주」에서 포정의 칼 이야기를 남겼다. 십구 년을 쓴 칼이 방금 숫돌에서 나온 듯했다. 결을 따라 베었기 때문이다. 결을 거스르지 않은 칼은 닳지 않는다.
코드도 그러하다. 시간의 결을 거스르지 않는 코드만이 시간을 견딘다. 우리가 짓는 모든 시스템은 결국 우리가 떠난 뒤에도 누군가가 읽어야 할 편지다. 그 편지가 해독 가능한 언어로 쓰였는지, 우리는 매일 자문해야 한다.