ASI - Automatic Semicolon Insertion

BK·2025년 3월 20일

JavaScript

목록 보기
1/2


semicolon 따위 쓰지 않는다

ASI(Automatic Semicolon Insertion)

JavaScript를 사용해 본 사람이라면 알겠지만, 아래 코드는 동작한다.

var foo = 49;

console.log(foo)

분명 세미콜론(semicolon, ;)이 필요하지만, 위 코드에서 semicolon을 작성하지 않아도 정상적으로 49를 출력하는 것을 확인할 수 있을 것이다. 이는 JavaScriptASI(Automatic Semicolon Insertion) 덕분인데(덕분인지는 모르겠다), JavaScript의 parser는 누락된 semicolon을 자동으로 추가해주며 이를 ASI(Automatic Semicolon Insertion)라고 한다.

ASI 예시

위와 같이 console.log( ) 뿐 아니라, 함수의 return 에도 semicolon을 작성하지 않아도 정상적으로 동작한다.

funciton func(num) {
	return num*2
}

console.log(func(3))

위 코드를 실행 하면 6이 출력되는 것을 확인할 수 있다.

그렇다면, JS는 어떠한 상황에 대해 자동으로 semicolon을 삽입하는지 알아보겠다.

우선 아래와 같이 매우 이상한 상황을 살펴보자

// for loop
for(var i=0; i<10; i++) {
	console.log(i);
}

// without semicolon
for(var i=0 i<10 i++) {
	console.log(i);
}

for loop를 순회하며 i를 출력하는 코드에서 semicolon을 제거해 보았다. 결과는 SyntaxError, 즉 틀린 문법이라는 말이다. JavaScript는 기본적으로 개행(new line) 문자 전 구문에 대해 필요한 경우 ;을 삽입하는 것 같다. 개행 문자 전 semicolon이 필요한 것으로 판단되는 상황에 대해 JavaScript는 자동으로 ;을 삽입해 정상적으로 동작할 수 있도록 하는 것이다.

하지만 그렇다고 해서 위와 같은 for loop에 semicolon을 아래와 같이 생략할 수는 없다.

for(
		var i=0
		i<10
		i++
) {
	console.log(i);
}

for loop에 사용되는 ;은 필수적인 문법이기 때문에, ASI에 해당하는 것이 아니며, ASI는 문장 끝 누락된 ;을 자동으로 삽입해 주는 것으로 보인다.

다음으로 함수의 return에 관련된 예시를 살펴보자

function func(num) {
	return
		num*2
}

console.log(func(5));
function func(num) {
	return num
	*2
}

console.log(func(5));

위 두 코드를 실행해 보면, 각각 undefined10을 출력한다. 첫 번째 코드는 return 뒤에 ;이 삽입되어 undefined를 출력하게 되고, 두 번째 코드는 return num 이후가 아닌, 그 다음 줄의 *2 까지 포함된 num * 2를 return 하게 되어 10을 출력하게 되는 것이다.

JS는 기본적으로 개행 문자를 바탕으로 누락된 semicolon을 판단하며, 어떠한 규칙에 따라 ;을 적절한 위치에 삽입하는 것으로 예상할 수 있다.

ASI 규칙

JavaScript가 자동적으로 semicolon을 삽입하는 규칙에 대해 알아보자

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#automatic_semicolon_insertion

ASI 적용 범위

MDN web docs에 따르면 ASI가 적용되는 범위는 아래와 같다.

  • var, let, const : 변수 선언
  • Expression statements
  • do ... while
  • continue, break, return, throw : 제어문
  • debugger
  • Class field declarations(public or private)
  • import, export - 모듈 import/export

ASI 적용 규칙

또한, 위 문서에서 ASI가 적용되는 상황을 확인할 수 있으며, 이는 아래와 같다.

1. 문법에 맞지 않는 상황에서 개행 문자 등으로 구분 된 경우

요약하자면 위와 같이 표현할 수 있으며, 자세한 설명은 아래와 같다.

문법적으로 허용되지 않는 token이 나왔으며, 이전 token과 적어도 하나의 line terminator(개행 등)으로 나누어진 상황. 다음 token이 }인 경우에도 삽입된다.

"When a token not allowed by the grammar is encountered, and it's separated from the previous token by at least one line terminator (including a block comment that includes at least one line terminator), or the token is "}", then a semicolon is inserted before the token."

문서에서 제공하는 이에 대한 예시는 아래와 같다.

// before
{ 1
2 } 3

// after
{ 1
;2 ;} 3;

또한 문서에서는 위에서 작성한 for loop와 같은 상황에서는 ASI가 적용되지 않음을 명시하고 있다.

2. “마지막에”

자세한 설명은 아래와 같다.

Token들의 input stream의 끝에 도달했을 때, parser가 해당 input stream을 온전한 프로그램으로 parse 할 수 없을 때 semicolon은 마지막에 삽입된다.

"When the end of the input stream of tokens is reached, and the parser is unable to parse the single input stream as a complete program, a semicolon is inserted at the end."

3. “개행”

문법적으로 line terminator가 허용되지 않는 위치에 있을 때, semicolon이 삽입된다.

"When the grammar forbids line terminators in some place but a line terminator is found, a semicolon is inserted."

문서에서 제공하는 상황은 다양하며, ++/--, return, break 등이 있다.

“Never Use Semicolons”

https://feross.org/never-use-semicolons/

상당히 자극적인 제목이다. 위 링크에서는 JS 개발에서 semicolon을 사용하지 말아야 하는 이유에 대해 확인할 수 있으며, ASI에 대해 이해해야 함을 말하고 있다. 간략히 요약하자면, ASI로 인해 우리가 원하지 않는 코드로 바뀔 수 있으니, ASI에 대해 알아야 한다는 내용이다.

위 글의 예시를 가져오면

function foo() {
	return
		{
			bar: 1,
			baz: 2
		};
}

위와 같은 코드에서, 객체를 return하는 것으로 예상할 수 있겠지만, 사실 위 코드는 return ;으로 바뀌기 때문에 문제가 발생할 것이다.

아무튼 semicolon을 사용하는지 않는지가 문제가 아니라, 알아야 할 것이 늘었다.

Why ASI ?

다른 언어들과 같이 semicolon을 꼭 작성하도록 했다면 위와 같이 ASI에 대해 알아야 할 필요가 없을 것인데 왜 이러한 것을 추가해서 알아야 할 것들이 많아지는지 궁금해졌다.

정확한 이유는 모를 일이지만, JavaScript는 아주 짧은 시간에 만들어진 언어로 여러 문제점들이 많았기에 이 또한 비슷한 상황이지 않을까 싶었다.

https://brendaneich.com/2012/04/the-infernal-semicolon/

위 링크에서 JavaScript를 개발하신 Brendan Eich 님의 글을 보면

“I wish I had made newlines more significant in JS back in those ten days in May, 1995.“

개행(newline)을 더 의미 있게 만들었으면 하면 약간의 후회를 찾아볼 수 있다.

또한 위 글에서 이 선생님께서는

“The moral of this story: ASI is (formally speaking) a syntactic error correction procedure.”

ASI는 에러 수정(error correction) 과정임을 명시하고 있다.

그치만, 에러 수정을 위한 기능이 사람들을 머리 아프게 만들었다면 꼭 필요한 기능이었을까.


참고자료

Why was automatic semi-colon insertion (ASI) added to javascript?

The infernal semicolon

Never Use Semicolons » Feross.org

Lexical grammar - JavaScript | MDN

0개의 댓글