51P by neo 15일전 | ★ favorite | 댓글 6개
  • 경력이 많은 개발자들이 신입 개발자와 소프트웨어 개발 철학을 공유한 내용
  • 전면 재작성(ground-up rewrite)을 피하고, 일정 관리와 코드 품질, 자동화, 엣지 케이스 대응 등 다양한 주제에 대한 조언을 담고 있음

어떤 대가를 치르더라도, 전면 재작성(ground-up rewrite)이 매력적으로 보이는 상황을 피할 것

  • 전면 재작성의 유혹이 생기는 시점은 이미 누적된 기술적 부채로 인해 기존 코드 유지가 어려워진 순간임
  • 코드 복잡도가 누적되는 시점에 미리 경고 신호(단순한 수정도 어려움, 주석/문서화 곤란, 핵심 코드 이해 인원 감소 등)를 포착해 적극적으로 해결책을 모색해야 함
  • 확장이 끝난 뒤에는 반드시 복잡도를 줄이고, 품질을 정비하는 통합 단계를 거쳐야 함
  • 전면 재작성이 불가피해지면 프로젝트가 이미 위험 단계에 진입했음을 의미함
  • 위험을 줄이기 위해서는 계속적으로 기술 부채를 관리하고 코드 품질을 주의 깊게 모니터링해야 함

가능한 시간의 절반으로 전체 작업의 90%를 완성할 것

  • 코드를 1차로 작성해 동작하게 만드는 것은 전체 작업의 절반 수준임
  • 그 이후의 단계(에지 케이스 처리, 테스트, 배포, 문서화, 성능, 유지보수성 등)를 제대로 마치려면 생각보다 많은 시간이 필요함
  • 충분한 버퍼를 두고 예상치 못한 문제나 마무리 작업(폴리싱)에 대응해야 함
  • 결국 ‘처음 코드를 대충 돌아가게 만들기’와 ‘완성된 기능으로 만들기’ 간 격차를 인식하고, 이를 일정에 반영해야 함

우수 사례를 자동화할 것

  • 개발자들에게 반복해서 “이렇게 해야 함”이라고 구두나 문서로 강조만 하면 실수가 발생하기 쉬움
  • 가능한 경우에는 자동화된 테스트나 스크립트로 ‘규칙 위반 시 빌드 실패’ 같은 형태로 강제하는 것이 효과적임
  • 새로 도입된 규칙(금지할 API, 반드시 달아야 하는 주석 등)에 대해서도 점진적으로 자동화해 오류나 누락을 줄일 수 있음
  • 단, 모든 사항을 자동화할 수 있는 것은 아니며, 너무 엄격한 규칙은 개발 흐름을 방해할 수 있으므로 균형이 필요함

극단적(병리적/Pathological) 데이터도 고려할 것

  • 정상 입력(골든 패스)만으로 코드를 판단하면 위험함
  • 요청이 지연되거나 중단되는 경우, 방대한 데이터(수백만~수억 행), 이상한 문자열(너무 긴 경우, 슬래시나 공백 포함) 등 문제 상황을 가정해야 함
  • 엣지 케이스를 철저히 대비하는 것이 최종적인 코드 품질을 좌우함

보통은 더 단순하게 작성 가능한 방법이 있음

  • 초기에 코드가 동작하게 만든 뒤, 시간적 여유를 두고 다시 더 단순하고 명확하게 개선하는 것이 좋음
  • “좋아 보이는 해법”을 찾았더라도, 더 나은 해법이 있는지 다시 살펴볼 여유를 가지는 태도가 중요함
  • 길고 복잡한 코드를 간결하게 리팩터링하는 과정이 최종 품질을 높여줌

테스트 가능하게 코드를 작성할 것

  • 인터페이스와 사이드 이펙트를 최소화하면 자동화 테스트 작성이 훨씬 수월해짐
  • 테스트하기 어려운 구조라면, 캡슐화가 제대로 되지 않았을 가능성이 큼
  • 구체적으로 테스트가 잘 진행될 수 있는 형태로 코드 구조를 설계하면 버그를 조기에 발견할 수 있음

코드가 ‘증명상’ 문제 없다고 끝이 아님

  • 구조적으로 안전해 보이는 코드라도, 주변 환경 변화나 일부 호출 방식이 바뀌면 문제가 생길 수 있음
  • 보안 관련 코드라면, 현재 호출부가 안전하더라도 미래에 변경될 가능성을 고려해 설계해야 함
  • 코드는 “명백히 안전하고, 바뀌어도 문제가 없도록” 작성되어야 함

