2.1 코딩 표준과 스타일
개요와 동기
코딩 표준은 많은 사람이 한 명의 신중한 작성자가 쓴 것처럼 코드를 쓰게 하는 공유된 관례입니다. 명명, 서식, 파일 배치, 관용구, 오류 처리, 팀이 선호하는 패러다임을 다룹니다. 작은 팀에서는 개인의 취향이 통할 수 있습니다. 큰 팀(수백, 수천 명의 엔지니어, 많은 계약자, 높은 인력 교체)에서는 비일관성이 모든 읽기, 모든 리뷰, 모든 온보딩에서 치르는 세금이 됩니다. 표준은 수많은 작은 스타일 논쟁을, 기계가 대신 시행하는 일회성 결정으로 바꿉니다.
큰 조직에서 이해관계는 구체적입니다. 코드는 쓰이는 것보다 훨씬 더 자주 읽힙니다. 기업과 정부 환경에서는 코드 한 줄이 작성자가 떠난 지 여러 해 뒤에 감사자, 보안 검토자, 유지보수자에게 읽힐 수 있습니다. 일관된 스타일은 그 읽기의 정신적 비용을 낮추고, 버그가 숨을 표면적을 줄이고, 린터(잠재적 버그와 스타일 위반을 자동으로 표시하는 도구), 보안 스캐너, 리팩터링 도구 전반에서 자동 분석을 신뢰할 수 있게 합니다. 금융 서비스, 의료, 국방, 공공 부문 시스템처럼 규제가 적용되는 곳에서는 표준이 코드베이스가 유지보수 가능하고 통제되고 있다는 증거의 일부를 이루기도 합니다.
현대적 접근은 스타일을 지속적인 인간의 판단 문제가 아니라 풀린 자동화된 관심사로 다루는 것입니다. 포매터와 린터는 편집기, 프리 커밋 훅, 그리고 모든 변경에서 실행되는 자동 빌드 및 테스트 프로세스인 지속적 통합(CI)에서 실행됩니다. 기계가 스타일을 시행하므로, 리뷰의 주의를 설계와 정확성에 쓸 수 있습니다. 목표는 획일성 그 자체가 아니라 마찰의 제거입니다. 기본을 다시 배우지 않고 서비스와 팀 사이를 오갈 수 있어야 합니다.
핵심 원칙
- 일관성이 개인 선호를 이깁니다. 어디서나 적용되는 하나의 합의된 스타일이 고르지 않게 적용되는 “최고”의 스타일보다 값집니다.
- 시행을 자동화하십시오. 간격에 대한 코드 리뷰 코멘트가 아니라 포매터와 린터가 진실의 원천입니다.
- 원 작성자가 아니라 독자와 유지보수자에게 최적화하십시오.
- 맞춤형 사내 규칙보다 더 넓은 언어 커뮤니티가 이미 쓰는 관례를 선호하십시오.
- 표준을 채택하기 쉽게 만드십시오. 아무도 읽지 않는 PDF가 아니라 공유 설정, 템플릿, 도구를 제공하십시오.
- 스타일 규칙은 적고, 방어 가능하고, 모호하지 않아야 합니다. 모든 규칙에는 시행 메커니즘이 있거나, 아니면 제안일 뿐입니다.
- 명명은 가독성에서 지렛대 효과가 가장 큰 결정이며 명시적인 안내를 받을 자격이 있습니다.
권장 사항
언어별로 표준 스타일 가이드를 채택한다
사용하는 각 언어에 대해 널리 인정받는 스타일 가이드(예컨대 그 언어의 커뮤니티 또는 벤더 가이드)를 기준선으로 채택하고, 조직에 필요한 차이점만 문서화하십시오. 사내 스타일을 처음부터 발명하지 마십시오. 선택을 중앙의 찾기 쉬운 곳에 공개하고 코드처럼 버전 관리하십시오.
포매터를 협상 불가한 기본값으로 만든다
포매터가 있는 모든 언어에 대해 의견이 분명한 자동 포매터를 쓰고, 저장소에 체크인된 단일 공유 설정을 두십시오. 서식은 저장 시 자동으로 적용되고 CI에서 검증되므로 리뷰에서 거론되어서는 안 됩니다. 언어에 강력한 포매터가 없다면 린터 설정 하나를 골라 같은 방식으로 다루십시오.
린터를 조언이 아닌 시행되는 관문으로 운영한다
합의된 규칙 집합으로 린터를 설정하고, 위반 시 빌드를 실패시키고, 변경이 리뷰를 거치도록 규칙 집합을 버전 관리에 두십시오. 자동 수정 가능한 규칙(자동으로 적용)과 사람의 판단이 필요한 규칙(표시하고 차단)을 분리하십시오. 새 규칙은 “경고” 모드로 도입하고, 쌓인 위반을 정리한 뒤, “오류”로 승격하십시오.
여러 계층에서 시행한다
즉각적인 피드백을 위한 편집기 통합, 로컬 시행을 위한 프리 커밋 훅, 권위 있는 관문으로서의 CI 검사를 제공하십시오. 위반을 일찍 잡을수록 비용이 쌉니다. 로컬 훅은 우회될 수 있으므로 CI가 최종 안전망이어야 합니다.
명명에 명시적 규칙을 준다
언어별 대소문자 관례를 표준화하고, 의도를 드러내는 이름을 요구하고, 오해를 부르는 약어를 금지하고, 불리언, 컬렉션, 단위, 비동기 작업에 대한 관례를 정의하십시오. 같은 개념이 어디서나 같은 이름을 갖도록 도메인 어휘를 공유 용어집에 적어 두십시오.
다언어 일관성을 의도적으로 관리한다
여러 언어에 걸친 코드베이스에서는 문법이 다르더라도 개념(오류 처리 패턴, 로깅 구조, 프로젝트 배치)의 일관성을 목표로 하십시오. 중앙 저장소에서 언어별 설정을 제공하여 새 서비스가 템플릿이나 스캐폴딩으로 표준을 자동으로 물려받게 하십시오.
관용구와 패러다임을 성문화한다
서식을 넘어서 가십시오. 선호하는 관용구, 즉 오류를 처리하는 방법, 모듈을 구조화하는 방법, 예외 대 결과 타입을 쓸 때, 그리고 팀이 선호하는 패러다임을 적어 두십시오. 진짜 가독성과 유지보수성은 여기에 있습니다.
장단점
| 접근 방식 | 장점 | 단점 |
|---|---|---|
| 엄격한 자동 포매터, 설정 없음 | 모든 서식 논쟁을 끝냄. 즉각적인 일관성. 사소한 온보딩 | 마음에 들지 않는 선택이 협상 불가. 처음 적용할 때 큰 차이 |
| 사내 규칙이 있는 설정 가능한 린터 | 조직의 필요에 맞춤. 실제 버그 방지 규칙을 부호화 가능 | 설정 표류. 규칙 자전거 창고 논쟁. 유지 부담 |
| 커뮤니티 표준을 통째로 채택 | 신규 입사자에게 익숙. 강력한 도구 생태계. 낮은 유지 비용 | 틈새 조직 제약에 안 맞을 수 있음. 가끔 어색한 규칙 |
| 맞춤형 사내 표준 | 조직에 정확히 맞음 | 쓰고 유지하는 비용이 큼. 채용자에게 낯섦. 약한 도구 |
| 팀별 자율 | 높은 지역 사기. 맥락에 특화 | 파편화. 고통스러운 팀 간 이동. 일관되지 않은 도구 |
시행되는 기본값은 약간의 개인 자율을 큰 집단적 이득과 맞바꿉니다. 리뷰 마찰이 줄고, 온보딩이 빨라지고, 자동화가 신뢰할 만해집니다. 주된 위험은 표준을 실제 결함은 막지 못하면서 모두를 늦추는 수백 개의 규칙으로 과설계하는 것입니다. 규칙 집합을 작고 증거에 기반하게 유지하고, 유지보수가 싸게 머물도록 기존 표준을 채택하는 쪽으로 기우십시오.
팀과 논의할 질문
어떤 린터 규칙이 빌드를 실패시켜야 하며, 모두를 멈춰 세우지 않고 규칙을 경고에서 오류로 어떻게 승격합니까? 이 장은 모든 규칙에 시행 메커니즘이 필요하고, 새 규칙은 경고 모드로 들어와 쌓인 위반을 정리한 뒤 오류로 바꿔야 한다고 주장합니다. 큰 팀에서 지저분한 코드베이스에 대해 규칙을 오류로 바꾸면 하룻밤 사이 수백 개의 무관한 변경을 막습니다. 후보 규칙마다 현재 위반 수와 자동 수정 가능한지 사람의 판단이 필요한지라는 확실한 증거를 회의에 가져오십시오. 기업과 정부 환경에서는 통과/실패의 선이 감사 관문에도 공급되므로, 모호한 규칙 집합은 컴플라이언스 이야기를 약하게 만듭니다. 단계적 롤아웃을 정하십시오. 할 수 있는 것은 자동 수정하고, 정리를 예산으로 잡은 뒤, 관문을 겁니다.
레거시 코드에 포매터를 처음 적용할 때, 그 재포맷이 git blame을 망치고 리뷰를 익사시키지 않게 하려면 어떻게 합니까? 장단점 표는 큰 초기 차이를 경고하고, 안티패턴 절은 재포맷 커밋과 로직 변경을 섞는 것을 지적합니다. 단 한 번의 전면적 재포맷은 수천 줄을 다시 쓰고 blame이 실제 작성자 대신 재포맷을 가리키게 하여, 수년 뒤 디버깅하는 모든 사람을 해칩니다. 재포맷을 하나의 분리되고 분명히 표시된 커밋으로 하고, blame 무시 파일에 등록하여 이력이 유용하게 남게 하십시오. 누가 무엇을 바꿨는지 추적하는 감사자에게 그 분리는 깨끗한 증거와 잡음의 차이입니다. 코드를 건드리기 전에 순서에 합의하십시오. 그 후가 아닙니다.
명명 용어집과 도메인 어휘는 누가 소유하며, 새 용어는 어떻게 추가됩니까? 이 장은 명명을 가독성에서 지렛대 효과가 가장 큰 결정이라 부르고 도메인 어휘를 공유 용어집에 적으라고 요구합니다. 이름 있는 소유자가 없으면 같은 개념이 팀마다 세 가지 다른 이름을 얻고, 정적 분석과 검색 도구가 신뢰성을 잃습니다. 이미 코드베이스에서 충돌하는 이름을 가진 개념의 예를 구체적 신호로 가져오십시오. 한 명의 소유자와 가벼운 제안 경로를 지정해, 용어를 추가하거나 이름을 바꾸는 일이 모든 풀 리퀘스트에서의 논쟁이 아니라 작은 검토된 변경이 되게 하십시오. 답은 온보딩을 바꿉니다. 신규 입사자는 일관되지 않은 코드에서 의도를 역공학하는 대신 하나의 용어집을 읽습니다.
각 언어에 대해 인정받는 커뮤니티 또는 벤더 스타일 가이드를 통째로 채택합니까, 그리고 사내 차이점이 실제로 정당화되는 곳은 어디입니까? 이 장은 기존 표준을 기준선으로 삼고 조직이 필요로 하는 차이점만 문서화해야 한다고 주장합니다. 맞춤형 표준은 쓰기 비싸고 채용자에게 낯설기 때문입니다. 상충하는 끌림은 실제입니다. 내부 제약(보안 규칙, 레거시 프레임워크, 접근성 의무)이 때로 커뮤니티 기본값과 정말 충돌하며, 유지하는 모든 차이점은 이제 영원히 소유하고 유지보수해야 하는 규칙입니다. 제안된 차이점 목록을 각각을 동기 부여하는 구체적 제약과 함께 회의에 가져오고, 단지 취향인 차이점은 잘라 낼 준비를 하십시오. 기업과 정부 환경에서 더 넓은 언어 커뮤니티와 맞는 기준선은 계약자와 새 벤더가 이미 익숙한 채 도착한다는 뜻이기도 하여, 온보딩을 단축하고 감사자가 찾는 유지보수성의 증거를 강화합니다.
다언어 코드베이스에서 어떤 관례가 진정 보편적이고 어떤 것이 언어 지역적으로 남으며, 저장소별 설정이 표류하는 것을 어떻게 막습니까? 이 장은 문법이 달라도 언어 전반에 일관된 개념(오류 처리, 로깅 구조, 프로젝트 배치)을, 그리고 새 서비스가 표준을 자동으로 물려받도록 중앙 저장소에서 제공되는 언어별 설정을 요구합니다. 긴장은 한 언어의 관용구를 다른 언어에 강제하면 어색하고 관용적이지 않은 코드가 나오는 반면, 모든 팀이 자기 설정을 포크하게 두면 “표준”이 아무 의미도 없게 된다는 점입니다. 구체적 신호로 현재 저장소별 린터와 포매터 설정의 목록과 그것들이 이미 얼마나 갈라졌는지 보여 주는 차이를 가져오십시오. 수십 개 서비스를 운영하는 큰 조직에서는 규칙 변경이 모든 저장소에 손으로 복사되지 않고 한 번에 전파되도록 배포 메커니즘(템플릿, 스캐폴딩, 공유 설정 패키지)을 정하십시오.
규칙을 비활성화하는 것이 정당한 때는 언제이며, 누가 억제를 검토하고, 일괄 비활성화가 표준을 속 빈 강정으로 만들지 않게 어떻게 합니까? 안티패턴 절은 널리 퍼진 인라인 억제를 규칙이 틀렸거나 팀이 포기했다는 신호로 지적하지만, 예외 없는 경직된 정책은 사람들이 린터를 만족시키려고 더 나쁜 코드를 쓰게 몰아갑니다. 가벼운 경로에 합의하십시오. 억제에는 이유가 있어야 하고, 가능한 가장 좁은 범위에 있어야 하며, 전역 무시 파일에 묻히지 않고 리뷰에서 보여야 합니다. 규칙별, 저장소별 현재 억제 수를 가져오십시오. 수백 번 억제된 규칙은 코드가 아니라 규칙에 대해 무언가를 말해 주기 때문입니다. 규제와 공공 부문 업무에서 설명 없는 일괄 억제는 감사 이야기를 직접 약하게 합니다. 병합된 코드가 합의된 관문을 진정으로 통과했음을 파이프라인이 더는 보일 수 없기 때문입니다.
분야별 관점
스타트업. 속도가 이기니, 하나의 언어에 대해 첫날 커뮤니티 포매터와 린터 기본값을 채택하고 두 번째 엔지니어가 오기 전에 프리 커밋 훅과 CI에 연결하십시오. 유지할 시간이 없는 사내 스타일을 쓰지 마십시오. 저장소에 실린 설정이 표준 전체입니다. 두 번째 언어를 추가할 때는 관례를 처음부터 발명하지 말고 그 언어의 표준 가이드에 손을 뻗으십시오.
소기업. 전담 도구 전문가도 빠듯한 예산도 있으니, 언어와 함께 오는 무료의 의견이 분명한 포매터에 전적으로 의지하고 조정하지 말고 기본값을 받아들이십시오. 이것은 만들기보다 사기가 분명한 경우입니다. 맞춤 규칙 집합을 유지하는 데는 없는 시간이 들지만, 기성 포매터는 비용이 들지 않고 스타일 논쟁을 즉시 끝냅니다. 내년에 채용할 계약자 한 명이 대화 없이 물려받도록 설정을 저장소에 두십시오.
대기업. 규모에서의 일은 많은 팀에 걸친 거버넌스입니다. 언어별 공유 포매터와 린터 설정을 담은 중앙 엔지니어링 표준 저장소, 그 설정을 끌어오는 템플릿에서 생성되는 새 서비스, 준수하지 않는 병합을 막는 CI 관문입니다. 규칙 집합을 코드처럼 버전 관리하고 변경을 정기 검토로 보내 표준이 표류하지 않고 의도적으로 진화하게 하십시오. 수익은 엔지니어가 팀 사이를 옮겨 익숙한 코드로 들어가는 것, 그리고 모든 저장소가 일관되어 자동화 도구가 신뢰할 만한 신호를 내는 것입니다.
정부. 조달과 책임성이 선택을 형성합니다. 운영 허가(ATO) 요건의 일부로 특정 스타일과 보안 규칙 집합을 의무화하고, 병합된 모든 변경이 합의된 관문을 통과했음을 보여 주는 보고서를 감사 증거로 파이프라인이 내보내게 하십시오. 포매터가 자동으로 적용되므로 여러 벤더와 계약자의 코드가 일관되어 보이며, 이는 계약이 끝난 뒤 오래도록 공공 유지보수 업무를 지킵니다. 표준이 투명하고 미래의 어느 공급자든 독점적 종속 없이 채택할 수 있도록 맞춤 규칙보다 인정받는 커뮤니티 기준선을 선호하십시오.
사례
스타트업. 네 명짜리 스타트업이 하나의 언어에 대해 첫날 커뮤니티 포매터와 린터 기본값을 채택하고 프리 커밋 훅과 CI에 연결하여 아무도 리뷰에서 간격을 두고 논쟁하지 않습니다. 설정이 저장소 안에 실려 있으므로 다섯 번째와 여섯 번째 채용자는 그것을 자동으로 물려받고 서식 코멘트를 한 번도 보지 않습니다. 팀이 나중에 두 번째 언어를 추가할 때, 유지할 시간이 없는 사내 스타일을 발명하는 대신 그 언어의 표준 가이드에 손을 뻗습니다.
대기업. 한 대형 은행은 수십 개 팀에 걸쳐 Java, Python, TypeScript로 서비스를 운영합니다. 각 언어의 공유 포매터와 린터 설정을 담은 중앙 “엔지니어링 표준” 저장소를 공개합니다. 새 서비스는 그 설정을 끌어오는 템플릿에서 생성되므로 모든 저장소가 처음부터 준수 상태로 시작합니다. CI는 모든 위반에서 병합을 막고, 분기별 검토가 규칙 변경을 다스립니다. 모든 저장소가 익숙해 보이기 때문에 팀 사이를 옮기는 엔지니어의 온보딩 시간이 눈에 띄게 줄어듭니다.
정부. 레거시 시스템을 현대화하는 공공 기관이 운영 허가(ATO), 즉 시스템을 프로덕션에서 운영하는 데 필요한 공식 승인의 요건으로 접근성과 보안 린팅 규칙 집합을 의무화합니다. 스타일 준수는 감사 증거의 일부가 됩니다. 병합된 모든 코드가 합의된 정적 분석 관문을 통과했음을 보여 주는 보고서를 파이프라인이 만듭니다. 포매터가 자동으로 적용되므로 여러 벤더의 계약자가 시각적으로 일관된 코드를 만들고, 이는 계약이 끝난 뒤 정부의 장기 유지보수 업무를 더 쉽게 합니다.
비즈니스 사례: 동기, ROI, TCO
표준을 도입하는 비용은 대부분 일회성입니다. 가이드를 고르고, 도구를 연결하고, 하나의 큰 초기 재포맷 커밋을 적용하는 것입니다. 반복 비용은 시행이 자동화되어 낮습니다. 표준을 도입하지 않는 비용은 반복적이고 누적됩니다. 모든 리뷰가 스타일에 몇 분을 쓰고, 모든 온보딩이 더 느리고, 정적 분석 도구가 잡음을 내고, 일관되지 않은 코드가 버그를 숨깁니다. 큰 조직 전반에서 그 몇 분은 상근 인력 환산 손실로 쌓입니다.
수익은 줄어든 리뷰 지연, 스타일 관련 리뷰 코멘트 감소, 더 빠른 온보딩, 자동화 도구의 더 높은 신호로 나타납니다. 규제 환경에서는 감사 준비라는 추가 수익이 있습니다. 입증 가능하게 시행되는 통제는 컴플라이언스 검토의 노력과 위험을 줄입니다. 리더십을 설득하려면 표준을 개발자 생산성과 감사 태세에 대한 저비용 고지렛대로 설명하고, 리뷰 코멘트 분석과 온보딩 설문 데이터로 비일관성의 현재 비용에 숫자를 매기십시오.
안티패턴과 함정
- 코드 리뷰에서 논쟁되는 스타일: 시행이 자동화되지 않았다는 신호. 규칙을 도구로 옮기십시오.
- 읽히지 않는 표준 문서: 시행이 없는 위키 페이지는 장식입니다. 모든 규칙에는 메커니즘이 필요합니다.
- 규칙의 난립: 결함은 막지 못하면서 일을 늦추는 수백 개의 지엽적 규칙.
- 설정 표류: 각 저장소가 자기 린터 설정을 포크하여 “표준”이 아무 의미도 없어질 때까지.
- 기능 작업 도중 전체 저장소 포맷: 재포맷 커밋과 로직 변경을 섞으면 리뷰와 blame이 파괴됩니다. 큰 재포맷은 분리되고 분명히 표시된 커밋으로 하십시오.
- 일괄 억제로 린터 무시: 널리 퍼진 인라인 비활성화는 틀린 규칙이거나 포기한 팀의 신호입니다.
- 소유자 없는 표준: 분명한 소유자가 없으면 규칙이 진화하지 않고 썩습니다.
성숙도 모델
- 1단계, 시작: 스타일이 작성자별이고 반응적입니다. 공유 설정이 없고, 서식은 리뷰에서 논쟁되며 그날 가장 신경 쓰는 사람이 정리합니다.
- 2단계, 발전: 개별 팀이 포매터와 린터를 채택하지만, 설정과 규칙 집합이 팀마다 저장소마다 달라서 일관성이 각 팀의 경계에서 멈춥니다.
- 3단계, 표준화: 언어별 중앙 공유 설정이 문서화되어 조직 전체에서 시행됩니다. CI가 준수하지 않는 병합을 막고, 새 저장소는 템플릿이나 스캐폴딩으로 표준을 자동으로 물려받습니다.
- 4단계, 관리: 표준이 데이터로 측정되고 통제됩니다. 위반율, 억제 수, 스타일 관련 리뷰 코멘트, 온보딩 시간이 기준선에 대해 추적되고, 규칙 변경은 의견이 아니라 그 증거에 따라 승격되거나 폐기됩니다.
- 5단계, 오케스트레이션: 표준이 지속적으로 개선되고 조직 전체에 통합됩니다. 다언어 관용구와 도메인 어휘가 문서화되고 시행되며, 시행은 거의 마찰이 없고, 규칙 집합은 언어, 도구, 조직의 필요가 변함에 따라 적응합니다.
논의를 위한 아이디어
- 시행되는 규칙과 엔지니어의 판단을 신뢰하는 문서화된 지침 사이의 선은 어디입니까?
- 조직은 진정한 내부 제약과 충돌하는 사랑받는 커뮤니티 규칙을 어떻게 다뤄야 합니까?
- 표준은 누가 소유하며, 규칙 변경은 혼란 없이 어떻게 제안되고, 논쟁되고, 배포됩니까?
- 다언어 코드베이스에서 어떤 관례가 진정 보편적이어야 하고 어떤 것이 언어 지역적으로 남아야 합니까?
- 혼란스러운 일괄 재포맷 없이 큰 레거시 코드베이스에 표준을 소급 적용하려면 어떻게 합니까?
- 기계적 서식을 넘어 관용구를 제안하거나 시행하는 데 AI 지원 도구는 어떤 역할을 해야 합니까?
핵심 요점
- 스타일을 자동화된 풀린 문제로 다뤄서 사람이 설계와 정확성을 리뷰하게 하십시오.
- 기존 커뮤니티 표준을 채택하고 차이점만 문서화하십시오.
- 편집기, 프리 커밋, CI 계층에서 시행하되 CI를 권위 있는 관문으로 삼으십시오.
- 규칙 집합을 작고, 방어 가능하고, 중앙에서 다스려지게 유지하십시오.
- 가독성이 진정으로 얻어지는 곳은 간격이 아니라 명명과 관용구입니다.
참고 문헌과 더 읽을거리
- Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship
- Andrew Hunt and David Thomas, The Pragmatic Programmer
- Steve McConnell, Code Complete
- Dustin Boswell and Trevor Foucher, The Art of Readable Code
- Kevlin Henney (ed.), 97 Things Every Programmer Should Know
- Google, Google Engineering Practices and language style guides (as reference exemplars)