본문 바로가기

Book

실용주의 프로그래머(7장 ~마지막)

코딩하는 동안

7장에서는 제목처럼 코딩하는 동안 우리가 신경 써야 하는 부분들을 말해준다.

Topic 37 파중류의 뇌에 귀 기울이기

여기서는 변연계에서 수행되는 감정에 관한 이야기를 한다. 일반적으로 본능적인 부분에 대해서 무시하라고 많이들 얘기한다. 하지만 본능은 우리가 경험하면서 학습한 패턴에 대한 반응으로도 만들어진다. 따라서 단순히 무시할 수 없다고 한다. 감정이 왜 들었는지 우리가 흔히 하는 메타인지처럼 메타감정도 중요하다고 하는 거 같다. 나도 이 부분을 요즘에서야 중요하게 생각하는데, 내가 하는 습관이나 여러 생각들이 생각보다 감정에서 유발된다고 생각한다. 나심 탈렙이 쓴 ‘Fooled by randomness’에서도 비슷한 얘길 하는데, 아무리 잘 학습된 사람도 극한의 상황에선 결국 감정에 의해서 충동적인 행동을 한다고 한다. 그리고 기본적으로 이성적이라고 생각하는 판단들도 감정으로부터 시작된다고 생각한다. 따라서 나도 일상 속에서 메타감정을 실천하려고 한다. 감정을 건강하게 관리하는 게 중요하다고 생각한다.

책에서 코딩 할때 생기는 두려움과 막막함을 다루는 구체적인 전략을 소개하는데, 상당히 재밌어 보인다. 이런 느낌을 받았을 때 프로젝트에서 시도해보고 싶은 특정한 측면을 찾아서 프로토타이핑 하는 것이다. 결국 지우게 될 코드지만 그렇게 하면서 여유를 가지고 다시 코딩을 할 수 있는 상태로 끌어올리는 것이다. 그래도 막막하다면 다시 시도하는 것이다. 산책과 수다, 휴식이 첫 단계라고 한다.

Topic 38 우연에 맡기는 프로그래밍

이 장을 읽고 보면 예전 나는 우연에 맡기는 프로그래밍이 전부 였던거 같기도 하다.

세상의 많은 패턴들이 우연으로 만들어지는 경우가 많다. 현실이 그렇다면 프로그래밍도 그러지 말라는 법은 없다. 우연에 의해 버그가 생겨서 그게 정확히 무슨 문제인지 모르고 코드를 고치는 경우도 있고, 우연하게 특정한 가정에 맞는 코드를 작성해서 현재는 괜찮게 작동하지만 그게 나중에 어떻게 될지 모르는 경우도 있다. 사실 현재 상황에만 맞게 작성한 것도 어떻게 보면 우연히 정해진 요구사항일 뿐이다. 마지막 문장은 당연한 얘기 같은데, 결론적으로 여기서 하고 싶은 얘기는 의도적인 프로그래밍을 하라는 것이다. 그니까 현재 정한 가정부터 해결 방안, 목적, 계획 모든 걸 다 명시하고 기록해야 한다고 한다. 그래야 미래에서 봤을 때 우연이 아니라 의도가 있는 행위가 되는 거 같다.

Topic 39 알고리즘의 속도

여기서는 기본적으로 알고리즘 성능을 추정해야 하는데, 이 역시도 상황에 따라 달라 질 수도 있다고 한다. 단순히 표면적으로 성능이 좋은 알고리즘도 입력값과 상황에 따라 충분히 달라질 수도 있으니까 고민이 필요하다. 또한 성급한 최적화는 오히려 독이 될 수도 있다.

Topic 40 리팩터링

리팩터링에 대한 구체적인 기법은 다른 책들에 있고 여기서는 기본적인 원칙들에 대해 나와있다.

리팩터링은 언제하는가

  • 중복
    • DRY 원칙 위반을 발견했다
  • 직교적이지 않은 설계
  • 더 이상 유효하지 않은 지식
    • 현실에서 사물은 변하고 요구사항은 변경되며, 우리의 지식은 늘어난다. 코드는 지금 상황에 뒤떨어지지 않아야 함
  • 사용 사례
    • 기능이라는 게 실제로 사용하다 보면 우선순위가 다시 작성되기도 한다.
  • 성능
    • 성능 개선하려면 시스템의 한 영역에서 다른 영역으로 기능을 옮겨야 한다.
  • 테스트 통과
    • 당연히 리그레션 테스트는 통과해야 함.

