본문 바로가기

프로그래밍 일반

[우아한 테크코스 6기 - 프리코스(프론트엔드)] 회고 3: 변수명 짓기

이 시리즈는 우아한 테스코스 6기의 프리코스 과정에서 유용했던 내용을 주제 별로 정리하고 있습니다. 

복잡한 프로젝트일수록 유지보수나 협업을 위해 직관적인 변수명을 사용해야 한다. 그렇다고 해서 이름을 축약해도 안되고 너무 상세하게 지어도 안되니 감이 안잡히는데 이번 기회에 기본적인 규칙을 정리했다.

예시로는 너무 간단한 프로젝트를 드는 건 의미가 없으니, mvc 패턴을 적용한 프로젝트라 생각해보자.

 

1. 한눈에 예측 가능한 변수명은 1,2 단어가 적당하다. 많아도 3단어를 넘지 말자.

가장 중요하고 간단하지만, 이 규칙을 지키기가 쉽지 않다. 이유는 이렇다.
1~2 단어로 메소드명을 지을 경우, 단어 각각은 메소드가 하는 역할과 그 대상을 가리킨다. 예컨대, 컴퓨터와 3판 2선승 가위바위보를 하는 게임을 생각해보자.

추상적 수준에서 과정을 분할하면

  • 게임을 시작한다.
  • 유저가 낼 것을 입력한다.
  • 컴퓨터가 낼 것을 랜덤으로 결정한다.
  • 유저와 컴퓨터 간 승패를 결정하는 로직이 실행된다.
  • 승패결과를 출력한다.
  • 한 명이 2선승을 할 때까지 위 과정을 반복한다.
  • 최종 결과를 출력한다.
  • 재시작 여부를 입력한다.

 

간단한 게임이지만, 유지보수와 확장을 고려하여 모듈로 나눠보자. 일단,  유저에게 입출력을 하는 로직은 view.js에 넣는다. 로직을 결정하는 주요 값은 변수로는 유저의 가위바위보와 컴퓨터의 가위바위보, 승리 횟수, 상수로는 가위바위보 간의 우열이 있다. 여기서 app.js가 단순히 게임의 시작만을 책임진다면, 대부분의 주요 로직은 추상적인 큰 수준에서는 controller.js가 담당하고 그 아래의 하위로직은 model.js에게 맡길 수 있다.

 

2. 함수의 역할이 입력(input), 출력(print), , 유효성 검사(validate), 형식 변환(parsing), 계산(calculate) 같은 거면, mvc 디자인의 파일 모듈 내에 위치시키는 것으로 생략이 가능하다.

위 예시에서 view.js에는 두 객체를 생성할 수 있다. 하나는 input, 다른 하나는 print이다. 이름만 봐도 각자가 무엇을 할지 알 수 있다. input에는 두 가지 메소드가 필요하다. 하나는 유저가 낼 가위바위보를 입력받는 메소드, 다른 하나는 유저의 재시작 여부를 입력받는 메소드다. 

단순하게 생각하면, 전자는 inputUserCard, 후자는 inputUserRestart 정도가 된다. 여기서 더 줄인다면, user를 뺄 수도 있다 (입력은 유저만 한다고 생각하면 말이다) . 그러나, 그냥 card, restart라고 지어도 무방하다. 왜냐하면 두 메소드를 실제로 쓸 때는 input.card, input.restart 이니까. 디자인에서 함수는 각자 고유의 기능을 하지만, 이런 큰 범주(입력, 출력, api, 이벤트 트리거...)에서 객체로 파일 모듈과 객체로 묶을 수 있다. 그리고 이 자체가 좋은 접두사가 되니, 내부의 메소드에서는 이런 부분을 과감히 빼도 된다.

 

3. 로직은 도메인 단위로 파일 모듈이나 객체를 나누자. 이름 짓기가 편해진다.

비즈니스 로직명은 접두사에 calculate를 붙이는 것만으로 충분하지 않다. 기능 중 "컴퓨터가 낼 것을 랜덤으로 결정한다."를 담당하는 함수는 randomComputerCard가 될 수 있다. 반면,  카드 간 승패를 결정하는 건 matchCardWin, 무승부일 시 재경기를 일으키는 로직은 triggerRematch, 한 명이 2선승을 하면 최종결과를 출력하도록 하는 로직은 triggerFinalResult가 될 수 있다. model의 주요 로직은 기능이 다양하다 보니, 접두사가 다양해진다.

이를 묶는 한 가지 방법은 도메인 별로 객체화하는 것이다. 예컨대, 조건부로 로직을 트리거하는 로직은 접두사에 trigger가 공통적으로 trigger가 붙을 수 있다. 이럴 때에는 trigger 객체에 이들을 넣고 Rematch와 FinalResult로 이름 지을 수 있다.

 

4. 이름은 함부로 축약하지 않는다. 메소드 간 구분을 위해 연속 숫자나 불용어를 사용하지 않는다.

연속 숫자로 이름을 구분한다는 건 이런 거다.

- input1, input2, 

 

불용어라는 건 특정한 별 의미가 없는 수식어로, data, number, string, info를 가리킨다. 예컨대 이런 식이다.

- printData, parsingString

 

 

5. 일관된 이름은 때때로 함수 작동을 예측하기 편하게 만든다.

함수가 어떤 인풋을 받고 어떤 아웃풋을 내보내는지는 직관적으로 알기 편해야 한다. 이를 위해 타입 스크립트나 js Doc 같은 방법이 있지만, 이름만으로도 이런 작동 과정을 알기 좋게 만들 수 있다. 예컨대, 유효성 검사를 위한 validate.js에서는 반환 방식이 크게 두 가지일 수 있는데, 하나는 불리언 타입을 반환하는 것이고, 다른 하나는 throw new Error을 하는 것이다. 이럴 때는 전자의 접두사에 is를 붙이고(validate.isCard - 올바른 카드를 냈는지 검사), 후자에는 throw를 붙일 수 있다.(validate.throwCard)

 

6. 상수는 대문자 스네이크 케이스로 작성한다. 

상수는 말그대로 불변하는 상수임을 알 수 있게 해야 한다. 이를 위해 많이 쓰는 방법이 대문자 스네이크 케이스다. 

 

* 예시

INPUT_CARD = ["가위", "바위", "보"]

INPUT_MESSAGE_RESTART = "재시작하시겠습니까?"

PRINT_MESSAGE_COMPUTER_WIN = "컴퓨터가 승리했습니다."

 

상수명도 공통되는 부분이 있다면, 파일이나 객체로 묶어주는 것도 좋다. 이런 경우

contants/message.js를 생성하고 message 객체 내에 INPUT_MESSAGE_RESTART, PRINT_MESSAGE_COMPUTER_WIN를 넣으면 이름에서 MESSAGE를 빼도 무방해진다.