LHJ

I'm a FE developer.

5. 흐름제어문(Flow Control Statement) - 직접 흐름 제어(Label)

08 Aug 2020 » codespitz_re

직접 흐름 제어

현재 자바스크립트에서 사용할 수 있는 직접 흐름 제어(Direct Flow Control)Label이다. 다중 for 문을 썼을 때 바깥쪽 for 문으로 빠져나오고 싶어서 break를 걸려면 Label이란 걸 써야한다.

Label 특징

  • Label 이름 규칙 : 자바스크립트 변수 이름 규칙과 한가지만 다르다. ($를 Label 이름으로 쓸 수 없다는 점)
  • Label 외에 실제로 존재하는 ‘문’이 하나도 없으면 에러가 발생한다. (Label은 ‘문’이 아니라는 것)
  • Label은 Record에 달아주는 일종의 Tag(꼬리표) 같은 개념이다.

Label의 Scope

  • Label의 Scope는 Function으로 결정된다.
    <script >
      abc: {
          
      }
    </script>
    
  • Label 쉐도잉
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
      <script>
          // 이런식으로 LABEL SCOPE를 나눠주면 아래처럼 작성 가능
          // 원래 이렇게 하면 바깥 LABEL의 스코프와 안쪽 LABEL의 스코프가 다르므로 스코프에 대한 쉐도윙이 일어난다.
          // 함수 지역변수도 바깥 지역변수를 가릴 수 있는 것처럼 아래 내부 abc도 바깥 abc LABEL을 가릴 수 있다.
          abc:{
              abc:{
        
              }
          }
      </script>
      </body>
      </html>
    
  • 동영상 강의에선 safari는 Label Scope를 아예 인정하지 않는다는 에러문구가 뜸..
    Label은 그만큼 오래된 기법이다보니 스펙이 계속 바뀌기도하고 그런가 봄.
  • Label은 빠져나오기 위해 존재한다.
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
      <script>
          abc:{
              console.log('start');
              // break 뒤에 label 이름을 꼭 명시해야된다.
              // 안 그럼 Illegal break statement 에러가 뜬다.
              if (true) break abc;
              console.log('end');
          }
      </script>
      </body>
      </html>
    

  1. Label 스코프를 생성하고 나면, Label 스코프에선 Label을 빠져나올 수 있는 권리가 주어진다.
  2. Loop 문은 아니라 continue 문은 사용하지 못하지만 break 문은 사용할 수 있다.
  3. Label은 가장 원초적인 Flow Control이다.

Label이 아닌 곳에서도 위와 같은 흐름제어를 할 수 있을까?
그렇게 하기 위해선 Label을 나눠줘야 된다.
이를 Label Range라고 한다.

Label Range & Set

Label Range를 이해하려면 우선 Set을 먼저 인식해야 한다.
어떻게 해서 Label이 Label 영역을 가지는지를 알아야된다는 것이다.
위에선 Label Scope를 생성해주었지만 Scope를 생성해주지 않았을 때, 하나의 Label이 어디까지 영역을 잡느냐는 것이다.

  1. Label에 특별한 무언가가 없다면 다음 Label까지를 범위로 삼는다.
  2. Label 다음에 Iteration(for, while…)이 오거나 switch가 오면 범위를 한정짓는다.

하지만, 위 사진을 보면 Label Set 법칙처럼 작용하지 않는다.
Label에 특별한 무언가가 없다면 다음 Label 까지를 범위로 삼는다고 했다.
그렇다면 위의 사진에서 1은 찍히지 말았어야 한다.

Label이 break 문에서 정확하게 작동하게 하려면 반드시 다음 3가지 구문 중 한가지를 사용해야된다.

  1. Label 스코프를 선언하라
  2. Iteration Label이 되어라
  3. switch Label이 되어라

위 규칙을 지켜야 break 또는 루프구문 한정 continue를 쓸 수 있다.

Label은 if 문이나 for 문이 있기 전에 개발자들이 직접 Flow를 컨트롤하던 흔적이다.
Label은 break, continue와 같은 문밖에 사용 못한다. 즉, 아래로 내려가는 Flow 제어밖에 못한다. 즉, Label 만 가지고 Loop 문은 못 만든다. 아래로만 흐르기 때문에.

break
위에 Label에선 break 뒤에 Label 이름을 붙여줘야 했다.
그런데 for 문이나 while 문에선 그런거 없이 왜 break 문만으로 빠져나갈 수 있는 걸까?

for (let i=0; i<10; i++) {
    if (i === 5) break;
}

아까 위의 break 문에 Label 이름을 안 주면 Syntax Error가 발생했다. 위의 자바스크립트 식은 에러가 발생 안한다.
이유가 뭘까?

temp38:
for (let i=0; i<10; i++) {
    if (i === 5) break temp38;
}

자바스크립트 엔진이 위와 같이 알아서 Label 이름을 생성해서 넣어준 것이다.
이름을 생략하면 break 문 뒤에, 그리고 for 문 앞에 이름이 임의로 들어가게 된다.
이것이 바로 Auto Label 기능이다.

Auto Label
이런 Auto Label 기능은 Interation(for, while…), switch 문에서 발동된다.
그래서 이런 Auto Label이 만들어낸 이름을 Undefined Named Label이라고 한다.
Label Scope는 자동으로 만들어지지 않는다. (명심!)

Label을 권장하는 이유
다른 문은 Run Time에서 에러가 잡힌다.
그런데 Label은 바로 Syntax Error로 잡힌다.
Parsing할 때 검사한다는 것이다.
에러를 훨씬 더 빨리 찾을 수 있다.

AS COMMENT

Label을 Comment(주석)으로 사용하는 경우도 있다.
Label을 왜 주석 대신 사용할까?

그 이유는 깔끔함 때문이다.

console.log('abcd'); // a
console.log('abdkasdfljewiofslfjsld'); // b
console.log('0ewofiejflksdjflsa'); // c

주석이 지저분하게 달려있다.

a: console.log('abcd');
b: console.log('abdkasdfljewiofslfjsld');
c: console.log('0ewofiejflksdjflsa');

그래서 이렇게 앞 주석으로 사용하기 위해 Label을 사용하는 경우가 많다.
Label은 코드에 부하를 걸지 않는다.
어차피 만들어진 Record에 달리는 태그이기 때문이다.

다른 제어문과 Label의 차이점

다른 제어문은 위로 올라가기도 한다.
하지만 Label은 무조건 아래로 내려간다.