3.2 코딩 스타일

컬러·2021년 1월 24일
0

JavaScript

목록 보기
21/27

개발자는 가능한 간결하고 읽기 쉽게 코드를 작성해야 한다.

복잡한 문제를 간결하고 사람이 읽기 쉬운 코드로 작성해 해결하는 것이야말로 진정한 프로그래밍 기술이다. 좋은 코드 스타일은 이런 기술을 연마하는 데 큰 도움을 준다.

문법

몇 가지 추천할만한 규칙을 아래 치트 시트를 보고 확인해보자.

⚠ 무조건 따라야 할 규칙은 없다

중괄호

대부분의 자바스크립트 프로젝트에서 여는 중괄호는 '이집션(Egyptian)' 스타일을 따라 새로운 줄이아닌 상용하는 키워드와 같은 줄에 작성한다. 여기에 더하여 여는 중괄호 앞엔 공백이 하나 있어야 한다.

예)

if (condition) {
  // 코드1
  // 코드2
  // ..코드 n..
}

if (condition) doSomething()과 같은 단 한 줄짜리 구문을 중요하게 다뤄야 할 에지 케이스이다. 이런 예외상황에도 중괄호를 써야 할까?

어떻게 코드를 작성해야 가독성이 좋은지 예시를 보고 직접 판단해보자.

  1. 초보 개발자들은 아래처럼 코드를 작성하곤 하는데, 중괄호가 필요하지 않기 때문에 추천하지 않는다.
if (n < 0) {alert('Power ${n} is no suported');}
  1. 중괄호 없이 새로운 줄에 코드를 작성할 수도 있는데, 이렇게 하면 새로운 코드 라인을 추가할 때 에러가 발생한다. 절대 이 방법은 사용하지 말자!
if (n < 0)
  alert('Power ${n} is no supported');
  1. 코드가 짧다면 중괄호 없이 한 줄에 쓰는 방법도 괜찮다.
if (n < 0) alert('Power ${n} is not supported');
  1. 가장 추천하는 방법은 다음과 같다.
if (n < 0) {
  alert('Power ${n} is not supported');
}

if (cond) return null 처럼 코드가 간단하다면 세 번째 예시같이 한 줄에 몰아서 작성해도 괜찮다. 그렇지만 네 번재 예시처럼 코드 블록을 사용하는 방법이 가장 가독성이 좋으므로 이 방법을 추천한다!

가로 길이

가로로 길게 늘어진 코드를 읽는 걸 좋아하는 개발자는 없다. 코드 가로 길이가 길어진다면 여러 줄로 나눠 작성하는 게 좋다.

예)

// 백틱(`)을 사용하면 문자열을 여러 줄로 쉽게 나눌 수 있습니다.
let str = `
  ECMA International's TC39 is a group of JavaScript developers,
  implementers, academics, and more, collaborating with the community
  to maintain and evolve the definition of JavaScript.
`;

if 문이라면 아래와 같이 작성할 수 있을 것이다.

if (
  id === 123 &&
  moonPhase === 'Waning Gibbous' &&
  zodiacSign === 'Libra'
) {
  letTheSorceryBegin();
}

최대한 가로 길이는 팀원들과 합의해 정하는게 좋다.

들여쓰기

들여쓰기에는 두 종류가 있다.

  • 가로 들여쓰기: 스페이스바 두 개 혹은 네 개를 사용해 만듦
    예)
show(parameters,
     aligned, // 스페이스 다섯 개를 이용해 들여쓰기 함
     one,
     after,
     another
  ) {
  // ...
}
  • 세로 들여쓰기: 논리 블록 사이에 넣어 코드를 분리해주는 새 줄
    예)
function pow(x, n) {
  let result = 1;
  //              <--
  for (let i = 0; i < n; i++) {
    result *= x;
  }
  //              <--
  return result;
}

이렇게 여분의 줄을 넣어주면 코드의 가독성이 좋아진다.

세미콜론

자바스크립트 엔진에 의해 무시되더라도 모든 구문의 끝엔 세미콜론을 써주는 것이 좋다.

