트러블 슈팅: 코드 가독성 개선 - minumsa/carver-music GitHub Wiki

문제 상황

프로젝트를 진행하다 보니 어느 순간 코드가 지저분하다는 생각이 들었고, 하드코딩 된 부분이나 용도를 한눈에 파악하기 어려운 변수명이 눈에 띄었습니다.

해결 과정

상수 선언

공통으로 사용되는 숫자, 문자열 변수를 대문자로 이루어진 상수로 선언했습니다. 그리고 이러한 상수를 별도의 파일에 모아 재사용 가능한 모듈로 만들었습니다.

// constants.ts

export const FIRST_PAGE = 1;
export const FIRST_SCROLL = 1;
export const PER_PAGE_COUNT = 50;
export const SUB_PER_PAGE_COUNT = 5;

긴 조건식 변수화

if문의 긴 조건식을 모두 변수로 선언했습니다. 복잡한 조건식은 코드의 가독성을 해치는 요인 중 하나였습니다. 동일한 조건식을 변수화했을 뿐인데 코드가 이전보다 깔끔하게 느껴졌고, 해당 조건식이 어떤 동작을 수행하는지 파악하기가 훨씬 수월했습니다.

// 변경 전

if (scrollCount <= activeScrollCount) {
  ...
}
// 변경 후

const isBelowScrollLimit = scrollCount <= activeScrollCount;
if (isBelowScrollLimit) {
  ...
}

함수는 한 가지 동작씩만

복잡한 함수는 코드의 가독성을 저하시킵니다. 로버트 C. 마틴의 [클린 코드]에 따르면, 함수는 하나의 역할만 수행해야 합니다. 하나의 함수가 여러 동작을 수행하면, 테스트나 결과 추론이 어려워지기 때문입니다. 반면, 함수가 하나의 행동만 수행하도록 정의하면 코드를 쉽게 리팩토링하고 명확하게 읽을 수 있습니다.

제 코드에서는 특히 REST API의 가독성 문제가 있었습니다. 이 함수는 여러 페이지에서 공통으로 사용되던 HTTP GET 요청을 처리하는데, 현재 pathName에 따라 서로 다른 데이터를 가져오기 위해 if 문을 과도하게 사용했습니다. 결과적으로 하나의 함수가 메인 페이지, 장르 페이지, 검색 페이지를 위한 데이터 조회 작업을 동시에 처리하고 있었던 셈입니다.

// 변경 전

export async function GET(request: Request) {
  try {
    // ...

    if (pathName === "") {
      perPageCount = PER_PAGE_COUNT;
    } else {
      perPageCount = SUB_PER_PAGE_COUNT;
    }

    // ...

    if (isMainPage(pathName) || isSearchPage(pathName)) {
      if (currentTagKey) {
        query.tagKeys = currentTagKey;
      }
    } else {
      query.genre = pathName;
    }

    // ...

    return NextResponse.json({ albumData, albumDataCount });
}

위 코드를 용도별로 나누어 메인 페이지, 장르 페이지, 태그 페이지에 해당하는 데이터 조회 API를 세분화하여 따로따로 생성했습니다. 이로 인해 pathName에 따라 조건문을 사용하는 복잡한 과정이 더 이상 필요하지 않게 되었습니다. 다음은 장르 페이지 데이터 조회 API 함수의 일부 코드입니다. 가장 큰 차이점은 코드에서 if 문을 완전히 제거했다는 점입니다.

// 변경 후

export async function GET(request: Request) {
  try {
    // ...
    const currentGenre = url.searchParams.get("currentGenre");
    const query = { genre: currentGenre };
    const skipCount = SUB_PER_PAGE_COUNT * currentPage - SUB_PER_PAGE_COUNT;
    const genreData = await Music.find(query)
      .sort(sortKey)
      .skip(skipCount)
      .limit(SUB_PER_PAGE_COUNT);

    // ...

    return NextResponse.json({ genreData, genreDataCount });
  }

배운 점

  • 상수의 개념에 대해 이해했습니다.
  • 긴 조건식을 변수화해 코드의 가독성을 높이는 스킬을 터득했습니다.
  • 하나의 함수는 한 가지 동작만 처리해야 한다는 점을 배웠습니다.