💻 Frontend

실무에서 바로 쓰는 Frontend Clean Code

category
💻 Frontend

Frontend Clean Code

프론트엔드에서 읽기 좋은 코드를 작성하려면 어떻게 해야할까?

실무에서 Clean Code란?

그 코드는 안 건드리시는게 좋을거에요.
아 그건 내가 맡을게.
이건 실제로 내가 학교 후배들이랑 프로젝트 하면서 한 후배에게 했던 말이다.

해당 코드들의 특징은 다음과 같다.
  • 흐름 파악이 어렵다.
  • 도메인 맥락 표현이 안되어있다.
  • 동료에게 물어봐야 알 수 있는 코드이다.
우리는 이러한 코드를 지뢰코드라고 한다. 이런 지뢰코드는 유지보수 하기 어렵고 심하면 기능 추가가 어려울 수 있다.
 
실무에서의 클린 코드란 유지보수 시간을 단축하는 의미이다. 동료가 작성한 코드나 혹은 과거의 내가 짠 코드를 빠르게 이해할 수 있다면 유지보수할 때 드는 개발 시간이 짧아진다.
출처 - toss
출처 - toss
시간은 자원이며, 자원은 곧 돈이다. 시간 = 자원 = 돈

사실 처음 코드를 설계하고, 새로운 파일에서 코드를 작성할 댄 참 깨끗하다. 하지만 코드를 추가할 때 긴장의 끈을 놓치면 코드가 들쑥날쑥 해진다. 사실상 회사에서 우리가 일하는 90% 정도는 기존 코드에 기능을 추가하는 일, 즉 유지보수하는 일이다.
 

안일한 코드 추가의 함정

코드를 안일하게 짠다면 어떠한 함정에 빠질까?
  1. 하나의 목적인 코드가 흩어져 있기.
notion image
기존 코드에서 안일하게 기능을 계속 추가하다보면 나쁜 코드가 될 수도 있다. 위의 코드는 하나의 목적인 코드가 흩뿌려져 있다. 이런식으로 코드를 작성한다면, 추후에 해당 코드를 읽을 때 스크롤을 위아래로 이동하며 미로찾기를 해야한다.
실제 토스 면접에서 받았던 질문이 생각난다. 버튼 클릭 시 다이얼로그를 띄우는 로직을 작성했었는데, 버튼은 코드 맨 아래있었고, 클릭 시 state를 변경하여 state가 true일 때 다이얼로그를 보여지게 하였다. 하지만 다이얼로그 로직은 윗부분에 있어서 면접관분이 코드가 흩어져 있어 이것을 어떻게 개선할거냐고 질문을 하셨다.

  1. 하나의 함수가 여러 가지 일을 하고 있다.
notion image
기존에 있던 함수가 이제 총 3가지 일을 하고 있다. 이렇게 된다면 세부 구현을 모두 읽어야 함수의 역할을 알 수 있게된다.

  1. 함수의 세부구현 단계가 제각각이다.
notion image
두 함수 다 이벤트 관련 코드이지만 handleQuestionSubmit코드에서는 여러 가지 일을 하고 있다.

여기서의 함정은 PR에서 file changes만 확인한다면 이 코드가 틀린 것인지 확인을 못한다는 것이다. 왜냐면 변경점 자체에서는 틀린 점이 없기 때문이다. 하지만 전체 코드로 읽는다면 엉망이다.
 

리팩토링

  1. 함수 세부 구현 단계를 통일
notion image
여러 가지 일을 하던 함수를 세부 구현 단계가 같은 여러개의 함수로 분리할 수 있다.

  1. 하나의 목적인 코드는 뭉쳐두기
notion image
팝업 관련된 코드를 PopupTriggerButton이라는 컴포넌트를 생성하여 여러 코드를 하나의 목적인 코드로 뭉쳐둘 수 있다.

  1. 함수 하나에서 하나의 일만 하도록 한다.

클린코드란 짧은 코드가 아니다. 클린코드란 원하는 로직을 빠르게 찾을 수 있는 코드이다.
notion image
 

로직을 빠르게 찾을 수 있는 코드

1. 응집도

같은 코드는 뭉쳐두자.
커스텀 훅을 생성한다면 코드를 한군데로 뭉칠 수 있다. 하지만, 커스텀 훅을 사용했을 때 오히려 코드 파악이 어려워질 수도 있다. 훅의 세부 내용을 보지 않는다면 해당 코드가 어떠한 역할을 하는지 알 수 없기 때문이다.
notion image
커스텀 훅을 작성할 때에는 어떠한 코드를 숨기고, 어떠한 코드를 필수적으로 보여줘야 하는지 잘 판단해야한다.
notion image
 