경험이 많은 자바스크립트 개발자라면 세미콜론이 없이 코드를 작성할 수 있지만 초보 개발자라면 에러를 만들 확률을 줄이기 위해서라도 세미콜론을 사용하는 게 좋다.

중첩 레벨

가능하면 너무 깊은 중첩문은 사용하지 않도록 하자.
반복문을 사용할 때 중첩문의 깊이가 길어지면 continue 지시자를 쓰는 게 좋은 대안이 도리 수도 있다.

if문으로 조건을 처리하는 예시를 살펴보자.

for (let i = 0; i < 10; i++) {
  if (cond) {
    ... // <- 중첩 레벨이 하나 더 늘어났습니다.
  }
}

위 코드는 continue를 써서 아래와 같이 바꿀 수 있다.

for (let i = 0; i < 10; i++) {
  if (!cond) continue;
  ...  // <- 추가 중첩 레벨이 추가되지 않습니다.
}

if/elsereturn 문을 조합하면 위 예시와 유사하게 중첩 레벨을 줄여 코드의 가독성을 높힐 수 있다.

아래 두 예시는 동일하게 동작한다.

예시 1)

function pow(x, n) {
  if (n < 0) {
    alert("'n'은 음수가 될 수 없습니다.");
  } else {
    let result = 1;

    for (let i = 0; i < n; i++) {
      result *= x;
    }

    return result;
  }
}

예시 2)

