Python 강좌 2편 - 파이썬의 어휘구조
어휘구조란?
우리가 파이썬 코드를 작성하면, 파이썬은 그것을 어떻게 이해할까요?
x = 42 + y
우리 눈에는 "변수 x에 42와 y를 더한 값을 넣어라"라고 보이지만, 파이썬 입장에서는 그냥 문자들의 나열일 뿐입니다.
'x', ' ', '=', ' ', '4', '2', ' ', '+', ' ', 'y'
파이썬이 코드를 실행하려면 먼저 이 문자들을 의미 있는 단위로 쪼개야 합니다. 마치 우리가 책을 읽을 때 글자들을 단어로 인식하는 것처럼요.
토큰: 의미의 최소 단위
코드를 쪼갠 의미 있는 조각들을 토큰(Token)이라고 부릅니다.
x = 42 + y
# 파이썬이 보는 토큰들:
# NAME: 'x'
# OP: '='
# NUMBER: 42
# OP: '+'
# NAME: 'y'
자연어와 비교하면 더 쉽습니다:
문장: "나는 밥을 먹는다"
단어: ["나는", "밥을", "먹는다"]
코드: "x = 42"
토큰: [NAME:'x', OP:'=', NUMBER:42]
어휘 분석: 토큰으로 쪼개기
어휘 분석(Lexical Analysis)은 코드를 읽어서 토큰으로 쪼개는 과정입니다.
이것이 파이썬 인터프리터가 하는 첫 번째 일입니다.
[소스 코드]
↓
[어휘 분석] ← 이번 강좌의 주제
↓
[토큰 리스트]
↓
[구문 분석]
↓
...
왜 이런 과정이 필요할까요?
코드를 한 번에 이해하려면 너무 복잡하기 때문입니다. 그래서 파이썬은 단계별로 나눠서 처리합니다. 어휘 분석은 그 첫 단계입니다.
어휘구조분석기가 작동하는 원리
어휘 분석기는 상태 기계(State Machine)라는 방식으로 작동합니다.
상태 기계가 뭔지 어렵게 느껴질 수 있는데, 우리 주변에서 흔히 볼 수 있는 개념입니다.
State Machine의 예시
1. 사람의 배고픔 상태
우리의 배고픔 상태를 생각해봅시다:
stateDiagram-v2
배고픔 --> 배부름: 식사
배부름 --> 배고픔: 운동
- 상태: 배고픔, 배부름
- 전이(transition): 식사를 하면 배고픔에서 배부름으로
- 다시 전이: 운동을 하면 배부름에서 배고픔으로
이것이 바로 상태 기계입니다! 특정 상태에 있다가, 입력이 들어오면 다른 상태로 바뀌는 시스템이죠.
2. 신호등
신호등도 상태 기계입니다:
stateDiagram-v2
빨간불 --> 초록불: 30초 경과
초록불 --> 노란불: 30초 경과
노란불 --> 빨간불: 3초 경과
- 상태: 빨간불, 노란불, 초록불
- 전이: 시간이 지나면 상태가 바뀜
- 규칙: 빨간불 → 초록불 → 노란불 → 빨간불 (반복)
3. 계산기의 입력 상태
계산기를 사용할 때를 생각해봅시다:
stateDiagram-v2
시작 --> 숫자대기
숫자대기 --> 연산자대기: 숫자 입력 (53, 10)
연산자대기 --> 숫자대기: 연산자 입력 (+)
연산자대기 --> 종료: (=) 입력
계산기는 항상 두 가지 상태 중 하나에 있습니다:
- 숫자를 기다리는 상태 (숫자대기)
- 연산자를 기다리는 상태 (연산자대기)
입력 "5 + 3 ="을 처리하는 과정:
1. 시작 → 숫자대기 → '53' 입력 → 연산자대기
2. 연산자대기 → '+' 입력 → 숫자대기
3. 숫자대기 → '10' 입력 → 연산자대기
4. 연산자대기 → '=' 입력 → 완료
이렇게 상태를 바꿔가며 입력을 처리하는 것이 상태 기계입니다.
어휘구조 분석 State Machine
이제 파이썬의 어휘 분석이 어떻게 작동하는지 살펴봅시다.
정수 인식하기
123이라는 문자열을 읽을 때의 상태 전이:
stateDiagram-v2
[*] --> 시작
시작 --> 숫자읽는중: 숫자 ('1')
숫자읽는중 --> 숫자읽는중: 숫자 ('2', '3')
숫자읽는중 --> [*]: 공백 또는 연산자
note right of 숫자읽는중
계속 숫자를 모음
예: "123"
end note
한 글자씩 읽으면서 "지금 숫자를 읽고 있구나"라는 상태를 유지하다가, 숫자가 아닌 문자를 만나면 토큰을 완성합니다.
결과: NUMBER 토큰: 123
실수도 인식하기
3.14처럼 소수점이 있으면 어떻게 될까요?
stateDiagram-v2
[*] --> 시작
시작 --> 정수읽는중: 숫자 ('3')
정수읽는중 --> 정수읽는중: 숫자
정수읽는중 --> 실수읽는중: 소수점 ('.')
실수읽는중 --> 실수읽는중: 숫자 ('1', '4')
정수읽는중 --> [*]: 공백/연산자
실수읽는중 --> [*]: 공백/연산자
note right of 실수읽는중
소수점 이하 숫자들을 모음
예: "3.14"
end note
정수를 읽다가 .을 만나면 "아, 실수구나!" 하고 상태를 바꿔서 소수점 이하 숫자들을 계속 읽습니다.
결과: NUMBER 토큰: 3.14
여러 종류 토큰 인식하기
실제 파이썬 코드 x = 42 + y를 어떻게 읽을까요?
stateDiagram-v2
[*] --> 시작
시작 --> 식별자읽기: 문자 ('x')
시작 --> 숫자읽기: 숫자 ('4')
시작 --> 연산자: 연산자 ('+', '=')
식별자읽기 --> 식별자읽기: 문자/숫자
식별자읽기 --> 시작: 공백 (NAME 토큰 생성)
숫자읽기 --> 숫자읽기: 숫자
숫자읽기 --> 시작: 공백 (NUMBER 토큰 생성)
연산자 --> 시작: (OP 토큰 생성)
시작 --> [*]: 문자열 끝
코드 x = 42 + y 처리 과정:
1. x → 문자 → 식별자 읽기 → 공백 → NAME: 'x'
2. = → 연산자 → OP: '='
3. 42 → 숫자들 → 공백 → NUMBER: 42
4. + → 연산자 → OP: '+'
5. y → 문자 → 끝 → NAME: 'y'
최종 결과: [NAME:'x', OP:'=', NUMBER:42, OP:'+', NAME:'y']
이렇게 상태 기계를 사용하면 복잡한 코드를 체계적으로 토큰으로 쪼갤 수 있습니다!
파이썬의 어휘구조
파이썬만의 특별한 어휘 규칙들을 알아봅시다.
1. 들여쓰기도 토큰이다
파이썬의 가장 큰 특징은 들여쓰기가 문법이라는 것입니다.
def greet():
print("hello") # 들여쓰기 1단계
if True:
print("world") # 들여쓰기 2단계
다른 언어들은 중괄호 {}를 사용하지만, 파이썬은 들여쓰기를 토큰으로 만듭니다:
# 파이썬이 보는 토큰들:
[
NAME: 'def',
NAME: 'greet',
OP: '(',
OP: ')',
OP: ':',
NEWLINE,
INDENT, # 들여쓰기 시작!
NAME: 'print',
...
NEWLINE,
DEDENT, # 들여쓰기 끝!
]
2. 여러 가지 문자열 표현
파이썬은 문자열을 다양하게 표현할 수 있습니다:
# 기본 문자열
s1 = 'hello'
s2 = "world"
# 여러 줄 문자열
s3 = """
여러 줄에 걸쳐
문자열을 쓸 수 있습니다
"""
# 이스케이프를 무시하는 Raw 문자열
s4 = r'\n은 줄바꿈이 아니라 그냥 \n 입니다'
# 변수를 넣을 수 있는 f-string
name = "파이썬"
s5 = f"안녕하세요, {name}!" # "안녕하세요, 파이썬!"
3. 다양한 숫자 표현
파이썬은 숫자를 여러 방식으로 쓸 수 있습니다:
# 일반 숫자
a = 42
# 2진수 (0과 1만)
b = 0b1010 # 10
# 8진수 (0~7)
c = 0o12 # 10
# 16진수 (0~9, A~F)
d = 0xA # 10
# 실수
e = 3.14
# 큰 숫자는 _로 구분 (읽기 쉽게)
f = 1_000_000 # 1000000
# 복소수
g = 3 + 4j
4. 실제 파이썬 토크나이저 확인하기
파이썬에는 토큰 분석을 직접 확인할 수 있는 tokenize 모듈이 있습니다.
코드 x = 42를 토큰으로 분석하면 이렇게 나옵니다:
NAME : 'x'
OP : '='
NUMBER : '42'
NEWLINE : '\n'
ENDMARKER : ''
우리가 예상한 대로 NAME, OP, NUMBER 토큰으로 쪼개지는 걸 확인할 수 있습니다!
정리
배운 내용
- 어휘 분석: 코드를 토큰으로 쪼개는 첫 번째 단계
- 토큰: 의미 있는 최소 단위 (변수명, 숫자, 연산자 등)
- 상태 기계: 상태를 바꿔가며 입력을 처리하는 방식
- 배고픔/배부름 (사람)
- 신호등 (빨강/노랑/초록)
- 계산기 (숫자 대기/연산자 대기)
파이썬의 특별함
- 들여쓰기가 토큰 (
INDENT,DEDENT) - 다양한 문자열 표현 (따옴표, f-string, raw 문자열)
- 여러 진법의 숫자 (2진수, 8진수, 16진수)
tokenize모듈로 직접 토큰 확인 가능
왜 중요한가?
어휘 분석을 이해하면:
- 파이썬이 코드를 어떻게 읽는지 알 수 있습니다
- 문법 오류를 더 잘 이해할 수 있습니다
- 나만의 언어를 만들 수도 있습니다!