댓글들

  • “이 편지를 짧게 쓰지 못한 이유는 짧게 쓸 시간이 없었기 때문이다” 라는 문장에 대한 출처는 Pascal임
  • 항상 오프바이원 에러(off-by-one error)를 주의할 것
  • 위키에 새로운 가이드라인 추가하기
    • 회사 내 문서화/지식 공유 체계가 제대로 잡혀 있지 않으면 정보가 산재되어 혼란스러운 상황이 생김
    • 공식 문서가 승인 과정을 거치며 구버전이 되거나, 여러 개의 위키가 동시에 존재해 어느 것이 정식 자료인지 모르는 문제가 발생함
    • 한 곳의 위키만 정해 모든 자료를 모으고, 부족한 부분이 있으면 개발자들이 직접 작성하거나 역공학(reverse-engineering)을 통해 채워나가는 방식이 유효함
    • 문서화가 다른 곳(소스 컨트롤, 코드 주석 등)에 잘 연동되어 있으면 최신 정보를 유지하기 쉬움
    • 자동화된 테스트와 빌드 환경이 복잡하거나 개발자에게 노출되지 않은 경우, 실제로 전체 테스트를 돌려본 경험이 없는 상황이 생길 수 있음
    • Jenkins 빌드 스크립트는 단순하게 유지하여 “cd project; ./build-it” 형태로 구성하고, 이 스크립트 자체도 소스 컨트롤에 포함하는 편이 유리함
    • 팀 전체가 동일 환경(예: 가상 머신 이미지, 빌드 설정)에서 빌드와 테스트를 수행할 수 있도록 공유하면 문제 발생을 사전에 줄일 수 있음
    • 에지 케이스를 개발 단계에서 고려해 destroy_object(foo)처럼 foo가 NULL이어도 안전하게 동작하도록 처리하거나, create_object() 실패 시 destroy_object()를 내부적으로 호출하게 하는 방식이 유익함
    • 궁극적으로 모든 개발자가 문서와 빌드/테스트 환경에 쉽게 접근하고 참여하도록 하는 것이 중요함
  • 문서화와 자동화 테스트: 지식 공유를 위한 문서나 위키의 중요성, 그리고 Jenkins 같은 CI/CD 환경의 설정이 공유 가능해야 한다는 실무적 제안이 언급됨
  • 사람들이 원하는 행동을 외울 때까지 "불편을 주는 것"보다 더 효과적인 행동 변화 도구는 없음
  • 체스의 격언 하나 “좋아 보이는 수가 보이면, 일단 실행하라”에도 반대 입장이 있듯, 프로그래밍도 마찬가지. 양면성이 있음.

어떤 대가를 치르더라도, 전면 재작성(ground-up rewrite)이 매력적으로 보이는 상황을 피할 것

많은 IT 회사들의 비즈니스가 발전하지 못하게 되는 pitfall 인 거 같고, 기술부채가 많이 쌓인 상태에서 그것을 해소하지 못하는 (또는 해소하고 싶지 않은) 엔지니어링 조직이 전면 재작성을 매력적으로 생각하는 것 같습니다.

진정으로 납득될만한 이유가 없다면 재작성은 최대한 피해야 한다는 저자들의 생각에 깊이 공감합니다.

보통은 더 단순하게 작성 가능한 방법이 있음

더 간결한 해결책을 고민하는것이 코드 및 정책의 복잡도를 낮춘다고 믿습니다.

"가능한 시간의 절반으로 전체 작업의 90%를 완성할 것"

이 내용은 정말 맞는 말인 것 같습니다. 한 번에 완벽하게 구현한다기 보다 빠르게 2 번을 보는 것이 실수도 줄이고, 시간관리도 더 잘되더라구요.

  1. 우수 사례 자동화 ( 테스트 코드 CI/CD 파이프라인 )
  2. 초기에 코드가 동작하게 만든 뒤, 시간적 여유를 두고 다시 더 단순하고 명확하게 개선하는 것이 좋음
  3. 전면 재작성(ground-up rewrite)이 매력적으로 보이는 상황은 무슨 일이 있어도 피할 것

항상 오프바이원 에러(off-by-one error)를 주의할 것

오프바이원 에러가 뭔가 했는데 for (int i = 1; i < n; ++i) { ... }, for (int i = 0; i <= n; ++i) { ... } 같은 경계 조건과 관련된 에러군요.

Hacker News 의견
  • 소프트웨어 개발은 시도와 학습의 반복적인 과정임. 경험 있는 개발자는 코드 작성과 테스트를 통해 이해를 높이고, 많은 학습을 하지만 이는 회의나 계획에서 잘 드러나지 않음. 주니어 개발자는 생산 준비된 코드를 제공하는 데 어려움을 겪으며, 버려지는 작업을 꺼려함. 관리자가 개발 경험이 부족하면 이러한 문제를 악화시킬 수 있음

  • "긴 편지를 쓴 것을 사과하지만, 짧게 쓸 시간이 없었다"라는 인용문은 프랑스 수학자이자 철학자인 Blaise Pascal의 말로, 짧게 쓰는 것이 더 어렵다는 의미를 담고 있음

  • 90/50 규칙은 코드의 품질을 높이기 위해 테스트와 예외 처리를 중요시해야 함을 강조함. 자동화된 테스트 설정은 코드베이스의 명확한 기대치를 설정하는 데 도움이 됨

  • 컴퓨터 과학 교육은 종종 복잡한 코드를 작성하도록 유도하지만, 읽기 쉬운 코드를 작성하는 것이 중요함. 변수와 함수의 명명, 일관된 포맷팅, 모듈화된 설계 등이 필요함

  • Ratchet이라는 메커니즘은 미래를 위한 완벽한 방법을 제공함

  • 경험과 도메인 인식을 일반화하려는 시도는 잘못된 일반화로 이어질 수 있음. 개발은 복잡성을 관리하는 예술이며, 실패를 통해 배우는 것이 중요함

  • "작업의 첫 90%가 90%의 시간을 차지하고, 나머지 10%가 또 다른 90%의 시간을 차지한다"는 인용문은 개발의 현실을 잘 나타냄. 예외 처리, 오류, 사용성, 보안 등을 고려할 때 많은 예상치 못한 작업이 필요함

  • Joel Spolsky의 글은 재작성의 위험성을 경고하며, DevOps의 지혜를 강조함

  • 코드의 가독성을 최적화하고, 버그가 발견되기까지의 시간이 길어질수록 비용이 증가함을 인식해야 함. 함수형 프로그래밍 원칙을 선호하고, 강한 타입 시스템을 사용하는 것이 유익함