JavaScript 어휘 구조와 기본 문법 규칙 심층 분석

문법적 기원과 대소문자 구분

ECMAScript 명세는 C, Java, Perl 등 C계열 언어의 문법적 특징을 상당 부분 계승했습니다. 중괄호({})를 활용한 코드 블록 정의와 유사한 제어 흐름 구조를 가지므로, 기존 프로그래밍 경험이 있는 개발자라면 비교적 빠르게 적응할 수 있습니다. JavaScript는 대소문자를 명확히 구분하는 언어로, 키워드, 변수명, 함수명, 연산자 모두 대소문자 차이가 있으면 완전히 다른 토큰으로 인식됩니다. 예를 들어 typeof 연산자를 TypeofTYPEOF로 작성하면 참조 오류가 발생합니다.

let lowerCaseData = '소문자 기반 값';
let UPPERCASEDATA = '대문자 기반 값';
console.log(lowerCaseData); // '소문자 기반 값'
console.log(UPPERCASEDATA); // '대문자 기반 값'

식별자 명명 규칙

식별자(Identifiers)는 변수, 상수, 함수, 클래스, 매개변수 등의 이름을 지칭합니다. 유효한 식별자를 정의하려면 다음 규칙을 준수해야 합니다.

  • 첫 글자는 반드시 영문자, 언더스코어(_), 또는 달러 기호($)여야 합니다.
  • 두 번째 글자부터는 영문자, 숫자, 언더스코어, 달러 기호를 자유롭게 조합할 수 있습니다.
  • 숫자로 시작하는 것은 허용되지 않으며, 이는 리터럴 숫자와의 모호함을 방지하기 위한 설계입니다.

유효한 식별자 예시: _tempVal, $apiResponse, userCount2, __privateFlag

주석 처리 방식

코드 가독성과 유지보수를 위해 C언어 스타일의 주석 기능을 제공합니다. 단일 행 주석은 // 이후의 텍스트를 무시하며, 블록 주석은 /*로 시작하여 */로 끝나고 여러 줄에 걸쳐 작성 가능합니다. 블록 주석의 중첩은 지원하지 않습니다.

// 단일 라인 주석: 상태 플래그 초기화
let isActive = true;

/*
 * 다중 라인 주석
 * 복잡한 설정 객체 정의 시 활용
 * 임시로 코드 블록을 비활성화할 때도 사용 가능
 */
let systemConfig = { mode: 'production', debug: false };

엄격 모드(Strict Mode) 적용

ECMAScript 5부터 도입된 엄격 모드는 잠재적인 오류를 사전에 차단하고, 안전하지 않은 문법 사용을 제한하는 실행 컨텍스트를 제공합니다. 전역 또는 함수 수준에서 "use strict"; 지시문을 선언하면 활성화됩니다. 이 지시문은 문자열 리터럴 형태이지만, 하위 버전과의 호환성을 해치지 않으면서 엔진에게 파싱 방식을 변경하도록 신호를 보냅니다.

// 전역 엄격 모드 활성화
"use strict";

function processUserData(input) {
  // 함수 스코프에서만 엄격 모드 적용
  "use strict";
  let result = input.trim();
  return result;
}

엄격 모드는 암시적 전역 변수 생성 방지, this 바인딩 규칙 변경, 삭제 불가 속성 삭제 시도 시 오류 발생 등 실행 환경을 개선합니다. 현대 브라우저는 대부분 지원하지만, 레거시 환경 고려 시 점진적 적용이 권장됩니다.

리터럴(Literal)의 개념

리터럴은 소스 코드 내에 직접 표기된 고정된 데이터 값을 의미합니다. 변수에 할당하기 전의 원시 값 자체를 지칭하며, 코드 실행 시 별도의 계산 없이 즉시 값으로 인식됩니다. 대표적인 예로 42, 3.14, "hello", true, null, [1, 2, 3], { key: "value" } 등이 있습니다.

키워드와 예약어 관리

ECMAScript 명세는 언어의 제어 흐름과 구조를 정의하는 키워드와 미래 버전을 위해 미리 확보한 예약어를 명시합니다. 이 단어들은 식별자나 일반 속성명으로 사용할 수 없습니다.

분류단어 목록
핵심 키워드break, case, catch, continue, debugger, default, delete, do, else, export, extends, finally, for, function, if, import, in, instanceof, new, return, super, switch, this, throw, try, typeof, var, void, while, with, yield, class, const, let
예약어 (미래/컨텍스트 제한)enum, implements, interface, package, private, protected, public, static, await(모듈 컨텍스트)

호환성과 코드 명확성을 위해 이러한 단어는 변수명이나 함수명으로 사용하지 않는 것이 안전합니다.

세미콜론과 자동 삽입(ASI) 메커니즘

JavaScript는 문장(Statement)의 경계를 구분하기 위해 세미콜론(;)을 사용합니다. 명시적 세미콜론 사용은 코드의 의도를 명확히 하고 파싱 오류를 방지하는 좋은 습관입니다. JavaScript 엔진은 자동 세미콜론 삽입(ASI, Automatic Semicolon Insertion) 메커니즘을 통해 줄바꿈을 세미콜론으로 간주하기도 하지만, 이 규칙에는 중요한 예외와 함정이 존재합니다. ASI는 다음 토큰이 현재 문법의 연장선으로 해석될 수 없을 때만 줄바꿈을 세미콜론으로 대체합니다.

let totalScore = 85
let bonusPoints = 10;
// 첫 줄은 ASI에 의해 세미콜론이 자동 삽입되어 정상 실행됨

그러나 아래 코드는 의도치 않게 단일 문장으로 병합되어 오류를 유발합니다.

let baseValue = 100
(function() { console.log('executed'); })()
// 파서 해석: let baseValue = 100(function() { ... })() -> TypeError 발생

이를 방지하려면 명시적으로 세미콜론을 추가해야 합니다. ASI가 작동하지 않거나 예외가 발생하는 주요 사례는 다음과 같습니다.

  1. return, throw, break, continue, yield 뒤에 줄바꿈이 오면, 엔진은 즉시 세미콜론을 삽입합니다. 따라서 반환 값이나 레이블은 반드시 키워드와 같은 줄에 위치해야 합니다.
    return
    { status: 'ok' }; // 실제로는 return; 과 객체 리터럴로 분리되어 undefined 반환
  2. 후위 증가/감소 연산자(++, --)는 피연산자와 같은 줄에 있어야 합니다. 줄바꿈 시 전위 연산자로 잘못 해석되거나 ASI가 개입할 수 있습니다.
  3. 화살표 함수 정의 시 => 토큰은 매개변수 목록과 동일한 줄에 위치해야 합니다.

태그: JavaScript ECMAScript StrictMode ASI LexicalStructure

9월 22일 15:35에 게시됨