How break statement breaks break statement

최근에, 어떤 분의 프로그램을 고쳐드리면서 매우 재미있는 코드를 보았었습니다.

1
2
3
4
5
6
something: {
...
if(status === false)
break something;
else ...
}

오, 이런. 저도 자주 보지 못한 코드이기에 스타일을 지적하기 전에 실행을 시켜보았었습니다.

block statement test

세상에, 잘 작동합니다. 진짜 Block 문이 멈추어 버렸어요!

늘 그렇듯이, 까닭이 궁금했던 저는 바로 명세서를 뒤적거리기 시작했습니다.
그리고 자바스크립트의 명세서의 13.13.14 Runtime Semantics: LabelledEvaluation 에서 그 이유를 찾을 수 있었습니다.

1
2
3
4
5
6
1. Let label be the StringValue of LabelIdentifier.
2. Append label as an element of labelSet.
3. Let stmtResult be LabelledEvaluation of LabelledItem with argument labelSet.
4. If stmtResult.[[Type]] is break and SameValue(stmtResult.[[Target]], label) is true, then
a. Set stmtResult to NormalCompletion(stmtResult.[[Value]]).
5. Return Completion(stmtResult).

명세서를 읽을 줄 모르시는 분들을 위해, 간략하게 요약해 보자면.

Label이 달린 구문을 실행한 후, 그 결과가 자신을 대상으로 하는 break라면 그 break를 제어하여 오류가 발생하지 않게 막는다.
(자바스크립트의 명세서에서는 스크립트의 실행 결과가 break, return, continue, throw 라면 구현체에서 오류를 발생시키도록 명시하고 있습니다. 그래서 함수 객체를 실행시키는 [[Call]] 메서드 등을 보면 return을 normal(유일하게 오류를 일으키지 않는 결과)로 바꾸지요. 여기서도 마찬가자입니다.)

할 이야기는 전부 한 거 같으니, 간단한 Q&A를 진행하고 이만 마치도록 하겠습니다. 봐주셔서 감사합니다 :)

Q&A

Q: if 문에서도 사용 가능하나요?
A: 네, 됩니다.

Q: 많은 코드의 for 문, switch 문, while 문 등을 보면 대상을 지정하지 않는 break 를 사용하는 경우가 있는데 그 경우는 어디서 처리하나요?
A: 13.1.7 Runtime Semantics: LabelledEvaluation 에서 명시하고 있습니다. 간략하게 말씀드리자면 그 경우들은 가장 가까운 Breakable 문(switch, for, while 등)이 처리합니다.

Q: 좋은 방식인가요?
A: 제 주관적인 생각으로는 안티 패턴이라고 생각합니다. break로 구문의 진행을 저지해야 하는 경우를 생각해보면 전부 함수로 프로세스를 추상화하고 이들을 조합하는 방식으로 해결할 수 있고, 이 방법이 유지 보수 면에서 더 나은 방식이라고 생각합니다.

Reference

공유하기