왜 신입 개발자에게 클린코드 가이드가 필요한가?
모든 창작 활동이 그렇겠지만, 첫 시작을 어떻게 하느냐에 따라 시간이 갈수록 창작자가 그 작품을 대하는데 발휘할 수 있는 생산성이 달라집니다. 만약 작업을 시작할 때 미래의 자신을 생각하지 않고 마구잡이로 작업을 시작하다보면, 중요한 수정을 해야할 때 손 쓸 방법이 없는 상황에 직면하게 됩니다.
⇒ 시작을 할 때 미래에 어떻게 할 지 생각을 하고 진행을 해야한다. Jira를 사용하여 티켓을 통해 요구사항을 제대로 파악하고 어떻게 진행할 것인지 사고하고 진행하자. 중요한 수정 사항이 있을 경우 티켓에 있는 내용을 읽고 파악하여 동료 개발자들이 어떤 방식으로 진행했는지 알 수 있도록 도와야한다.

소프트웨어는 특히 형체를 알 수 없기 때문에 잘 와닿지 않겠지만, 후일을 생각하지 않은 상태에서 실컷 개발해놓고 나중에 코드 수정을 해야할 때가 되면 자신이 여러 코드들을 뒤져가면서 막막해하거나, 수정을 하면 다른 부분에서 버그가 발생해 스트레스 받고 있을 가능성이 높습니다. 혹은, 새로운 사람이 함께 일하고 싶어도 코드를 이해하기 어려워해 협업 일정의 발목을 잡을 수 있습니다.
⇒ 컴포넌트화 하고 문서화를 하자.Jira, Notion 활용
클린코드 가이드는 이러한 상황들을 줄이기 위해 실천할 수 있는 항목들을 나열하고, 각각에 대한 필요성을 전달하기 위해 만들어졌습니다. 평소에는 실천해볼 기회가 많이 없었겠지만, 익스턴십 프로그램에 참가하면서 가이드에 언급된 항목들을 습관화하시면 더 좋은 개발자로 거듭나실 수 있을 것입니다.
Mission 에서 적용 될 수 있는 클린코드 규칙
클린코드 규칙에는 다양한 것들이 있으며, JavaScript 코드 자체에 대한 Best practice들도 존재합니다. 후자의 것은 모든 Best practice들을 나열하기 어려워, 본 섹션에서는 전자의 것들 중 중요하다고 생각되는 것들만 골라 설명하려고 합니다.
더 자세한 Best practice들을 알고 싶으신 분들은 ESLint를 사용하면서 제안받는 규칙들(List of available rules)을 그 때 마다 확인해보시고, Vue.js에서 제안하는 Style Guide(Priority A와 B 위주로)를 읽어보시는 것을 추천드립니다.
⇒ ESLint를 사용하면서 제안받는 규칙들 확인, VSCode Extension 사용할 것
⇒ Vue.js에서 제안하는 Style Guide 정리할 것
TDD와 테스트 코드
Test-driven Development(일명 TDD) 방법론의 개념을 많이 들어보셨을 것이며 그의 중요성도 많이 들으셨을 겁니다. 하지만 TDD 방법론은 계기가 없으면 방법론을 직접 적용하여 테스트 코드를 짜며 개발하는 습관을 들이는 것이 힘듭니다.
TDD(Test-driven Development) 방법론은 자연어 상태의 요구사항을 테스트 코드를 작성하고, 그에 맞춰 애플리케이션 코드를 점진적으로 작성해나가는 것이 핵심입니다. 이러한 특징으로 인해 요구사항을 이해하고 구체화할 수 있기 때문에 불확실성을 줄여나가며 애플리케이션 코드를 작성할 수 있는 밑거름이 됩니다. 또한 코드 수정이 필요한 경우에도 기존의 테스트 케이스들의 통과 여부를 통해 기존의 요구사항들의 만족 여부를 확인할 수 있어 실제 코드를 믿고 변경할 수 있는 환경이 만들어집니다. 따라서 본 강의를 통해서 수강생 여러분들이 5주동안 TDD 방법론을 적용하고 이를 습관화하셨으면 합니다.

