2.0 2부 소개: 소프트웨어 프로그래밍
2부는 많은 사람이 오랜 수명에 걸쳐 읽고, 바꾸고, 신뢰할 수 있는 소프트웨어를 쓰는 일상의 기술을 다룹니다. 1부는 팀이 어떻게 조직하고 결정하는지의 토대를 놓았습니다. 이 부는 코드 자체로 눈을 돌립니다. 따르는 관례, 설계와 인터페이스를 빚는 방식, 작업을 테스트하고 리뷰하는 방법, 소스 이력을 관리하는 방법, 기록으로 남기는 방법입니다. 이런 관행이 전달 속도를 높이는 코드베이스와 모든 변경에 저항하는 코드베이스를 가릅니다.
큰 팀에서 기예는 개인 취향의 문제가 아닙니다. 조율하는 방법입니다. 수백, 수천 명의 엔지니어, 계약자, 후임자가 같은 시스템을 만질 때, 공유된 관례와 분명한 계약이 모두가 끊임없는 충돌 없이 병렬로 일할 수 있게 합니다. 코드는 쓰이는 것보다 훨씬 더 자주 읽히고, 그 읽기의 상당 부분이 여러 해 뒤에 만난 적 없는 사람들에 의해 이루어진다는 것을 기억하십시오.
기업과 정부 환경에서는 이해관계가 더 오릅니다. 시스템은 흔히 작성자보다 10년 이상 오래 삽니다. 규제와 감사는 통제의 문서화된 증거를 요구합니다. 지식은 인력 교체와 계약 경계를 넘어 전달되어야 합니다. 그래서 이 부의 장들은 품질을 영웅적 행동이 아니라 팀 전체가 일하는 방식의 엔지니어링된, 대체로 자동화된 속성으로 다룹니다.
이 부의 장
2.1 코딩 표준과 스타일: 많은 작성자가 한 명의 신중한 작성자가 쓴 것처럼 쓰게 하는, 명명, 서식, 관용구에 대한 공유되고 자동으로 시행되는 관례. 그래서 리뷰어는 주의를 스타일이 아니라 설계에 씁니다.
2.2 소프트웨어 설계 원칙: SOLID(다섯 가지 객체 지향 설계 원칙), DRY(반복하지 마라), 결합도와 응집도, 도메인 주도 설계(비즈니스 도메인의 언어로 소프트웨어를 모델링)와 같은 휴리스틱을, 따라야 할 법칙이 아니라 적용 영역과 알려진 실패 양상이 있는 도구로 다룹니다.
2.3 API와 인터페이스 설계: 시스템과 팀이 만나는 계약을 설계하여, 독립적인 팀이 소비자를 깨뜨리거나 보조를 맞춘 배포를 강제하지 않고 내부를 바꿀 수 있게 합니다.
2.4 테스트 전략: 무엇을, 어느 수준에서, 어느 정도 확신으로 테스트할지에 대한 의도적 선택으로, 큰 조직이 자주 안전하게 배포할 수 있게 하는 빠르고 신뢰할 수 있는 안전망을 만듭니다.
2.5 코드 리뷰와 협업: 병합되기 전에 변경을 검토하여 결함을 잡고, 지식을 퍼뜨리고, 표준을 시행하고, 컴플라이언스 통제를 충족하면서, 리뷰를 의례적이 아니라 빠르고 건설적으로 유지합니다.
2.6 버전 관리와 소스 관리: 모든 변경의 기록 시스템이며, 메인라인을 릴리스 가능하게, 이력을 읽을 수 있게, 감사 추적을 온전하게 유지하는 브랜칭, 저장소, 커밋의 규율.
2.7 문서화: 시작 안내서부터 런북(단계별 운영 절차)과 결정 로그까지, 핵심 인력 위험에 대비하고, 온보딩을 가속하고, 이해를 수년과 계약 경계를 넘어 전달하는 서면 지식.
2.8 소프트웨어 요구사항: 소프트웨어가 무엇을 어느 정도 잘해야 하는지를 도출하고, 명세하고, 검증하고, 관리하며, 규제와 정부 업무가 요구하는 추적성을 갖춥니다.
2.9 소프트웨어 구축: 동작하는 소프트웨어를 만드는 기술. 복잡성 최소화, 검증과 변경을 위한 구축, 방어적 프로그래밍, 규율 있는 재사용.
2.10 소프트웨어 형상 관리: 모든 형상 항목(버전을 추적하고 통제해야 하는 모든 산출물)과 변경을 식별하고, 통제하고, 감사하여, 릴리스를 재현 가능하게 하고 감사 추적을 온전하게 합니다.
2.11 소프트웨어 품질: 테스트보다 넓은 관리되는 속성으로서의 품질. 품질 모델, 보증 대 통제, 측정, 결함 관리, 품질 비용.
2.12 소프트웨어 모델과 방법: 언제 어떻게 모델링할지. 구조 및 행위 모델, 형식 기법(수학에 기반한 명세와 검증), 프로토타이핑, 애자일 방법, 그리고 모델링이 낭비인 때를 다룹니다.
2.13 컴퓨팅, 수학, 엔지니어링의 기초: 실천 아래의 변치 않는 기본. 알고리즘과 자료 구조, 논리와 확률, 경험적 엔지니어링 방법.
2.14 프로젝트와 저장소 구조: 표준 폴더, README 진입점, 공유 설정을 포함해 솔루션과 저장소를 조직하는 일관된 관례로, 어떤 엔지니어든 어떤 코드베이스든 탐색할 수 있게 합니다.
2.15 디버깅과 문제 해결: 결함을 찾아 고치는 일을 추측과 산탄총식 변경이 아니라, 재현하고, 이진 탐색으로 격리하고, 가설을 세워 시험하고, 각 수정을 회귀 테스트로 남기는 규율 있고 가르칠 수 있는 실천으로 다룹니다.
2.16 성능 엔지니어링: 성능 예산을 정하고, 최적화 전에 측정하고 프로파일링하고, 알고리즘 비용과 꼬리 지연을 이해하고, 회귀를 막아서, 소프트웨어를 의도적으로 충분히 빠르게 만듭니다. 모두 코드와 구성 요소 수준에서 이루어집니다.
2.17 동시성과 병렬성: 불변성과 메시지 전달을 기본으로 삼고, 경쟁 상태, 교착 상태, 메모리 가시성을 이해하고, 적절한 동기화와 더 높은 수준의 모델을 선택하고, 비결정적 동작을 의도적으로 테스트하여 올바른 동시성 코드를 씁니다.
2.18 의존성과 공급망 관리: 버전 규율과 락 파일, 꾸준한 갱신 주기, 최소한이고 검증된 의존성 발자국, 신뢰할 수 있는 공급망을 위한 출처와 소프트웨어 자재 명세서를 통해, 현대 시스템의 대부분을 이루는 서드파티 코드를 관리합니다.
2.19 리팩터링과 기술 부채: 신뢰할 수 있는 테스트 스위트 뒤에서 동작하는 코드의 내부 설계를 개선하고, 코드 스멜을 알아보고 작고 이름 붙은 리팩터링을 적용하고, 더 큰 변경에는 교살자 무화과를 쓰고, 기술 부채를 도덕적 결함이 아니라 눈에 보이고 재원이 마련된 포트폴리오로 관리합니다.
2.20 오류 처리와 복원력 패턴: 분명한 오류 계약, 빠르게 실패 대 안전하게 실패의 선택, 백오프와 멱등성을 갖춘 재시도, 서킷 브레이커와 우아한 성능 저하를 통해 코드가 어떻게 실패하고 복구하는지를 의도적으로 정하고, 오류를 절대 조용히 삼키지 않습니다.
2.21 타입 시스템과 정적 분석: 불법적인 상태를 표현할 수 없게 하는 정적 및 점진적 타이핑, 그리고 편집기와 파이프라인에 연결된 린터, 타입 검사기, 분석기를 통해 코드가 실행되기 전에 결함의 부류 전체를 잡아냅니다.
이 장들은 어떻게 서로 연결되는가
2부를 관통하는 줄기는 규모에서의 변경 가능성입니다. 여기의 모든 관행은 많은 사람이 공유되고 오래 사는 시스템을 확신을 가지고 바꿀 수 있게 하려고 존재합니다. 코딩 표준(2.1)과 설계 원칙(2.2)은 코드를 이해하고 수정할 수 있도록 빚습니다. 인터페이스 설계(2.3)는 팀이 독립적으로 내부를 바꿀 수 있게 하는 경계를 긋습니다. 테스트(2.4)는 변경을 안전하게 하는 안전망을 제공합니다. 코드 리뷰(2.5)는 개인의 작업이 집단적 소유권을 만나는 곳이자 표준이 실제로 시행되는 곳입니다. 버전 관리(2.6)는 리뷰, 통합, 감사가 모두 의존하는 토대입니다. 그리고 문서화(2.7)는 이 모든 것 뒤의 의도를 나중에 오는 사람들을 위해 보존합니다.
이 장들은 가이드북의 나머지에도 공급됩니다. 여기의 인터페이스와 설계 원칙은 3부 시스템의 구성 요소, 특히 아키텍처의 기본(3.1장)이 됩니다. 테스트 전략(2.4)과 버전 관리(2.6)는 8.1장의 자동화된 전달 파이프라인의 원료입니다. 문서화 관행(2.7)은 9.2장 같은 운영의 런북 및 관측 가능성과 직접 연결됩니다. 그리고 이 부 전체는 1부에서 놓은 가치와 의사결정의 토대 위에 서서, 공유된 원칙을 구체적인 일상의 기술로 바꿉니다.