유닉스(Unix) 계열 시스템에서 터미널의 동작 방식을 직접 제어하고 싶다면, 파이썬(Python)의 tty 모듈을 활용할 수 있습니다. 이 모듈을 사용하면 터미널을 raw 모드와 cbreak 모드라는 두 가지 모드 중 하나로 설정할 수 있으며, 키보드 입력을 Enter 키 없이 즉시 받아 처리하는 프로그램을 만들 때 특히 유용합니다.
tty 모듈 임포트하기
tty 모듈은 파이썬 표준 라이브러리에 포함되어 있어 별도 설치 없이 바로 사용할 수 있습니다. 다음과 같이 임포트합니다.
import tty
tty 모듈에서 자주 사용되는 핵심 함수는 아래 두 가지입니다.
tty.setraw(fd, when = termios.TCSAFLUSH)
이 함수는 터미널을 raw 모드로 전환합니다. raw 모드에서는 커서가 새 줄로 이동하긴 하지만 캐리지 리턴(carriage return) 동작은 수행되지 않습니다. 또한 입력을 시스템에 전달하기 위해 Enter(Return) 키를 누를 필요가 없고, 키를 입력하는 순간 자동으로 전송됩니다. 이러한 특성 덕분에 한 글자 단위로 키 입력을 실시간으로 감지해야 하는 프로그램에 적합합니다.
tty.setcbreak(fd, when = termios.TCSAFLUSH)
이 함수는 터미널을 cbreak 모드로 전환합니다. cbreak 모드 역시 커서가 새 줄로 이동하고, Enter 키 없이 입력이 즉시 시스템으로 전달된다는 점은 raw 모드와 동일합니다. 다만 Ctrl+C와 같은 인터럽트 시그널 처리가 운영체제의 기본 동작대로 유지된다는 점에서 raw 모드와 차이가 있습니다.
예제 코드
다음 예제는 터미널을 raw 모드로 전환한 뒤 5개의 문자를 하나씩 읽어 출력하고, 작업이 끝나면 원래의 터미널 설정을 복원하는 코드입니다.
import sys
import tty
import termios
file_desc = sys.stdin.fileno()
old_setting = termios.tcgetattr(file_desc)
tty.setraw(sys.stdin)
for i in range(5):
char = sys.stdin.read(1)
print("Char: " + str(char))
termios.tcsetattr(file_desc, termios.TCSADRAIN, old_setting)
코드 흐름 살펴보기
sys.stdin.fileno()로 표준 입력의 파일 디스크립터를 가져오고, termios.tcgetattr()로 현재 터미널 설정을 미리 저장해 둡니다. 이후 tty.setraw()로 raw 모드를 활성화한 상태에서 문자를 읽고, 프로그램 종료 전 termios.tcsetattr()을 호출해 저장해 둔 설정을 복원합니다. 이 복원 과정을 생략하면 프로그램 종료 후 터미널이 비정상적으로 동작할 수 있으므로 반드시 함께 사용하는 것이 좋습니다.
실행 결과
$ python3 example.py
Char: K
Char: E
Char: 5
Char: 2
Char: @
실행 결과를 보면 각 문자가 점점 더 오른쪽으로 들여쓰기 되어 출력되는 것을 확인할 수 있습니다. 이는 raw 모드에서 개행 문자(\n)가 캐리지 리턴 없이 줄만 바꾸기 때문에, 커서가 이전 출력이 끝난 열 위치에 그대로 머물러 있기 때문입니다.