Topic 41 테스트로 코딩하기

여기서 테스트의 중요한 가치는 다음과 같다

테스트는 버그를 찾기 위한 것이 아니다

테스트에 대해 생각하면서 코드의 작성자가 아니라 사용자인 것처럼 메서드를 외부의 시선으로 보게 된다. 다른 코드와 긴밀하게 결합된 함수나 메서드는 테스트하기 힘들다. 즉 테스트 하기 쉽게 만들면 결합도도 낮아진다.

코드를 시작하기 전에 경계 조건의 테스트와 경계 조건에서 어떻게 동작해야 하는지를 먼저 생각해 본다면, 함수를 단순하게 만드는 코드 패턴을 찾을 수 있다. 테스트해야 하는 오류 조건에 대해 생각해 보면 그에 맞게 함수 구조를 잡을 수 있다.

다만 여기서는 너무 TDD에 빠지게 되는 경우에 대해 주의를 줬는데 과도하게 되면 역시 문제가 조금 있다. 문제는 다음과 같다.

  • 테스트 커버리지 100%를 위해 너무 많은 시간을 투자함
  • 많은 수의 중복 테스트가 생김. 불필요한 테스트들이 생김
  • 밑에서부터 시작하여 위로 올라가는 방식으로 설계

여기서 상향식 하향식 만을 지원하는 코드의 문제를 얘기한다. 근데 직관적으로 봐도 현실 문제를 저렇게 이분법 적으로 적용해서 푸는 게 좋을 거 같진 않다. 그리고 저자가 추천하는 end-to-end도 솔직히 뭐 정해진 개념이라기보다는 실용주의 프로그래머가 해야 하는 방식을 그냥 정리한 거 같다.

그래도 테스트는 해야 한다. 필수는 맞다. 여기서도 단위 테스트에 대한 이야기를 더 하는데, 앞에서 소개했던 개념인 계약을 테스트에 포함시켜서 프로젝트에서 이후에 벌어질 수 있는 문제들을 회피할 수 있다. 나도 테스트할 때 계약에 대한 생각은 안 하고 단순히 기능 테스트만 했는데 고민해 봐야겠다.

Topic 42 속성 기반 테스트

앞서 소개했던 계약과 불변식을 테스트에 포함시켜 테스트 자동화에 사용하는 속성 기반 테스트에 대해서 소개한다. 여기서 속성은 코드에 존재하는 계약과 불변식을 뭉뚱그려서 속성이라고 한다.

여기서는 속성 기반 테스트를 통해 우리는 코드를 구현할 때 세우는 잘못된 가정을 찾는데 도움을 받을 수 있다.

속성 기반 테스트를 통해 임의의 매개변수에서 실패했다면 그 값을 기반으로 단위 테스트를 정식 추가하는 게 좋다. 이렇게 생성된 단위테스트는 2가지 역할을 한다.

  • 속성 기반 테스트의 여러 가지 다른 수행 결과와 상관없이 문제가 발생하는 상황에 집중할 수 있게 해 준다.
  • 회귀 테스트 역할을 해 준다.

또한 속성기반 테스트는 코드를 불변식과 계약이라는 관점으로 보게 해준다. 이런 관점으로 보게 되면 경계조건은 줄어들고, 데이터의 일관성을 해치는 함수는 더 도드라진다.

Topic 43 바깥에는 안전에 주의하라

사실 보안에 관련해서는 깊게 고민을 안 해봤다. 그래서 기본적으로 여기서 제안하는 원칙들은 지키려고 노력해야겠다.

  • 공격 표면을 최소화하라
    • 코드의 복잡성은 공격 매개체를 유발함
      • 코드가 단순할수록 버그도 적고 심각한 보안 구멍을 만들 확률을 줄여줌
    • 입력 데이터는 공격 매개체이다.
      • 외부 데이터를 절대 신뢰하지 마라
    • 인증이 없는 서비스는 공격 매개체다
    • 인증을 요구하는 서비스도 공격 매개체다.
      • 인증받은 사용자의 수를 언제나 최소로 유지하라
    • 출력 데이터는 공격 매개체다.
    • 디버깅 정보는 공격 매개체다.
  • 최소 권한 원칙
    • 최소한의 권한만을 꼭 필요한 시간만큼만 제일 짧게 부여하라
    • 애플리케이션 개발할 때도 항상 여러 단계의 접근 권한에 대해 고민해라.
  • 안전한 기본값
  • 민감 정보를 암호화하라
  • 보안 업데이트를 적용하라
    • 보안 패치는 항상 신속하게