항상 작은 단위의 테스트 코드를 가장 먼저 작성하세요
“클린코드”로 잘 알려진 로버트 마틴(일명 Uncle Bob)은 TDD 방법론에 대해 3가지 원칙을 내세웁니다.
- 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다.
- 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다.
- 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다.
앞서 소개한 TDD의 필요성에 대입해서 정리하자면, 요구사항을 테스트 코드로 옮겨 적은 다음에 애플리케이션 코드 작성을 시작하라는 것입니다. 이 때 주의할 것은 테스트 코드로 옮길 요구사항들은 쉽게 테스트할 수 있도록 아주 작은 단위부터 차근차근 쌓아나가는 것입니다.
위의 3가지 원칙을 한 사이클(Cycle)로 잡으면서 테스트 코드와 애플리케이션 코드를 번갈아가다보면 긴장감을 유지하면서 상대적으로 더 높은 생산성을 유지할 수 있지만, 테스트 코드로 옮길 요구사항을 크게 잡으면 어느 한 쪽의 코드에 갇혀서 긴장감을 유지하지 못해 생산성을 떨어질 위험이 있습니다. 때문에, 작은 단위의 테스트부터 차근차근, 그리고 빠른 사이클로 여러 번 반복하는 것이 좋습니다.
Input과 Output으로만 테스트를 하세요
테스트할 때 구현 내부를 확인하는 것은 지양해야 하며, 입력(Input)과 출력(Output)으로만 성공 여부를 확인해야 합니다. 이는 실제 구현은 개발 상황에 따라 언제든지 바꿀 수 있기 때문에, 테스트 코드에 구현 내부를 확인하는 로직이 포함되면 애플리케이션 코드 수정이 필요할 때 테스트 케이스를 갈아엎어야 할 수도 있습니다. 때문에 Input으로 적절한 Output을 만들어주는지만 테스트하여 테스트하는 대상이 원하는 역할을 제대로 해주는지만 테스트하는 것이 이상적입니다.
비슷한 원리로 Vue.js에서 컴포넌트 단위 테스트(Unit Test) 코드를 작성할 때는 UI 상호작용와 props와 같이 외부에서 유입되는 데이터 등을 테스트의 입력으로, 그에 따른 DOM element나 event 등을 테스트의 출력으로 사용하는 것을 권장합니다. (참고: Do not test implementation details)
린터(Linter)와 포맷터(Formatter)
원활한 협업을 위해서는 일관된 모양(스타일)을 가진 코드들을 주고 받는 것이 좋습니다. 일관된 모양을 가진 코드를 작성하면 협업하는 사람끼리 서로 코드를 리뷰할 때 자잘한 특징들로 소모적인 논쟁을 하지 않고, 작성하는 애플리케이션의 핵심 로직에 대한 리뷰를 할 수 있어 더 효율적인 협업을 할 수 있기 때문입니다. 이를 위해서 린터와 포맷터라는 유틸리티들을 사용할 수 있습니다.
린터는 소스 코드를 분석하여, 프로그램의 (잠재적) 오류, 버그, 스타일 오류들을 알려주는 도구들이며, 린터와 포맷터를 함께 사용하면 이러한 오류들을 수정하고, 일관된 스타일을 유지하도록 도와줘서 안정적인 애플리케이션을 만드는데 도움을 줍니다.

각 언어들은 자신에 대한 린터와 포맷터 유틸리티들이 존재하며, 각 언어에서 권장되는 코딩 컨벤션들과 취향에 맞게 적용할 수 있는 코딩 스타일 옵션들이 내장되어 있어 협의한 코드 스타일들을 설정 파일로 만들어 Git 저장소를 통해 공유할 수 있습니다. 이렇게 하면 Pull Request를 만들어서 코드리뷰를 진행할 때 유의미한 변경사항들만 볼 수 있도록 도와줍니다.