선언적 프로그래밍
“무엇을 해야할지만 알려줘, 세부 구현은 미리 해놨거든”
notion image
명령형 프로그래밍
“어떻게 해야할 지 하나하나 명령해줘.”
notion image
명령형 프로그래밍 코드는 읽는데 오래걸리고, 재사용하기 어렵다는 단점이 있다.
반면 선언적 프로그래밍 코드는 세부 구현은 안쪽에 뭉쳐두어서 신경 쓸 필요가 없고, ‘무엇’만 바꿔서 쉽게 재사용할 수 있다는 장점이 있다.

그렇다면 무조건 선언적인 코드가 좋은 걸까?
그건 아니다! 두 방법 모두 유동적으로 사용하면 된다.
 

2. 단일책임

하나의 일을 하는 뚜렷한 이름의 함수를 만들자.
폼에서 질문 제출 버튼을 클릭했을 때 실행되는 함수 이름을 어떻게 지을 것인가? 해당 함수의 기능은 약관동의여부를 체크하고 질문을 제출한다. 나라면 handleFormQuestion? 이런식으로 작성했을 것 같다.
예를들어 handle질문제출 이런 식으로 했다면 해당 이름은 위험하다.
notion image
함수 기능에는 약관을 체크하고, 팝업을 보여주고, 질문을 제출하는 총 3가지 기능이 있지만 함수 이름에 질문키워드만 넣으면 이는 읽는이가 예상한대로 코드가 동작하지 않을 것이다.
만약 저 함수에 또 기능이 추가가 된다면 어떻게 될까? 코드가 더 뚱뚱해지고, handle질문제출이란 함수 이름에 맞지 않은 기능을 하게 된다.
이때는 한가지 일만 하는 명확한 이름의 함수가 되도록 리팩토링해야 한다. 이를 필요한 상황에서 따로따로 부르기만 하면 된다.
notion image

한 가지 일만 하는 기능성 컴포넌트를 제작할 수도 있다.
notion image

코드를 작성하면서 가장 어려운 일중 하나는 바로 변수명을 짓는 것이다. 만약 복잡한 이름이라면 한글 변수명을 써보는 것도 유용하다.
notion image
 

3. 추상화

핵심 개념을 뽑아내자.
notion image
추상화에 답은 없다. 상황에 따라 필요한 만큼 추상화하면 된다.
하지만, 추상화 수준이 섞여 있으면 코드파악이 어렵다.
notion image
중간으로 추상화된 코드를 보고 높은 추상화인 코드도 구체적으로 작성되어있다고 짐작하게 될 것이다. 하지만 해당 컴포넌트 내부에서 복잡한 코드가 숨겨져 있을 수도 있다.
notion image
추상화 수준을 통일하면 코드를 물 흐르듯이 파악할 수 있다.
 

액션 아이템

1. 담대하게 기존 코드 수정하기

두려워하지 말고, 기존 코드를 씹고 뜯고 맛보고 즐기자.
구조 뜯기를 두려워 하면, 클린한 실무 코드를 유지할 수 없다.
 

2. 큰 그림 보는 연습하기

그 때는 맞고 지금은 틀리다. 기능 추가 자체는 클린해도, 전체적으로 어지러울 수 있다.
그 때는 맞고 지금은 틀리다. 내 기능 추가 자체는 클린 해도 큰 그림으로는 어지러운 코드일 수도 있음을 유념하자.
 

3. 팀과 함께 공감대 형성하기

코드에 정답은 없습니다. 명시적으로 이야기를 하는 시간이 필요합니다.
우리는 코드리뷰를 할 때 이러한 고민을 하게 된다. “이건 너무 사소한데 리뷰 해도 되는걸까?” 내적에서 해당 부분을 지적할 지 말지 고민해봤을 것이다. 사소하지만 일관성을 깨는 코드가 쌓이면 유지보수 하기 힘든 코드가 된다.
그러니 팀과 함께 코드에 대해 이야기 하는 시간을 가지고 사소한 것도 이야기를 하며 공감대를 형성해보자!
 

4. 문서로 적어보기

글로 적어야 명확해집니다.
  1. 향후 어떤 점에서 위험할 수 있는지
  1. 어떻게 개선할 수 있는지
 

마무리

느낀점

클린코드는 짧은 코드가 아닌, 쉽게 이해하고 원하는 로직을 빨리 찾을 수 있는 코드라는 걸 알게되었다.
가장 기억에 남는 내용은 추상화이다. 우리가 컴포넌트나 커스텀 훅을 제작하는 것이 다 추상화 수준을 조절하는 일이었다는 것을 알게되었다. 그리고 내 코드가 제일 어지러워지는 부분도 추상화 때문이었던 것 같다.
내 코드의 문제점과 어떻게 개선해야하는지 이번 기회를 통해 알게 되었으니 똑같은 실수를 반복하지 않도록 지속적으로 코드의 품질에 대해 생각하는 습관을 가져야겠다!

References

Video preview