Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
172 changes: 172 additions & 0 deletions 2025/Becoming a Better Programmer/ymkim97/chapter14~23.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# 더 나은 프로그래머 되는 법

## 14장 ~ 23장

---

## 14장 - 소프트웨어 개발이란

우리는 적절한 방식으로 적절한 제품을 작성하길 갈망해야 한다.
훌륭한 프로그래머의 주요 특징 중 하나는 작성한 소프트웨어와 그 작성법에 대해 진심으로 주의를 기울이는 것이다.
즉, 더 애정 어린 장인 정신을 바탕으로 코드를 작성해야 한다.

> _좋은 소프트웨어 개발은 머릿속에 떠오른 첫 번째 코드를 뱉어내는 카우보이식 코딩(cowboy coding)이 아니다. 신중하고, 심사숙고하며, 정확한 노력의 산물이다._
>
> _좋은 프로그래머는 겸손한 자세로 일한다. 그들은 자신이 모든 것을 알지는 못한다는 점을 인정한다._

저자는 이번 장에서 소프트웨어의 개발을 다양한 은유를 통해 정의한다.
당연히 완벽한 은유나, 단 하나의 은유만으로 정의하는 것은 불가능하다고 생각한다.

책에서는 성분(음식), 예술, 과학, 스포츠, 아이들 놀이, 집안일로 비유하고 있다.
모두 동의하고 좋은 은유지만, 현재로서는 스포츠라는 은유가 나와 가장 잘 맞는다고 생각한다.
결국 소프트웨어라는 것을 개발할 때는 대부분 팀이라는 공동체에서 발생하는 것이기 때문이다.
같은 목표를 향해 서비스에 대한 애정과 진심을 담아 전문성을 통해 천천히 완성해 나아가는 것을 크게 느꼈기 때문이다.

## 15장 - 규칙 가지고 놀기

> _우리는 프로젝트에 참여할 때는 다양한 규칙을 지켜야 한다._ > _높은 품질의 코드 작성에 대한 규칙, 작업 절차와 관례에 대한 규칙, 그리고 프로젝트와 업무 영역에 관한 특정 규칙 등이다. 이러한 규칙은 함께 일하는 데 유용하다. 규칙은 우리의 수고를 조화롭게 하고 통제한다._

책에서는 규칙에 대해 강조하고 있으며, 저자의 팀은 개발 규칙을 세 개의 짧은 상호 보완적인 선언문으로 요약하였다.

- 간결하게 하라.
- 머리를 쓰라.
- 변하지 않는 것은 없다.

이러한 규칙들만으로도 팀이 잘 협업되었던 것은 결국 서로간의 신뢰와 책임감에서 나왔다고 생각한다.

> _모호하게 구두로 전해지는 팀의 규칙에 의존하지 말라. 무언의 규칙을 명백하게 만들고 코딩 문화를 다스려라._

마지막 세 번째 규칙은 규칙 자체에도 적용된다.
결국 규칙은 깨지거나 다시 만들어지라고 있어 상황에 따라 미래에는 규칙도 변할 수 있다는 것을 인지해야 한다.

## 16장 - 간결하게 하기

> _개발자 세상에는 잘못된 방향과 좋은 방향의 간결함이 존재한다. 다만 우리가 간절히 찾는 ‘간결함’은 다음 행위와 반드시 같지는 않다. 즉, 작성할 수 있는 제일 쉬운 방법으로 작성하고, 복잡한 부분은 생략하고, 다루기 힘든 복잡한 것들은 무시하는 (카페 아래로 더러운 것들을 집어넣고 알아서 없어지길 바라는) 일반적인 프로그래밍 바보가 되자는 의미가 아니다._

생각 없이 접근하다가 간결한 코드를 넘어 과도하게 단순한 코드를 만들지 말자.
또한 일관성은 명확성으로 이어지고 이러한 일관성은 간결한 코드로 이끄는 주역이다.

간결함과 단순함의 차이를 명확히 인지하고 주의를 기울여서 코드를 작성해야겠다.
그렇다고 모든 코드가 간결할 수는 없다. 우선적으로 명확한 코드를 작성한 후에 복잡한 것은 필요할 때 만들면 된다.

간결함은 충분함과 연관이 있다. 이러한 충분함을 잘 지킬 수 있어야 간결한 코드를 작성할 수 있다.

