1. 토크나이저: 코드를 의미있는 조각으로 나누기
첫 번째 단계는 바로 **토크나이저(Tokenizer)**입니다. 토크나이저는 우리가 작성한 '달빛 약속' 코드, 즉 순수한 문자열을 컴퓨터가 이해할 수 있는 의미있는 단위의 목록으로 변환하는 중요한 역할을 합니다.
이 과정을 토크나이징(Tokenizing) 또는 **어휘 분석(Lexical Analysis)**이라고 부릅니다. 너무 어려운 말처럼 느껴진다면, 그냥 "코드를 단어 단위로 쪼개는 과정"이라고 생각해도 좋습니다.
토큰(Token)이란 무엇일까요?
토크나이저가 코드를 쪼갠 결과물을 **토큰(Token)**이라고 합니다. 토큰은 문법적으로 더 이상 나눌 수 없는 가장 작은 단위입니다. 예를 들어, 다음과 같은 코드가 있다고 해봅시다.
결과 = 10
사람의 눈에는 이 코드가 "결과라는 변수에 10을 할당한다"는 의미로 보이지만, 토크나이저는 이 문장을 다음과 같은 토큰의 목록으로 인식합니다.
결과
: 변수나 함수의 이름을 나타내는Identifier
(식별자) 토큰=
: 값을 할당하는Operator
(연산자) 토큰10
: 숫자 값을 나타내는Number
(숫자) 토큰
이처럼 토크나이저는 단순한 문자열에 종류
와 값
이라는 속성을 부여하여, 의미를 가진 구조적인 데이터(토큰)로 만들어줍니다.
TIP
공백과 개행 또한 토크나이저에서는 토큰으로 처리됩니다.
'달빛 약속'의 토크나이저 엿보기
'달빛 약속'의 토크나이저는 정규표현식(Regular Expression)을 기반으로 코드를 분석합니다. tokenize.ts
파일에 이 로직이 구현되어 있습니다.
간단한 코드가 실제로 어떻게 변환되는지 볼까요?
입력 코드:
# 변수를 만들고, 화면에 출력합니다.
결과 = 10 * (2 + 3)
보여주기(결과)
토크나이저의 출력 (토큰 목록):
[
{ "type": "Identifier", "value": "결과" },
{ "type": "Operator", "value": "=" },
{ "type": "Number", "value": "10" },
{ "type": "Operator", "value": "*" },
{ "type": "Bracket", "value": "(" },
{ "type": "Number", "value": "2" },
{ "type": "Operator", "value": "+" },
{ "type": "Number", "value": "3" },
{ "type": "Bracket", "value": ")" },
{ "type": "Identifier", "value": "보여주기" },
{ "type": "Bracket", "value": "(" },
{ "type": "Identifier", "value": "결과" },
{ "type": "Bracket", "value": ")" }
]
💡 주목할 점: 주석 (
#
으로 시작하는 부분)은 토큰 목록에서 사라진 것을 볼 수 있습니다. 토크나이저는 이처럼 문법적으로 의미 없는 부분들을 걸러내는 역할도 합니다.
이제 우리는 코드가 어떻게 의미있는 조각으로 나뉘는지 알게 되었습니다. 하지만 이 토큰 목록만으로는 아직 코드의 전체 구조를 알 수 없습니다. 결과 = 10
이라는 문장이 어떤 의미인지, 보여주기(결과)
가 함수를 호출하는 것인지 아직은 알 수 없죠.
다음 장인 **파서(Parser)**에서 이 토큰들을 조합하여 어떻게 문법적인 구조(AST)를 만들어내는지 알아보겠습니다.