Topic 44 이름 짓기

이름 짓기 참 어렵다. 초반에 프로그래밍할 때 함수명이나 클래스 이름 지을 때 생각보다 작업에 부담을 많이 줬다. 이것도 계속 노력하다 보면 전보다는 잘 할거 같은데 이름 짓는 게 생각보다 고민이 많이 되서 작업에 영향을 주더라.

여기서는 이름 짓는게 문제풀이 사고방식에서 벗어나 큰 그림을 보도록 도와준다고 한다. 사람의 뇌는 단어를 꼭 지켜야 하는 것으로 인식한다고 한다. 단어로 이해하는 게 우선순위가 높다고 한다.

또한 이름 지을 때 팀 내에서 약속도 중요하고 문화적으로 통용되는 단어도 고려해야 한다.

이름 바꾸기는 훨씬 어렵다. 만약 이름 바꾸기가 너무 어려운 상황이라면 더 큰 문제일 수도 있다고 한다.

프로젝트 전에

Topic 45 요구 사항의 구렁텅이

초반에 굉장히 멋진 말이 나온다.

프로그래머는 사람들이 자신이 원하는 바를 깨닫도록 돕는다.

요구사항이란 애초에 정해져 있을 수 없다. 그니까 우리에게 무언가를 원하는 의뢰인은 자신의 머릿속에 존재하는 추상적인 기능을 우리에게 의뢰한다. 따라서 책에서는 의뢰인에게 질문을 통해서 구체적인 요구사항을 끌어내야 한다.

요구 사항은 과정이다.

위의 질문과 피드백 과정이 반복되면서 요구사항이 점점 구체화가 된다. 그래서 실용주의 프로그래머는 프로젝트 전체를 요구 사항 수집 과정으로 보아야 한다. 책에서는 짧은 주기로 반복하는 것을 추천한다. 그래야 잘못된 방향으로 가더라도 다시 돌아오는데 시간이 적게 걸린다.

요구 사항 대 정책

여기서 권한에 대한 예시를 드는데, 이것이 사업 정책인지 요구 사항인지 구분하기는 힘들다. 하지만 요구사항이 ‘인사팀에게만 직원 기록을 열람할 수 있다’라는 식이면 개발자는 코드 작성할 때 인사팀인지 확인하는 코드를 작성할 것이다. 하지만 요구 사항이 ‘권한이 있는 사용자만이 직원 기록에 접근할 수 있다’ 라면 일종의 접근 관리 시스템을 설계하고 구현해야 한다. 그리고 정책이 바뀔 때마다 시스템의 메타데이터만 업데이트하면 된다.

시스템은 다양한 정책을 처리할 수 있도록 일반적으로 구현해야 한다.

앞의 다른 장에서도 계속 언급되었지만, 요구사항이 충족되려면 의뢰인(고객, 사용자 등)에게 지속적으로 피드백을 받아야 한다.

요구사항 문서화

요구사항 문서화는 애초에 의뢰인을 위한 게 아니라 구현과정에서 이정표 같은 것이고 개발자들을 위해 쓰는 것이다. 애초에 두껍게 프로그래머의 관점으로 써봤자. 의뢰인은 애초에 요구사항이 추상적이기 때문에 본인도 잘 모르고, 잘 모르기 때문에 잘 읽지 않는다.

따라서 개발자를 위한 문서화이고 이런 문서는 구체적으로 길게 작성하는 게 아니라 명료하게 표현하고, 의미론적 불변식을 요구 사항으로 잘 갈무리하면 된다.

딱 하나만 더..

요구사항은 계속 변하기 때문에 당연히 작업하면서 의뢰인이 계속 추가하는 상황이 자주 생긴다. 이럴 때도 자주 대화를 통해서 그게 얼마나 걸리는지를 의뢰인도 명확하게 알게 하는 게 좋다.

Topic 46 불가능한 퍼즐 풀기

퍼즐을 푸는 비법은 실제 제약 조건을 알아내고, 그 속에서 해답을 찾는 것이다. 절대적 제약조건은 꼭 따라야 한다.