(린터와 포맷터를 사용하지 않으면 이렇게 Pull Request의 이름과 관련이 없는 변경사항이 들어갈 수 있어 리뷰하는 사람에게 혼동을 줄 수 있습니다.)
린터와 포맷터를 처음부터 수시로 실행하세요
목표로 한 요구사항들을 모두 구현한 후에 소스 코드에 린터와 포맷터를 실행할 수도 있겠지만, 이런 방식은 린터와 포맷터에서 알려주는 수정 필요사항들을 가늠할 수 없기 때문에 엄청난 수정을 해야할 수 있으며, 이러한 수정사항을 Git과 같은 VCS에 기록을 하게 된다면 변경사항들을 확인하기 어렵습니다. (마치 빚이 쌓이는 것과 같습니다.)
따라서 린터와 포맷터를 사용할 때는 개발 초기부터 설정들을 적용하고, 구현을 하면서 수시로 린터와 포맷터를 적용하여 수정 필요사항들을 반영하는 것이 좋습니다. 그리고 커밋을 남길 때는 협업하는 사람들끼리 일관된 스타일이 적용된 소스 코드만을 볼 수 있게 린터와 포맷터를 모두 통과한 코드만을 추가하는 것이 좋습니다.
비슷한 논리로 구현할 때는 린터의 경고를 하나도 남기지 않을 정도로 유지해야 합니다. 린터가 주는 경고를 남겨두고 쌓아놓으면 경고에 무뎌지게 되어 린터를 사용하지 않는 것과 다름없게 됩니다. 그렇다고 경고를 강제로 끄지 마세요. 경고를 강제로 끄는 것은 합의된 코딩 컨벤션 약속을 어기는 것과 마찬가지이며, 만약 경고를 직접 반영하지 않고 강제로 꺼야할 이유가 있다면 협업하는 사람들과 합의하고 끄세요.
이름을 지을 때는 최대한 자세하게, 그리고 규칙을 가지고 지으세요
잘 지은 이름은 그 역할을 한 번에 알 수 있게 해줍니다. 이 팁은 변수명과 메서드 뿐만 아니라 Vue 컴포넌트의 이름에도 적용할 수 있습니다. 이를 위해서는 이름을 지어주는 대상의 의도(예. 함수/변수의 역할)가 분명하게 드러나도록 직관적인 이름을 지어줘야 합니다. (예. Tightly coupled component names) 특히 모든 이름들을 나름의 어순의 규칙을 세우고 지으신다면, 이름이 시사하는 역할을 미세하게나마 더 빠르게 이해할 수 있습니다.

만약 이름을 길게 지으면 코드 작성하는 것이 힘들지 않을까 걱정하신다면 그러실 필요가 없습니다. 우리에게는 강력한 자동완성 기능들을 가진 IDE와 에디터들이 있기 때문에 안심하고 작명하시면 됩니다.
모듈의 역할이 커지지 않도록 통제하세요
애플리케이션 개발을 하다보면 특정 모듈이 하는 역할이 커질 수 있습니다. 단순히 메서드의 기능 단위가 커지는 것 뿐만 아니라 숫자/문자열 상수를 가지고 있는 것, 혹은 특정 기술/패키지에 종속되는 현상도 포함됩니다.
이렇게 각 모듈의 역할이 커지게 되면 수정하거나 재사용하기 어려워져서 요구사항 변화에 대응하기 어려워집니다. 예를 들어, 특정 메서드들에 필요한 하나의 설정값을 메서드의 인자(Parameter)에 상수로 넘겼다면, 설정값을 바꾸기 위해 여러군데를 바꿔야하는 번거로움이 생깁니다.
따라서, 모듈의 역할이 커지면서 의존 관계가 보이기 시작하면 이를 미리 분리하려는 노력을 해보세요. 여기에는 URL과 같은 문자열 상수를 const로 선언하여 사용하거나, 특정 패키지를 직접 사용하지 않고 추상화하여 Wrapper를 만들어 사용하는 것도 포함될 수 있습니다.