## 17장 - 머리 쓰기

> 일을 멈추고 생각하라. 바보 같은 코드를 작성하지 말라.

모든 사람은 실수한다는 것을 인지하고, 내가 실수하게 된다면 일단 실수했음을 인지하고 코드로 되돌아가 더 나은 방향을 찾아보자.
실수를 인정하고 실수를 바로잡는 용기를 가지자.

해당 장에서는 그저 손이 따라가는대로 코드를 작성하는 것이 아닌, 먼저 충분히 생각과 검토, 페어 프로그래밍, 코드 리뷰 등을 하라고 조언해주고 있다.

## 18장 - 변하지 않는 것은 없다

프로그래머들은 두려움으로 인해 코드의 수정에 대해 부정적으로 보게 된다.
잘못될지도 모른다는 두려움과 어떤 것을 깨뜨려야 한다는 두려움, 추가 업무, 수정 비용에 대한 두려움 등이다.

> _코드는 변해야 한다. 제품 중에 ‘불변’의 코드가 있다면 그 제품은 썩어버릴 것이다._

코드란 절대로 불변이어서는 안되며, 그 어떤 코드도 신성시되어서는 안 된다.
어떠한 코드도 완벽할 수 없고, 코드 주변의 세상은 끊임없이 변화한다.

그냥 용감하고 대담하게 코드를 수정하자.
언제든지 코드를 정상적인 상태로 되돌릴 수 있으므로 다시 시도하면 된다.
시도하는 것은 부끄러운 일이 아니며 실수로부터 항상 배울 수 있다. 다만 그 어떠한 수정에 대해서도 출시 이전에 충분한 테스트와 검증을 거쳤음을 보장하라.

수정할 때는 수정을 위한 설계, 도구(CI) 등을 사용할 수 있다.

## 19장 - 코드 재사용 사례

복사/붙여넣기는 코드 재사용이 아닌 중복에 가깝다.
이러한 코딩은 자제해야 하며 복제된 코드(and 버그)로부터 고통받지 말고, 로직을 공통 함수와 공통 라이브러리에 넣자.

> _주의 깊게 조사하지 않은 채 웹에서 찾은 코드를 프로젝트에 복사하는 일이 없도록 하라._

> _다른 사람의 코드를 무시하지 말라. 자신만의 버전을 작성하는 것보다 이미 존재하는 라이브러리를 사용하는 편이 나을 수도 있다._

## 20장 - 효과적인 버전 관리

개발자에게 버전 관리란, 하루하루의 개발에서 핵심적인 부분을 차지한다.
버전 관리는 단순한 도구지만 이를 잘 사용하면 다양한 이점을 누릴 수 있다.

- 협업의 중심으로써 개발자들 간의 협력을 조율한다.
- 최신의 상태를 정의하고 게재한다.
- 프로젝트 내에서 이루어진 작업들의 기록을 유지하고, 각 출시 버전에 포함되어야 하는 정확한 콘텐츠를 모아둔다.
- 이를 통해 소프트웨어 고고학을 수행할 수 있다.
- 작업에 대한 중추적 백업 도구로써의 역할을 한다.
- 개발자에게 안정망을 제공한다.
- 작업에 운율과 박자를 부여한다.
- 하나의 코드베이스에서 동시에 여러 방향으로 개발을 수행하는 동안 서로의 작업이 꼬이지 않도록 한다.
- 작업을 되돌릴 수 있다.

나는 버전 관리(git)을 아주 당연히 여기지만, 저자의 과거 협업 경험에서 이런 것을 아예 적용하지 않았던 팀이 있었다는 것이 정말 신기했다.

> _버전 관리 도구에 소프트웨어 프로젝트를 구성하는 모든 파일을 저장하라. 다만 가능한 한 최소한으로 유지하라. 불필요한 파일을 포함하지 말라._

버전 관리를 잘 활용하기 위해서는 원자적 커밋, 적절한 체크인 메시지, 좋은 커밋을 고안하는 방법이 있다.

## 21장 - 골키퍼 있다고 골 안 들어가랴

개발자 과정에서 가장 스트레스를 많이 받는 시점에 QA팀과 매우 긴밀한 관계를 유지하며 협업하게 된다.
이때 개발자는 테스트를 담당하는 골키퍼를 제치고 소프트웨어라는 축구공을 골인시키고자 한다.

