ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Front-end Clean Code
    Note 2021. 9. 24. 14:57

    토스 개발자 컨퍼런스를 보고 실무에서 바로 쓰는 클린 코드는 어떻게 되어있는지 정리해보려고 한다.

     

     

    실무에서의 클린 코드

    실무에서 클린 코드의 의의는 유지보수 시간의 단축을 의미한다고 한다.

     

    동료 혹은 과거의 내가 스스로 짠 코드를 다시 봤을 때도 빠르게 이해할 수 있다면 유지 보수할 때 드는 개발 시간이 짧아질 것이다. 

     

    유지보수 시간의 단축

    1) 빠른 코드 파악

    2) 버그가 났을 때 디버깅 시간 단축

    3) 코드 리뷰 시간 단축

     

    코드를 처음 설계하고 새로운 파일에서 짤 때는 대부분 깨끗할 것이다. 하지만 기존 코드에 기능을 추가하는 상황이라면 조금 달라지게 된다.

     

    사실 회사에서 개발자 대부분의 일이 기존 코드에 기능을 추가하는 것인데, 남이 짠 코드, 혹은 내가 지난주에 짠 코드에 기능을 붙이다 보면 코드가 들쑥날쑥해지기 쉽다. 

     

    기능이 추가되더라도 원하는 로직을 빠르게 찾을 수 있는 코드는 어떻게 짜야할까?

     

     

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

    클린 코드는 짧은 코드가 아니고 원하는 로직을 빠르게 찾을 수 있는 코드를 말한다.

     

    하나의 목적을 가진 코드가 흩뿌려져 있을 때는 응집도를 높여서 뭉쳐두어야 하고, 함수가 여러 가지 일을 하고 있는 경우에는 단일책임 원칙에 의거하여 쪼개 줘야 한다. 그리고 함수의 세부구현 단계가 제각각일 때는 추상화 단계를 조정해서 핵심 개념을 필요한 만큼만 노출해야 한다.

     

    응집도

    같은 목적의 코드는 뭉쳐 두는 것이다.

     

    하나의 기능이지만 코드가 여러 군데로 분리되어 있는 경우에 커스텀 훅을 사용해 한 군데로 뭉칠 수가 있다. 하지만 한 군데로 뭉치고 나면 오히려 읽기 힘든 코드가 될 수가 있다. 예를 들어 어떤 내용의 팝업을 띄우는지, 팝업에서 버튼을 눌렀을 때 어떤 액션을 하는지가 커스텀 훅에 가려져서 알 수 없게 될 수 있다.

     

    그럼 무엇을 뭉쳐야 할까?

     

    당장 몰라도 되는 디테일을 커스텀 훅을 사용해 숨긴다면 짧은 코드만 보고도 빠르게 코드의 목적을 파악하는 게 쉬워질 것이다.

     

    반대로 코드 파악에 필수적인 핵심 정보를 뭉쳐버린다면 여러 모듈을 넘나들며 코드 흐름을 따라가야 하는 문제가 발생할 것이므로 뭉치는 것을 지양해야 할 것이다.

     

    코드 응집 Tip

    - 핵심 데이터와 세부 구현을 나누고 핵심 데이터는 남기고 세부 구현을 숨긴다.

    - 핵심 데이터는 밖에서 전달, 나머지는 뭉친다.

     

     

    단일책임

    하나의 일을 하는 뚜렷한 이름의 함수를 만드는 것이다.

     

    예를 들어 약관 동의 여부를 체크하고 질문을 제출하는 함수가 있다면

    async function 함수 이름() {
      // 약관 체크 및 팝업
      const 약관동의 = await 약관동의_받아오기();
      if(!약관동의) {
        await 약관동의_팝업얻기();
      }
      
      // 질문 제출
      await 질문전송(questionValue);
      alert("질문이 등록되었습니다.");
    }

    함수 이름을 handle질문제출 정도로 한다면 좋지 않을 것이다. 함수 이름은 질문제출인데 기능은 약관 체크와 질문 제출이 섞여 있기 때문이다. 

     

    이렇게 중요 포인트가 모두 담겨 있지 않은 함수명은 읽는 이가 예상한 대로 코드가 동작하지 않으며 이는 코드에 대한 신뢰 하락으로 이어진다.

     

    여기서 함수에 기능 추가(전문가 연결)가 더 들어간다면 handle질문제출 이라는 함수가 질문 제출을 제외한 2가지 일을 더 하게 된다. 이러한 기능 추가가 반복되는 경우 이 함수는 더욱 잡탕이 되게 되는 것이다.

     

    그러므로 한 가지 일만 하는 명확한 이름의 함수로 잘 쪼개는 것이 중요하다.

    async function handle약관체크팝업() {
      const 약관동의 = await 약관동의_받아오기();
      if(!약관동의) {
        await 약관동의_팝업얻기();
      }
    }
    
    async function handle질문제출() {
      await 질문전송(questionValue);
      alert("질문이 등록되었습니다.");
    }
    
    async function handle전문가연결() {
      await 연결(questionValue);
      alert("연결이 되었습니다.");
    }

    이렇게 나누고 필요한 상황에서 따로따로 부르면 되는 것이다.

     

     

    추상화

    로직에서 핵심 개념을 뽑아내는 것을 말한다.

     

    먼저 팝업 컴포넌트 코드를 처음부터 디테일하게 구현한 것이다.

    <div style={팝업스타일}>
      <button onClick={async () => {
        const res = awiat 회원가입();
        if (res.success) {
          프로필로이동();
        }
      }}>전송</button>
    </div>

     

    아래는 팝업 코드를 제출 액션과 성공 액션이라는 중요 개념만 남기고 추상화한 것이다.

    <Popup
      onSubmit={회원가입}
      onSuccess={프로필로이동}
    />

    이렇게 기능을 Popup이라는 이름 아래에 추상화하여 읽기 쉽게 만들 수 있는 것이다.

     

     

     

     

     

     

    참고 자료

    'Note' 카테고리의 다른 글

    E2E Test  (0) 2021.09.28
    webpack  (0) 2021.09.09
    Context API  (0) 2021.09.03
    Portals  (0) 2021.08.30
    옵셔널 체이닝  (0) 2021.08.24

    댓글