본문 바로가기

JavaScript

자바스크립트와 세미콜론

자바스크립트와 세미콜론

자바스크립트 엔진은 일정 규칙에 따라 세미콜론을 자동으로 삽입해준다.
(물론 세미콜론을 붙이는 것이 기본이다)
가끔 오픈소스들을 둘러보다 보면 세미콜론을 삽입하지 않은 코드를 어렵지 않게 본다. 
단지 가독성을 위해서만 세미콜론이 필요한가?

예1

아래와 같이 세미콜론이 생략된 코드가 있다.
const a = 5
const b = 10
const c = a + b
 
[123].forEach((e) => console.log(e))
cs

코드만 봐도 어렵지 않게 아래와 같은 결과를 기대할 것이다. 
1
2
3


그러나 직접 실행해보면 아래와 같은 에러를 뱉는다.
[1, 2, 3].forEach((e) => console.log(e)) 
 
TypeError: Cannot read property 'forEach' of undefined

위 코드에서 자바스크립트 엔진은 line 1 을 훑고 line 2로 내려간다.
const라는 키워드(offending token)를 만나면, line 1 끝에 세미콜론을 삽입한다.  line 2도 마찬가지다.

line 3 을 훑고 line 5로 내려갈 때는 조금 다르다.
line 3의 b가 line 5의 [ 를 만나 b[ 가 되어 배열로 인식하는 것이다. 

따라서 line 3 과 line 5가 한 줄의 코드처럼 인식되며,
b[1,2,3]undefined 가 되므로 에러가 발생하는 것이다.

예2

예1은 자바스크립트가 예상과 다르게 세미콜론을 자동으로 삽입해주지 않아 에러가 발생한 것이고, 예2는 세미콜론이 의도하지 않은 곳에 삽입되어 발생하는 것이다. 
const sum = (a, b) => {
  return 
  {
    result: a + b
  }
}
 
const result = sum(13)
console.log(result)
cs

1과 3을 더하는 것으로 {result: 4} 라는 결과값을 기대할 것이다. 
하지만 결과는 undefined가 된다.

그 이유는 return 에서 찾을 수 있다. 
자바스크립트 엔진이 return 다음에 자동으로 세미콜론을 삽입함으로써 곧바로 sum()을 빠져나오고, 아래의 line 3, 4, 5에 닿지 못한다.

세미콜론 없이 기대한 결과를 얻기 위해서는 아래와 같이 return과 같은 라인에 { 를 배치하는 것으로 고쳐야 한다.
const sum = (a, b) => {
  return {
    result: a + b
  }
}
 
const result = sum(13)
console.log(result)
cs

라인만 변경했을 뿐이지만 제대로 결과가 출력된다. 
[object Object] {
result: 4
}

결론

위와 같은 세미콜론 자동 삽입 기능을 ASI(Automatic Semicolon Insertion) 이라고 한다. 

함수나 클래스 정의 등에선 세미콜론을 붙이지 않으므로 아예 모든 코드에서 세미콜론을 빼 버리자는 주장도 본다. ASI 규칙을 유의하면 얼마든지 가능한 이야기다.

그러나 ASI 규칙을 외우고 주의하는 것보다 세미콜론을 사용하면서 에디터와 lint의 도움으로 세미콜론이 찍히지 않을 곳을 찾아내는 것이 훨씬 편하고, 위와 같이 예상치 못한 에러를 방지할 수 있지 않을까 싶다. 

무조건 넣어야 된다는 쪽과 넣지 않아도 된다는 쪽이 갈리지만, 
넣으려면 다 넣고 빼려면 전부 빼야 한다는 것은 이견이 없는 것 같다.