> _개발 막바지라고 해서 소프트웨어를 QA팀에게 던져버려서는 안 되며 지속적인 의사소통을 추구해야 한다._

QA 담당자들을 개발자와는 구분되는 별도의 부류로 취급하는 것은 개발 조직에 대한 잘못되고 편파적인 시각으로 문제를 불러일으킨다.

> _개발과 테스트 사이에 인위적인 단절을 만들어내지 않도록 주의하라._

> _팀 간의 의사소통이 건전하지 않으면 코드도 건전해지지 않는다._

모든 각자 다른 팀들도 포함되지만, 개발자와 QA는 서로 협업하는 동료로서 받아들이고 좋은 관계를 유지해야 한다.

개발자에게는 (단위)테스트가 있어 개발자가 의도한대로 작동할 것이고, 모든 테스트를 통과하겠지만, 이것이 소프트웨어의 상태를 완전히 반영할 수는 없다.
즉 사용자가 실제로 수행할 모든 경우의 수와 일치하지는 않는다.
이 단계에서는 아직 소프트웨어에 대한 모든 use case를 다루지 않는다.
소프트웨어는 엄청나게 복잡한 만큼, 모든 경우의 수를 고려하기 어렵고 이러한 부분에 대한 고민을 해결해주는 팀이 QA다.

> _효율적인 업무 관계는 개발자의 태도에서 시작된다. QA 엔지니어와 일할 때 서로의 차이를 이해해야 하고 그것을 장점으로 삼아야 한다._

## 22장 - 프리징된 코드의 신기한 사례

> _“코드 프리징”은 더 이상의 변경이 이루어지지 않을 것으로 예상되는 출시 직전까지의 기간이다._

> “코드 프리징”은 애매한 용어다. 아무리 코드가 변하지 않길 바라지만 코드는 반드시 변경되기 마련이다.

책을 읽으면서 코드 프리징이라는 용어를 새롭게 알게 되었다.
이는 특히 GM 버전, 즉 출시 버전의 설치 디스크를 만들고 복제하는 때에서부터 만들어진 용어다.

지금은 코드 프리징을 선언할 때는 보통 버전 관리 시스템에서 코드를 브랜치한다.
브랜치는 코드 프리징 관리의 핵심 요소다.

그러나 “프리징”이라는 단어에 현혹되어 업무를 유연하게 처리해야 할 때 융통성을 잃는 일이 없도록 유의해야 한다. 변경이 필요한 경우에는 변경해야 한다.

> _유일하고 참된 “코드 프리징”은 납득할 만한 출시가 이루어진 시점을 가리킨다. 이는 곧 코드에 더 이상의 변경이 가해지지 않게 된 시점이다._

그렇다고 프리징이 필수는 아니다. 프리징하지 않아도 CD, 테스트 등을 통해 출시 준비가 완변히 되어 있는 코드를 만들어 나갈 수 있다.

## 23장 - 제발 저를 출시해주세요

> 소프트웨어 출시 버전을 만드는 과정에는 규율과 계획이 필요하다. 개발자의 IDE에서 ‘빌드’ 버튼을 누르는 것만으로는 충분하지 않다.

출시 준비가 끝나면, 버전 관리 시스템 상의 주 개발 브랜치나 프리징된 브랜치를 백업해두고, 그로부터 건전한 출시 버전을 만들게 하는 엄격함과 원칙이 필요하다.

소프트웨어 출시 과정은 소프트웨어 개발 절차 중에서도 매우 중대한 단계로, 설계나 코딩 혹은 디버깅이나 테스트 등에 뒤지지 않을 만큼 중요하다. 더 효율적인 출시를 위한 요소는 다음과 같다.

- 단순함
- 반복 가능함
- 신뢰할 수 있음

1. 정식 출시 버전은 개발자의 개발/테스트 빌드와는 다르게 다뤄야 하는 것으로, 기존의 작업 디렉토리에서 만들어서는 안 된다. 출시 버전의 이름과 유형에 대해서도 협의하라.
2. 어떤 코드를 이번 출시 버전에 포함시킬 것인지 명확히 하라.
3. 출시할 것이라고 표시된 태그로 전체 코드베이스의 새로운 사본을 체크아웃하라.
4. 출시 버전을 패키징하라.
5. 출시 버전을 배포하라.