자유도

기본적으로 제약과 조건들의 경계선을 파악하는 게 우선이다. 그 이유는 문제를 해결하는데 주어진 자유도를 파악하기 위해서다.

모든 선입견을 의심하고 바꿀 수 없는 제약인지 가늠해 봐야 함. 틀을 벗어나고 벗어나지 않고 문제가 아니라 틀을 찾는 거임. 진짜 제약을 찾아야 함.

제약을 범주별로 나누고 우선순위를 매겨야 함. 제일 구속이 심한 제약부터 파악해 내고 나머지 제약을 그 안에서 맞춰야 함.

자신만의 방법에서 빠져나와라

어떤 문제는 생각보다 훨씬 어려워 보이기도 함. 이 문제 때문에 일정이 늦어지고 있거나, 시스템 작동하게 만드는 일 자체를 포기하고 있을 수도 있다.

이럴 때는 이 책 초반에 말했던 거처럼 잠시 딴짓을 해라. 산책을 하거나. 의식 밑에 있는 무의식의 뇌에게 할 일을 던져주는 것이다. 실제로 도움이 된다고 한다.

간단히 표현하자면 딴짓을 한 사람이 의식적으로 노력한 사람보다 복잡한 문제 해결 과제를 더 잘 해냈다.

만약 아예 문제에 대해서 놓기 힘들다면, 문제에 대해 다른 사람과 얘기해 보는 거다. 그리고 다음과 같은 질문을 던져 달라고 해라

  • 왜 이 문제를 풀고 있는가?
  • 문제를 풀어서 얻는 것이 무엇인가?
  • 풀려고 하는 문제가 특수한 경우에 해당하는가? 특수한 경우를 없앨 수는 없나?
  • 관련된 문제 중에 여러분이 풀 수 있는 더 간단한 문제는 없나?

행운은 준비된 사람에게 찾아온다.

위에서 말한 유레카를 경험하려면 뇌의 무의식에 연료를 많이 주입해야 한다. 가장 좋은 방법은 일상적인 작업을 할 때 무엇은 잘되고 무엇은 안되는지 피드백을 주는 것이다. 전에 이야기한 엔지니어링 일지 쓰는 게 도움이 된다.

그리고 언제나 Don’t Panic

Topic 45 함께 일하기

여기서는 짝 프로그래밍, 몹 프로그래밍에 대해서 이야기한다. 같이 프로그래밍하면서 훨씬 생산적으로 할 수 있다.

짝 프로그래밍에서는 코드를 입력하는 사람과 옆에서 얘기해 주는 사람의 일을 나누는 게 좋다고 하는데, 생각보다 코드 자체를 입력하는 거 자체가 뇌의 용량을 꽤 많이 소모한다고 한다. 따라서 옆에서 이야기하는 사람은 좀 더 높은 수준으로 문제를 고민할 수 있다.

Topic 45 애자일의 핵심

애자일이 탄생한 지 시간이 좀 지나서 형태만 애자일인 사례들이 많다고 한다. 다음과 같은 가치를 기억해야 한다.

  • 공정과 도구보다 개인과 상호작용
  • 포괄적인 문서보다 작동하는 소프트웨어
  • 계약 협상보다 고객과의 협력
  • 계획을 따르기보다 변화에 대응하기

애자일은 딱 정해진 게 아니라 지속적인 피드백 수집과 대응이다.

밑에서도 나오기는 하는데 이 토픽을 읽으면서 내가 추구해야 될 삶과 닮아 있다고 생각했다. 애초에 현실을 살아가는 형태는 과거로부터 오는 정보에서 피드백을 통한 현실에서의 대응이라고 생각한다.

저자는 진정한 애자일은 다음과 같다고 한다.

  • 여러분이 어디에 있는지 알아내라
  • 도달하고 싶은 곳을 향하여 의미 있는 발걸음을 가능한 한 적게 옮겨라
  • 어디에 도착했는지 평가하고, 망가트린 것이 있으면 고쳐라

이러한 피드백고리는 프로젝트의 높은 층위에서도 적용될 수 있다고 한다. 또한 소프트웨어뿐만 아니라 수많은 결정들에 대해서도 적용할 수 있다.

실용주의 프로젝트