function pow(x, n) {
  if (n < 0) {
    alert("'n'은 음수가 될 수 없습니다.");
    return;
  }

  let result = 1;

  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

n < 0인 '특별한 상황’을 앞에 두고, 그 안에 return문을 추가해주었더니 가독성이 훨씬 좋아졌다. 특별한 상황인지를 확인하고 조건을 통과하면 추가 중첩 없이 ‘주요’ 코드 흐름으로 넘어가게 코드를 짰기 때문이다.

함수의 위치

'핼퍼' 함수 여러 개를 만들어 사용하고 있다면 아래와 같은 방법을 사용해 코드 구조를 정돈할 수 있다.

  1. 헬퍼 함수를 사용하는 코드 에서 핼퍼 함수를 모아 선언하기
// 함수 선언
function createElement() {
  ...
}

function setHandler(elem) {
  ...
}

function walkAround() {
  ...
}

// 헬퍼 함수를 사용하는 코드
let elem = createElement();
setHandler(elem);
walkAround();
  1. 코드를 먼저, 함수는 그 다음에 선언하기
// 헬퍼 함수를 사용하는 코드
let elem = createElement();
setHandler(elem);
walkAround();

// --- 헬퍼 함수 ---
function createElement() {
  ...
}

function setHandler(elem) {
  ...
}

function walkAround() {
  ...
}
  1. 혼합: 코드 바로 위에서 필요한 핼퍼 함수 그때그때 선언하기.

대개는 두 번째 방법으로 코드를 정돈하는 걸 선호한다.

사람들은 이 코드가 '무엇을 하는지' 생각하며 코드를 읽기 때문에 코드가 먼저 나오는 것이 자연스럽다. 이름만 보고도 핼퍼 함수의 역할을 쉽게 유추할 수 있게 핼퍼 함수 이름을 명명했다면 함수 본문을 읽을 필요도 없다.

스타일 가이드

코딩 스타일 가이는 코드를 '어떻게 작성할지'에 대한 전반적인 규칙을 담은 문서로, 어떤 따옴표를 쓸지, 들여쓰기할 때 스페이스를 몇 개 사용할지, 최대 가로 길이는 몇까지 제한할지 등의 내용이 담겨있다.

유명 스타일 가이드:

Linter

Linter라는 도구를 사용하면 내가 작성한 코드가 스타일 가이드를 준수하고 있는지를 자동으로 확인할 수 있고, 스타일 개선과 관련된 제안도 받을 수 있다.

이렇게 자동으로 스타일을 체크받다 보면, 변수나 함수 이름에 난 오타 등이 유발하는 버그를 미리 발견할 수 있어서 좋다.

아직 '코드 스타일’을 정하지 않았더라도 linter를 사용하면 버그를 예방할 수 있기 때문에 linter 사용을 권장한다.

유명 linter:

  • JSLint – 역사가 오래된 linter
  • JSHint – JSLint보다 세팅이 좀 더 유연한 linter
  • ESLint – 가장 최근에 나온 linter

위 linter 모두 훌륭한 기능을 제공한다.

대부분의 linter는 플러그인 형태로 유명 에디터와 통합해 사용할 수 있다. 원하는 스타일을 설정하는 것 역시 가능하다.

  1. Node.js를 설치.
  2. npm(자바스크립트 패키지 매니저)을 사용해 다음 명령어로 ESLint를 설치. npm install -g eslint
  3. 현재 작성 중인 자바스크립트 프로젝트의 루트 폴더(프로젝트 관련 파일이 담긴 폴더)에 .eslintrc라는 설정 파일을 생성.
  4. 에디터에 ESLint 플러그인을 설치하거나 활성화. 주요 에디터들은 모두 ESLint 플러그인을 지원.

아래는 .eslintrc 파일의 예시이다.

{
  "extends": "eslint:recommended",
  "env": {
    "browser": true,
    "node": true,
    "es6": true
  },
  "rules": {
    "no-console": 0,
    "indent": ["warning", 2]
  }
}

요약 ✔

이 챕터에 소개한 문법 규칙과 스타일 가이드 관련 참고자료들은 코드 가독성을 높이기 위해 만들어졌다.

'더 좋은' 코드를 만들려면 "가독성이 좋고 이해하기 쉬운 코드를 만들려면 뭉서을 해야할까?"라는 질문과 "에러를 피하려면 어떤 일을 해야 할까?"라는 질문을 스스로에게 던져야 한다. 어떤 코딩 스타일을 따를지 결정할 때와 이에 대한 논쟁을 한 땐 이런 질문을 기반으로 해야 한다.

유명 스타일 가이드를 읽다 보면 코드 스타일에 관한 경향과 모범 사례에 대한 최신 정보를 유지할 수 있다.

과제 ✔


좋지 않은 코드 스타일

아래 코드가 어떤 점에서 좋지 않은지 생각해보자.

function pow(x,n)
{
  let result=1;
  for(let i=0;i<n;i++) {result*=x;}
  return result;
}

let x=prompt("x?",''), n=prompt("n?",'')
if (n<=0)
{
  alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else
{
  alert(pow(x,n))
}

더 나은 코드로 수정해보자.

해답

function pow(x,n)
// <- 인수 사이에 공백이 없음
{  // <- 별도의 줄에 있는 중괄호
  let result=1;
  // <- 할당 연산자 = 앞/뒤에 공백이 없음
  for(let i=0;i<n;i++) {result*=x;}
  // 비교 연산자 < 앞/뒤에 공백이 없음
  // { ... }안의 코드는 새로운 줄에 위치해야 함
  return result;
}

let x=prompt("x?",''), n=prompt("n?",'')
// <-- 에러를 발생시키는 코드는 아니나,
// 두 줄로 나눠서 작성하는 게 좋고, 연산자 앞/뒤 공백과 문장 끝 ;를 넣어주는 게 좋음
if (n<=0) 
  // <- (n <= 0) 같이 공백을 넣는 게 좋고, 윗줄은 비워놓아야 함(세로 들여쓰기)
{   // <- 별도의 줄에 있는 중괄호
  // 아랫줄같이 가로 길이가 길어지면 가독성을 위해 코드를 여러 줄로 쪼개는 게 좋음
  alert(`Power ${n} is not supported, please enter an integer number greater than zero`);
}
else
  // <- "} else {"같이 else와 중괄호는 한 줄에 작성하는 게 좋음
{
  alert(pow(x,n)) 
 // 공백과 ; 가 없음
}

더 나은 코드로 변경

function pow(x, n) {
  let result = 1;

  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

let x = prompt("x?", "");
let n = prompt("n?", "");

if (n <= 0) {
  alert(`Power ${n} is not supported,
    please enter an integer number greater than zero`);
} else {
  alert( pow(x, n) );
}

0개의 댓글