Skip to main content

Command Palette

Search for a command to run...

Python 톺아보기 1화 - 토큰화(Tokenization)

Updated
4 min read

Python 에서는 코드를 의미 있는 단위로 나누기 위한 토큰화 작업을 거친다. 이 작업을 거치면 코드는 토큰으로 분해된다. 오늘은 tokenize 모듈을 사용해서 이를 한번 눈으로 보고 확인해보도록 하자.

import tokenize
import io

# 토큰 타입 이름 확인
print("주요 토큰 타입:")
print(f"  NAME: {tokenize.NAME} - 변수명, 함수명 등")
print(f"  NUMBER: {tokenize.NUMBER} - 숫자 리터럴")
print(f"  STRING: {tokenize.STRING} - 문자열 리터럴")
print(f"  OP: {tokenize.OP} - 연산자")
print(f"  NEWLINE: {tokenize.NEWLINE} - 줄바꿈")
print(f"  INDENT: {tokenize.INDENT} - 들여쓰기 시작")
print(f"  DEDENT: {tokenize.DEDENT} - 들여쓰기 종료")
print(f"  ENDMARKER: {tokenize.ENDMARKER} - 파일 끝")

이건 python 에서 주로 쓰이는 토큰 타입들이다. 이를 출력해보면 아래와 같이 출력된다.

주요 토큰 타입:
  NAME: 1 - 변수명, 함수명 등
  NUMBER: 2 - 숫자 리터럴
  STRING: 3 - 문자열 리터럴
  OP: 55 - 연산자
  NEWLINE: 4 - 줄바꿈
  INDENT: 5 - 들여쓰기 시작
  DEDENT: 6 - 들여쓰기 종료
  ENDMARKER: 0 - 파일 끝

토큰화 함수

기본적으로 tokenize.generate_tokens(readline) 함수를 사용합니다.

  • readline: 한 줄씩 읽어오는 함수

  • 반환: 토큰 네임드튜플 (type, string, start, end, line)

# 간단한 코드 토큰화 예시
code = "x = 1 + 2"
print(f"코드: {code!r}")
print("\n토큰 목록:")
print("-" * 60)

tokens = tokenize.generate_tokens(io.StringIO(code).readline)
for tok in tokens:
    tok_name = tokenize.tok_name[tok.type]
    print(f"{tok.type:3} {tok_name:12} {tok.string!r:15} 위치: {tok.start}-{tok.end}")
코드: 'x = 1 + 2'

토큰 목록:
------------------------------------------------------------
  1 NAME         'x'             위치: (1, 0)-(1, 1)
 55 OP           '='             위치: (1, 2)-(1, 3)
  2 NUMBER       '1'             위치: (1, 4)-(1, 5)
 55 OP           '+'             위치: (1, 6)-(1, 7)
  2 NUMBER       '2'             위치: (1, 8)-(1, 9)
  4 NEWLINE      ''              위치: (1, 9)-(1, 10)
  0 ENDMARKER    ''              위치: (2, 0)-(2, 0)

실제로 실행시켜보면 해당 토큰의 타입과 이름과 위치정보 등등이 표기 된다. 이를 통해 토큰이 파일내에서 어떤 위치에 있는지 등등을 판단할 수 있다.

INDENT, DEDENT

code2 = '''def greet(name):
    print(f"Hello, {name}!")
    return True
'''

print("=== 실습 2: 함수 정의 토큰화 ===")
print(f"\n원본 코드:")
print(code2)
print("=" * 70)
print(f"{'타입':<15} {'값':<20} {'줄':<5} {'열':<5}")
print("=" * 70)

tokens = list(tokenize.generate_tokens(io.StringIO(code2).readline))
for tok in tokens:
    tok_name = tokenize.tok_name[tok.type]
    line, col = tok.start
    value = tok.string[:18] + '...' if len(tok.string) > 20 else tok.string
    print(f"{tok_name:<15} {value!r:<20} {line:<5} {col:<5}")

print("\n주목할 점:")
print("- INDENT: 함수 본문의 들여쓰기가 시작됨을 표시")
print("- DEDENT: 들여쓰기가 종료됨을 표시 (return 문 이후)")
print("- f-string의 경우 FSTRING_START, FSTRING_MIDDLE, FSTRING_END로 분리됨")
=== 실습 2: 함수 정의 토큰화 ===

원본 코드:
def greet(name):
    print(f"Hello, {name}!")
    return True

======================================================================
타입              값                    줄     열    
======================================================================
NAME            'def'                1     0    
NAME            'greet'              1     4    
OP              '('                  1     9    
NAME            'name'               1     10   
OP              ')'                  1     14   
OP              ':'                  1     15   
NEWLINE         '\n'                 1     16   
INDENT          '    '               2     0    
NAME            'print'              2     4    
OP              '('                  2     9    
FSTRING_START   'f"'                 2     10   
FSTRING_MIDDLE  'Hello, '            2     12   
OP              '{'                  2     19   
NAME            'name'               2     20   
OP              '}'                  2     24   
FSTRING_MIDDLE  '!'                  2     25   
FSTRING_END     '"'                  2     26   
OP              ')'                  2     27   
NEWLINE         '\n'                 2     28   
NAME            'return'             3     4    
NAME            'True'               3     11   
NEWLINE         '\n'                 3     15   
DEDENT          ''                   4     0    
ENDMARKER       ''                   4     0    