마지막 장이다. 앞에서 조언해 준 내용을 바탕으로 프로젝트를 진행할 때 팀이 어떤 식으로 작업하면 좋을지를 말해준다.

Topic 45 실용주의 팀

여기선 앞에서 이야기했던 개인 단위에서 의식해야 하는 부분을 팀단위로 옮겨가도 이뤄질 수 있도록 더욱 노력해야 한다고 말한다. 깨진 창문을 없애라, 삶은 개구리 문제, 지식 포트폴리오, DIY, 예광탄 코드 작성과 방안들을 팀 단위에서 더 신경 써야 한다고 한다.

Topic 45 코코넛만으로는 부족하다

흔히 유행하거나 유명한 방식이나 접근법을 단순히 형태만 따라 한다면 아무 의미가 없다. 진짜 목표는 작동하는 소프트웨어를 제공함으로써 사용자가 즉각적으로 새로운 일을 할 수 있게 되는 것이다.

Topic 45 실용주의 시작 도구

프로젝트를 지탱하는 3가지 기둥에 대해서 이야기한다.

  • 버전관리
    • 버전 관리 시스템으로 빌드, 테스트, 릴리스를 운용하라
  • 회귀 테스트
    • 자동 빌드로 모든 가용한 테스트를 수행한다.
      • 단위 테스트
      • 통합테스트
      • 유효성 평가 및 검증
        • 버그가 없어도 잘못된 문제를 푼다면 쓸모가 없다.
      • 성능 테스트
        • 소프트웨어가 실세계 조건에서 성능 요구 사항들을 준수하는가
      • 테스트를 테스트하기
        • 고의로 버그를 심어 놓고 테스트가 잘 도는지 테스트하라
      • 철저한 테스트
        • 코드 커버리지만 올리지 말고 상태 조합을 테스트하라
  • 전체 자동화
    • 수작업 절차를 사용하지 마라

Topic 45 사용자를 기쁘게 하라

사용자들이 기대하는 것을 밝혀내려면 다음과 같은 단순한 질문을 던져라

이 프로젝트가 끝나고 한 달 후에 우리가 성공했는지 어떻게 알 수 있을까요?

프로젝트 배후의 가치에 대해 사용자가 기대하는 바의 일부가 수면 위로 올라왔다면, 다음과 같은 고민을 시작할 수 있다.

  • 모든 팀 구성원이 사용자가 기대하는 바를 완전히 이해해야 함
  • 결정을 내릴 때면 어떤 선택이 사용자의 기대에 더 가깝게 가는 길인지 생각하라
  • 이런 기대를 염두에 두고 사용자 요구 사항을 비판적으로 분석하라. 우리가 겪은 많은 프로젝트에서 명시된 ‘요구 사항’은 사실 기술로 무엇을 할지에 대한 추측일 뿐이었다. 요구 사항을 바꾸면 프로젝트가 목표에 가까워지는가? 그럼 바꾸어라
  • 프로젝트를 진행하면서 지속적으로 사용자에 대해 고민하라

도메인에 대한 우리의 지식이 늘어남에 따라 근본적인 사업 문제를 해결하기 위해 우리가 맡지 않은 부분에 대해서도 더 좋은 제안이 가능하다고 한다. 그리고 이런 부분이 조직의 여러 측면을 경험한 개발자가 방법을 잘 찾아낼 거라고 한다.

저자는 우리의 진짜 직함은 ‘문제 해결사’라고 한다. 이게 우리가 하는 일이고 실용주의 프로그래머의 본질이라고 한다.

이 마지막 문장이 너무 멋있는 거 같다. 사실 이런 생각을 갖고 시작했지만 정말 어려운 거 같다.

Topic 45 오만과 편견

책임을 회피하지 말고 내가 보기에 자랑스러운 작품을 만들자.

참고 및 출처: <실용주의 프로그래머(20주년 기념판)> (데이비드 토머스, 앤드류 헌트 지음, 정지용 옮김, 김창준 감수 인사이트 , 2022)

'Book' 카테고리의 다른 글

작업 단위 패턴  (0) 2023.10.05
MySQL 퍼포먼스 최적화 (1~3장)  (0) 2023.08.17
실용주의 프로그래머(5~6장)  (0) 2023.07.29
실용주의 프로그래머(3~4장)  (0) 2023.07.28
실용주의 프로그래머(1~2장)  (0) 2023.07.25