Python 3.13에서 도입된 PyREPL의 구문 강조, 멀티라인 편집, 자동완성, 히스토리 관리 등 현대적 REPL 기능을 실전 예시와 함께 다룹니다.
Python의 대화형 인터프리터(REPL, Read-Eval-Print Loop)는 Python을 처음 접하는 개발자가 가장 먼저 만나는 도구입니다. 간단한 코드를 실행하고, 라이브러리를 탐색하며, 아이디어를 빠르게 검증하는 데 사용됩니다.
그러나 Python의 기본 REPL은 30년 넘게 거의 변하지 않았습니다. IPython, ptpython, bpython 같은 서드파티 도구들이 제공하는 구문 강조, 자동완성, 멀티라인 편집 같은 기능을 기본 REPL은 지원하지 않았습니다.
1. 구문 강조 없음 - 모든 텍스트가 같은 색상
2. 멀티라인 편집 제한 - 입력한 줄로 되돌아가기 어려움
3. 히스토리 관리 빈약 - 블록 단위 재실행 불편
4. 자동완성 기초적 - Tab 키의 기능이 제한적
5. 붙여넣기 문제 - 코드 블록을 붙여넣으면 들여쓰기 오류Python 3.13은 이 문제를 해결하기 위해 PyREPL이라는 완전히 새로운 대화형 인터프리터를 도입했습니다.
PyREPL을 실행하면 가장 먼저 눈에 들어오는 변화는 색상입니다. 키워드, 문자열, 숫자, 주석이 각각 다른 색상으로 표시됩니다.
>>> def greet(name: str) -> str:
... return "Hello, " + name
...
>>> greet("World")
'Hello, World'키워드(def, return)는 특정 색상으로, 문자열 리터럴은 다른 색상으로, 타입 힌트는 또 다른 색상으로 구분됩니다. 이 시각적 구분은 코드를 입력하는 도중에 문법 오류를 빠르게 인지하는 데 도움이 됩니다.
기존 REPL에서 여러 줄의 코드를 수정하려면, 전체를 다시 입력해야 했습니다. PyREPL에서는 화살표 키로 이전 줄로 이동하여 수정할 수 있습니다.
# 여러 줄의 함수를 입력한 후
>>> def calculate(x, y):
... result = x + y
... return result # 이 줄에서 * 로 변경하고 싶다면?
# 화살표 키로 이전 줄로 이동하여 수정 가능또한 Up 키를 누르면 이전에 입력한 코드 블록 전체가 하나의 단위로 불러와집니다. 기존 REPL에서는 줄 단위로 불러와서 멀티라인 블록을 재실행하기 어려웠지만, PyREPL에서는 한 번의 키 입력으로 전체 블록을 복원합니다.
PyREPL은 브라켓 페이스트(Bracketed Paste) 모드를 지원합니다. 이 기능은 클립보드에서 여러 줄의 코드를 붙여넣을 때, 터미널이 붙여넣기를 감지하여 한 번에 처리합니다.
기존 REPL에서는 코드를 붙여넣으면 각 줄이 개별적으로 실행되어 들여쓰기 오류가 발생할 수 있었습니다. PyREPL에서는 전체 텍스트가 하나의 입력으로 처리됩니다.
브라켓 페이스트는 대부분의 현대적 터미널 에뮬레이터에서 지원됩니다. macOS의 Terminal.app, iTerm2, Windows Terminal, 그리고 대부분의 Linux 터미널이 해당됩니다.
PyREPL의 자동완성은 Tab 키를 눌러 활성화합니다. 기존 REPL보다 더 정교한 자동완성을 제공합니다.
>>> import pathlib
>>> p = pathlib.Path(".")
>>> p. # Tab 키를 누르면 사용 가능한 메서드 목록 표시
absolute() chmod() cwd()
exists() expanduser() glob()
home() is_dir() is_file()
iterdir() mkdir() name
parent parts read_text()
...객체의 메서드, 속성, 모듈의 이름을 탐색할 때 특히 유용합니다.
PyREPL은 다양한 키보드 단축키를 지원합니다. readline 기반의 Emacs 스타일 단축키가 기본입니다.
이동:
Ctrl+A 줄의 시작으로
Ctrl+E 줄의 끝으로
Ctrl+B 한 글자 뒤로
Ctrl+F 한 글자 앞으로
Alt+B 한 단어 뒤로
Alt+F 한 단어 앞으로
편집:
Ctrl+D 커서 위치의 글자 삭제 (비어있으면 종료)
Ctrl+K 커서부터 줄 끝까지 삭제
Ctrl+U 커서부터 줄 시작까지 삭제
Ctrl+W 이전 단어 삭제
Ctrl+Y 마지막 삭제한 텍스트 붙여넣기
히스토리:
Up/Down 이전/다음 히스토리 항목
Ctrl+R 히스토리 역방향 검색
Ctrl+P 이전 히스토리 (Up과 동일)
Ctrl+N 다음 히스토리 (Down과 동일)
특수:
F1 pydoc 도움말 브라우저
F2 히스토리 브라우저
Tab 자동완성
Ctrl+L 화면 지우기F1을 누르면 pydoc 도움말 브라우저가 바로 열립니다. 별도로 help() 함수를 호출하지 않아도 됩니다.
F2를 누르면 이전 세션을 포함한 전체 REPL 히스토리를 탐색할 수 있습니다. 세션 간에 히스토리가 유지되므로, 어제 실행한 코드를 오늘 다시 찾을 수 있습니다.
기존 REPL에서 세션을 종료하려면 exit() 또는 quit()를 호출해야 했습니다. 괄호 없이 exit만 입력하면 "Use exit() or Ctrl-D to exit"라는 메시지가 표시되었습니다.
PyREPL에서는 괄호 없이 exit 또는 quit만 입력해도 세션이 종료됩니다.
# 기존 REPL
>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit
# PyREPL (3.13+)
>>> exit
# 바로 종료PyREPL은 Python의 내장 디버거인 pdb와 자연스럽게 통합됩니다. 디버거 세션에서도 구문 강조와 멀티라인 편집이 동작합니다.
import pdb
def buggy_function(data: list[int]) -> int:
total = 0
for item in data:
pdb.set_trace() # 브레이크포인트
total += item
return total
buggy_function([1, 2, 3])디버거에 진입하면 PyREPL의 기능(구문 강조, 자동완성, 히스토리)을 활용하여 변수를 검사하고, 표현식을 평가할 수 있습니다.
PyREPL은 기존의 PYTHONSTARTUP 환경 변수를 그대로 지원합니다. 이 파일에 자주 사용하는 임포트나 유틸리티 함수를 정의해두면, 매번 REPL을 실행할 때마다 자동으로 로드됩니다.
# PYTHONSTARTUP 파일 예시
import json
import os
import sys
from pathlib import Path
from datetime import datetime, timedelta
from pprint import pprint
# 자주 사용하는 유틸리티
def pp(obj):
"""Pretty print with JSON formatting for dicts"""
if isinstance(obj, (dict, list)):
print(json.dumps(obj, indent=2, ensure_ascii=False, default=str))
else:
pprint(obj)
def ls(path="."):
"""Quick directory listing"""
for item in sorted(Path(path).iterdir()):
prefix = "d " if item.is_dir() else "f "
print(prefix + item.name)
print("Custom environment loaded")# .bashrc 또는 .zshrc에 추가
export PYTHONSTARTUP="$HOME/.pythonrc.py"PyREPL이 특정 환경에서 문제를 일으키거나, 기존 REPL의 동작이 필요한 경우 환경 변수로 전환할 수 있습니다.
PYTHON_BASIC_REPL=1 python3.13일부 자동화 스크립트나 CI/CD 파이프라인에서 REPL의 출력을 파싱하는 경우, PyREPL의 색상 코드나 변경된 출력 형식이 문제를 일으킬 수 있습니다. 이런 환경에서는 PYTHON_BASIC_REPL=1을 설정하는 것이 안전합니다.
PyREPL이 서드파티 REPL 도구를 완전히 대체하는 것은 아닙니다. 각 도구의 특성을 비교합니다.
| 기능 | PyREPL | IPython | ptpython |
|---|---|---|---|
| 구문 강조 | 지원 | 지원 | 지원 |
| 멀티라인 편집 | 지원 | 지원 | 지원 |
| 자동완성 | 기본 | 고급 (Jedi) | 고급 |
| 매직 명령어 | 없음 | 지원 (%timeit 등) | 일부 |
| 노트북 통합 | 없음 | Jupyter | 없음 |
| 외부 의존성 | 없음 | 필요 | 필요 |
| 시작 속도 | 빠름 | 보통 | 보통 |
| 내장 여부 | 기본 | 별도 설치 | 별도 설치 |
PyREPL의 핵심 가치는 "별도 설치 없이" 현대적인 REPL 경험을 제공한다는 것입니다. 고급 기능이 필요한 경우 IPython이 여전히 강력한 선택이지만, 빠른 탐색과 디버깅에는 PyREPL만으로 충분합니다.
>>> import pathlib
>>> p = pathlib.Path("/tmp")
>>> # Tab으로 메서드 목록 확인 후 바로 실행
>>> list(p.glob("*.txt"))
[PosixPath('/tmp/notes.txt'), PosixPath('/tmp/log.txt')]
>>> # F1으로 glob 도움말 확인>>> data = [
... {"name": "Alice", "score": 95},
... {"name": "Bob", "score": 87},
... {"name": "Charlie", "score": 92},
... ]
>>> # 멀티라인 블록을 Up 키로 재호출하여 수정 가능
>>> sorted(data, key=lambda x: x["score"], reverse=True)
[{'name': 'Alice', 'score': 95}, {'name': 'Charlie', 'score': 92}, {'name': 'Bob', 'score': 87}]>>> import json
>>> # 오류가 의심되는 JSON 파싱 테스트
>>> raw = '{"key": "value", "nested": {"a": 1}}'
>>> parsed = json.loads(raw)
>>> parsed["nested"]["a"]
1
>>> # 구문 강조 덕분에 JSON 문자열의 구조가 한눈에 보임PyREPL은 Python 3.13에서 도입된 현대적 대화형 인터프리터입니다.
6장에서는 Python 3.12의 성능 향상 메커니즘을 다룹니다. 특수화 적응 인터프리터(Specializing Adaptive Interpreter), 컴프리헨션 인라인화, asyncio 최적화 등 CPython이 어떻게 더 빨라졌는지 분석합니다.
이 글이 도움이 되셨나요?
Python 3.12의 성능 향상 원리를 분석합니다. 특수화 적응 인터프리터, 컴프리헨션 인라인화, immortal objects, asyncio 최적화 등 CPython 내부를 다룹니다.
Python 3.12의 PEP 701 유연한 f-string 파싱과 3.12~3.13의 에러 메시지 개선을 다룹니다. 컬러 트레이스백, 제안 기반 에러 등 디버깅 경험 향상을 살펴봅니다.
Python 3.13의 free-threaded 모드를 심층 분석합니다. GIL의 역사와 문제점, PEP 703의 설계, free-threaded 빌드의 설치와 실전 멀티스레드 성능을 다룹니다.