소프트웨어 품질의 황금률

ko생성일: 2025. 9. 22.갱신일: 2025. 9. 24.

소프트웨어 품질에 관한 ‘황금률’—문제를 다운스트림에서 우회하기보다 업스트림으로 수정을 올리기—을 제시하고, 서드파티 의존성, 타입 설계, 사회적 분열의 사례로 그 함의를 설명합니다.

Haskell for all: 소프트웨어 품질의 황금률

===============

Haskell for all

2020년 7월 27일 월요일

소프트웨어 품질의 황금률

golden-rule

===============

이 글은 내가 소프트웨어 품질을 논할 때 자주 인용하는 경험칙을 정리한 것으로, 시간을 아끼려고 내 글을 링크해 둘 수 있게 하려는 목적입니다. 규칙이 간결하고 일반화 가능하기 때문에 나는 이것을 “소프트웨어 품질의 황금률”이라고 부르기로 했습니다.

황금률은 다음과 같습니다:

문제를 다운스트림에서 우회하기보다 업스트림으로 수정을 올리는 것을 선호하라

… 그리고 이 규칙이 몇 가지 소프트웨어 공학적 트레이드오프에 어떤 함의를 가지는지(하스켈 커뮤니티와 생태계의 예시를 통해) 설명하겠습니다.

면책 고지: 소프트웨어 품질의 황금률은 타인을 자신이 대접받고 싶은 대로 대하라는 황금률과는 아무런 관련이 없습니다.

서드파티 의존성

대부분의 개발자는 프로젝트에서 서드파티 의존성이나 도구에 의존하지만, 정작 그 서드파티 코드 자체를 고치거나 개선하는 일은 거의 생각하지 않습니다. 대신 이들은 방관자 효과에 굴복하는 경향이 있는데, 즉 많이 쓰이는 프로젝트일수록 다른 누군가가 문제를 해결해 줄 것이라고 가정합니다. 그 결과, 바로 이런 개발자들이 널리 쓰이는 도구의 문제를 우회하는 데에 더 익숙해집니다.

예를 들어, 오랫동안 하스켈은 레코드 필드에 접근하는 “점(dot)” 문법을 지원하지 않았고, 커뮤니티는 언어 안에서 점 문법을 흉내 내려 다양한 패키지(예: lens)로 다운스트림에서 이를 우회해 왔습니다. 이 접근은(액세서가 일급 값이라는) 장점도 있었지만, 타입 추론이 나쁘고, 에러 메시지가 부실하며, 에디터의 필드 자동완성 지원이 부족하다는 단점이 있었습니다. 최근에서야 Neil MitchellShayne FletcherRecordDotSyntax 제안을 통해 이 기능을 언어에 직접 업스트림하여 문제의 근원을 해결했습니다.

소프트웨어 품질의 황금률은 당신이 의존하는 도구와 패키지를 직접 개선하는 것(“업스트림으로 수정 올리기”)을, 로컬에서 대충 때우는 것(“다운스트림에서 문제 우회”)보다 선호해야 한다고 시사합니다. 이러한 업스트림 개선은 다음과 같은 대상에 직접 기여하는 방식으로 이뤄질 수 있습니다:

  • 사용하는 에디터 / IDE
  • 명령행 셸
  • 사용하는 프로그래밍 언어
  • 의존하는 패키지

물론 항상 가능한 것은 아닙니다(특히 업스트림이 외부 기여에 적대적일 때). 다만 최소한 시도라도 해 보기 전에 포기하지는 마세요.

타입이 있는 API

함수의 타입도 같은 원칙을 따를 수 있습니다. 예를 들어, 리스트의 첫 번째 값을 얻는 head 함수에 “안전한”(전체 함수인) 타입을 부여하는 방법은 두 가지가 있습니다.

첫 번째 접근은 오류 처리를 다운스트림으로 미룹니다:

-- 리스트가 비어 있지 않으면 첫 값을 `Just`로 감싸서 반환하고, 비어 있으면 `Nothing`을 반환합니다
head :: [a] -> Maybe a

… 두 번째 접근은 요구 사항을 업스트림으로 끌어올립니다:

-- 리스트가 `NonEmpty`라면 실패하지 않고 첫 값을 반환합니다
head :: NonEmpty a -> a

황금률은 head의 후자 타입 시그니처(입력에 NonEmpty를 요구)를 선호하라고 말합니다. 이 타입은 애초에 빈 리스트를 전달하지 못하게 함으로써 수정을 업스트림으로 올리기 때문입니다. 더 일반적으로 이 규칙을 논리적으로 밀고 나가면 불법 상태를 표현 불가능하게 만들기에 이르게 됩니다.

이에 반해 전자의 타입 시그니처는 Maybe를 반환함으로써 리스트가 비어 있을 가능성을 우회합니다. 이 타입은 오류를 프로세스의 더 나중에 잡도록 부추기는데, 이는 우리가 마땅히 해야 할 만큼 빨리 실패하지 않게 만들어 품질을 낮춥니다. 문제의 간접적인 다운스트림 증상을 디버깅하기보다, 진짜 업스트림의 근원에서 빠르게 실패하도록 만들어 품질을 높일 수 있습니다.

사회적 분열

저는 콘웨이의 법칙을 굳게 믿습니다. 이 법칙은 이렇게 말합니다:

어떤 조직이(광의로 정의된) 시스템을 설계하면, 그 설계의 구조는 그 조직의 커뮤니케이션 구조를 복제한 모습이 된다.

— Melvin E. Conway

… 이를 저는 때때로 “사회적 분열은 기술적 분열을 낳는다”라고 바꿔 말하곤 합니다.

사회적 문제가 기술적 문제의 업스트림에 있다면, 황금률은 기술적 해법으로 사회적 갈등을 가리려 하기보다 근본 원인(사회적 마찰)을 고치는 것을 선호해야 한다고 시사합니다.

하스켈 커뮤니티의 고전적인 예로 cabalstack의 분열이 있습니다. 이는 FPComplete와 Cabal 기여자들 사이의 분열에서 비롯되었습니다(하스켈 서브레딧의 피드백을 바탕으로 정정). 유급 기여자와 오픈 소스 기여자 간 업스트림의 마찰을 해결하지 못하자, 병렬 설치 도구를 만드는 기술적 해결책으로 다운스트림에서 문제를 우회하려 했습니다. 그 결과 하스켈 커뮤니티가 분열되었고, 초보 사용자에게 나쁘고 혼란스러운 경험을 안겨 주었습니다.

이는 커뮤니티의 분열이 반드시 해결 가능했어야 한다는 뜻은 아닙니다(유급 기여자와 오픈 소스 자원봉사자 사이의 차이가 타협 불가능했을 수도 있습니다). 그럼에도 이 예시는 근원에서 문제를 고치지 못했을 때 품질에 어떤 뚜렷한 영향이 있는지를 잘 보여 줍니다.

결론

소프트웨어 품질의 황금률이 업스트림에서 문제를 반드시 고쳐야 한다고 명령하는 것은 아님을 유의하세요. 이 규칙은 다른 모든 것이 같다면 업스트림으로 수정을 올리기를 권할 뿐입니다. 때로는 시간이나 돈의 제약 같은 다른 고려 사항 때문에 그럴 수 없기도 합니다. 그러나 품질이 최우선이라면 이 규칙을 지키도록 노력해야 합니다!

작성자: Gabriella Gonzalez — 게시 시각: 오전 8:14