> 최종 결과물을 테스트하지 않았다면 출시해서는 안 된다.

## [논의 내용]

- 14장에서 소프트웨어 개발이란 무엇인지 여러 은유를 통해 저자의 생각을 드러냈고, 생각해보기에서 어떤 은유가 가장 자신과 맞아떨어지는지가 있었습니다. 저는 스포츠라고 생각하고 위에 생각을 적어보았는데, 이에 대해서 다른 분들은 어떤 것이 가장 본인과 잘 맞는다고 생각하시는지 이야기를 나누면 좋을 것 같습니다!
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 과학 > 스포츠 > 집안일 >>>>> 예술 > 놀이 순으로 순위를 매길 수 있다고 생각 했고, 그 이유는 기본적으로 개발자들의 대부분이 회사에서 고용되어서, 비즈니스 가치를 창출하는 제품을 만드는 일을 하고 있기 때문이고, 대부분 혼자가 아닌 여러 팀원들과 함께 일하기 때문 입니다

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 연구성으로 한다면 과학쪽에 무게를 주면 좋을 것 같고
팀으로 성과를 내서 사용자를 기쁘게 하는 소프트웨어라면 스포츠에 가깝다고 볼 수 있을 것 같습니다.

그리고 둘 다 잠깐 하고 버리는게 아니라 계속 동작하게 만들 생각이면 집안일을 겸하면 좋지 않을까 정도로 얘기해 볼 수 있을 것 같네요.

- 20장에서는 버전 관리에 대한 이야기가 나오는데, 개발하시면서 add, commit, push, pull을 제외한 어떤 명령어를 유용하게 사용하시는지 궁금합니다. 저는 stash로 작업했던 것들을 임시적으로 보관하는 것을 많이 사용하는 것 같습니다.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

유용성의 측면에서 보자면, rebase -i 만큼 유용한 건 없지 않을까 생각되고요

저는 cherry-pick 도 많이 사용 합니다

아마도 이건 잘 모르실 텐데, rerere 라는 기능이 있습니다 설명은 아래와 같습니다

rerere 기능은 이전 충돌 해결 작업들을 기억하고 있다가 유사한 문제가 발생하면 이를 다시 적용 합니다.

반복적인 merge conflict resolve 작업을 해야하는 상황일 때, 위 옵션 설정해두고 사용하면, 이전에 conflict resolve 한 기록을 가지고 있다가 동일한 상황에선 자동으로 resolve 해줍니다

다만, 이전에 conflict resolve 를 할 때, 잘못 resolve 한 경우라면, 잘못 resolve 한것 그대로 적용하니 이부분은 주의해서 써야합니다

링크도 참고 하면 좋겠네요

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

깃을 잘 다루는 것은 아니지만 rebase를 가장 유용하게 사용하고 있습니다.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

git 명령어라면

  • git log
  • git status
  • git diff
  • git switch
  • git reset
  • git merge
  • git branch
  • git restore

등을 더 사용하고 있습니다.
언젠가 git cheat sheet라는 걸 봤을 때 명령어 한 두개 빼고 모두 사용하고 있는 걸로 확인한 적도 있네요.
그런데 태형님이나 영명님이 얘기하는 rebase와 stash는 자주 사용하는 것 같지는 않습니다.

rebase는 commit 순서 정렬 목적에는 좋지만
나중에 시간 순서나 작은 단위 커밋이 중요한 때 파악이 어렵다는 점 때문에 (조작이 가능하므로) 저는 추천하지는 않고
대안으로는 작은 단위의 pull request 생성과 자주 git merge를 수행하자 쪽으로 가이드를 주고 있습니다.
rebase 금지는 아니지만 히스토리 조작은 하지 말자 쪽에 가깝습니다.

git statsh 역시 충돌 없이 사용하면 로컬에서 파일 관리하기에는 좋긴 한데
명시적으로 git checkout을 통해 여러개의 작은 branch로 관리하고 git merge하는 과정에서 commit 로그를 남기는 쪽이
제가 가이드하는 작은 단위의 pull request에 부합하므로 그렇게 자주 쓰지는 않습니다.
전 일단 작업하던 것 때문에 git pull 명령이 충돌날 때만 git stash를 쓰는 것 같네요.