주목할 점:
- INDENT: 함수 본문의 들여쓰기가 시작됨을 표시
- DEDENT: 들여쓰기가 종료됨을 표시 (return 문 이후)
- f-string의 경우 FSTRING_START, FSTRING_MIDDLE, FSTRING_END로 분리됨

실제로 실행시켜보면 “INDENT”“DEDENT” 등이 표기되는 것을 알 수 있다. FSTRING_START 등 신기한 토큰들도 많이보인다. Python 은 들여쓰기 수준이 증가하거나 감소할때 잘 알고 있듯이 INDENTDEDENT 가 아래 처럼 발생한다.

=== 중첩 함수의 INDENT/DEDENT ===
def outer():
    x = 1
    def inner():
        y = 2
        return y
    return x

============================================================
NAME: 'def'
NAME: 'outer'
OP: '('
OP: ')'
OP: ':'
INDENT → 레벨 1
  NAME: 'x'
  OP: '='
  NUMBER: '1'
  NAME: 'def'
  NAME: 'inner'
  OP: '('
  OP: ')'
  OP: ':'
  INDENT → 레벨 2
    NAME: 'y'
    OP: '='
    NUMBER: '2'
    NAME: 'return'
    NAME: 'y'
  DEDENT ← 레벨 2
  NAME: 'return'
  NAME: 'x'
DEDENT ← 레벨 1

List comprehension 토큰화

=== 연습 2: 리스트 컴프리헨션 토큰화 ===
코드: squares = [x**2 for x in range(10) if x % 2 == 0]

토큰 목록:
--------------------------------------------------
  NAME            'squares'
  OP              '='
  OP              '['
  NAME            'x'
  OP              '**'
  NUMBER          '2'
  NAME            'for'
  NAME            'x'
  NAME            'in'
  NAME            'range'
  OP              '('
  NUMBER          '10'
  OP              ')'
  NAME            'if'
  NAME            'x'
  OP              '%'
  NUMBER          '2'
  OP              '=='
  NUMBER          '0'
  OP              ']'

모든 코드가 토큰화 된다.

마치며

양질의 글은 아니지만 복리 효과를 믿으며 적어보는 글. 토큰화에 대한 개념을 알고 있으면 나중에 재밌는 것들을 해볼 수 있을 것 같다.

22 views

More from this blog

RDB 에서 큰 컬럼을 인덱스로 잡으면 안되는 이유

B-Tree 는 기본적으로 페이지 사이즈 와 저장할 수 있는 원소의 개수를 고정값으로 사용한다. 하지만 우리가 실제로 페이지에 저장하는 값은 가변적인 크기를 가지고 있기 때문에 필연적으로 물리적으로 저장해야할 개수가 다 차기도 전에 페이지가 넘치는 상황에 부딪히게 된다. 예를 들어 100KB 를 저장하는 페이지에 위와 같이 데이터를 저장한 상태이다. 여

Feb 26, 20262 min read49

Slotted Page

데이터베이스와 관련된 기술을 보다보면 어떻게 데이터를 관리하고 저장하지? 특히 단편화(Fragmentation) 이 일어나는 것을 어떻게 통제하고 관리할까? 혹은 정렬된 자료구조 내부에서 데이터의 순서를 보존하기 위해 어떠한 행위들을 할까? 궁금해집니다. 오늘은 조금 더 데이터베이스 내부에 쓰이는 자료구조를 들여다보며 연관된 행위를 공부해보려고 합니다. F

Feb 22, 20264 min read63
Slotted Page

MCP 를 통한 workflow 자동화

AI native 최근에 LinkedIn 이나 여러 소셜 플랫폼들의 글을 보면 AI native 회사 라는 워딩들이 많이 보입니다. IBM 의 정의에 따르면 AI native 를 아래와 같이 정의한다고 하는데요. “AI를 사고와 업무 방식에 끊임없이 내재화하는 상태” 그렇다면 팀원들이 계속해서 AI 를 사고와 업무 방식에 끊임 없이 내재화 하려면 어떻게 해야할까요? 개발자들은 이미 Claude code 나 Codex 등 여러 AI Tool...

Feb 14, 20263 min read100

파이썬 톺아보기 2화 - Ast 와 바이트코드

식(Expression) 과 문장(Statement) 프로그래밍을 공부하다보면 위 두 단어를 반드시 마주하게 된다. 가끔 헷갈려하는 경우가 많은데 오늘은 python 에서 기본 모듈인 ast 모듈을 공부하며 이를 알아보도록 하자. 식(Expression) 기본적으로 식(Expression) 이란 평가되면 값이 나오는 코드 조각을 뜻한다. 파이썬에서는 어떠한 부분들이 있을까? 노드 타입설명예시 BinOp이항 연산a + b, x * y...

Feb 6, 20267 min read30
D

dev_roach

41 posts

Introduction to Python Tokenization