표준 입출력의 개념을 이해하고 print()·input()의 모든 매개변수를 마스터한다.
🎯 이 강의에서 배우는 것
드디어 실제 파이썬 코드를 작성합니다. 대부분의 강좌는 print("Hello, World!")를 바로 실행하고 넘어가지만, 여기서는 이 한 줄 뒤에 숨겨진 원리를 파헤칩니다. 표준 스트림이 무엇인지, print()의 모든 매개변수가 왜 존재하는지, input()이 왜 항상 문자열을 반환하는지 완전히 이해합니다.
🌊 표준 스트림 — 모든 것은 파일이다
유닉스 철학의 핵심 원칙 중 하나는 "모든 것은 파일이다(Everything is a file)"입니다. 파일뿐만 아니라 키보드, 모니터, 네트워크 소켓까지 파일처럼 읽고 쓸 수 있습니다. 이 원칙에서 표준 스트림(standard streams)이 탄생했습니다.
프로그램이 시작될 때 운영체제는 자동으로 세 가지 스트림을 연결합니다:
| 스트림 | 파이썬에서 | 기본 연결 | 역할 |
|---|---|---|---|
| stdin (표준 입력, fd=0) | sys.stdin | 키보드 | 프로그램이 데이터를 읽는 곳 |
| stdout (표준 출력, fd=1) | sys.stdout | 터미널 | 프로그램이 결과를 내보내는 곳 |
| stderr (표준 오류, fd=2) | sys.stderr | 터미널 | 오류 메시지 전용 출력 |
import sys
# stdout과 stderr를 구분해서 출력하는 이유
print("정상 결과입니다", file=sys.stdout) # 기본값
print("오류가 발생했습니다!", file=sys.stderr)
# 터미널에서 두 스트림을 분리할 수 있음:
# python script.py > output.txt 2> error.txt
# stdout → output.txt, stderr → error.txt로 분리
stdout과 stderr를 분리하는 것은 실무에서 중요합니다. 로그 분석 도구나 배포 파이프라인에서 오류만 걸러내거나, 정상 출력과 오류를 다른 파일에 저장할 수 있습니다.
🖨️ print() 시그니처 완전 분석
print()의 완전한 시그니처는 다음과 같습니다:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)
각 매개변수를 하나씩 실험해봅시다:
# 1. *objects: 여러 값을 한 번에 출력
print(1, 2, 3) # 1 2 3
print("이름:", "홍길동") # 이름: 홍길동
# 2. sep: 구분자 (기본값: 공백)
print(1, 2, 3, sep=', ') # 1, 2, 3
print(1, 2, 3, sep=' | ') # 1 | 2 | 3
print("2024", "01", "15", sep='-') # 2024-01-15 (날짜 형식 활용)
# 3. end: 끝 문자 (기본값: 줄바꿈 \n)
print("로딩 중", end="") # 줄바꿈 없이 출력
print(".", end="")
print(".", end="")
print(".") # 전체: 로딩 중...
# 4. file: 출력 대상 (기본값: sys.stdout)
import sys
print("오류 발생!", file=sys.stderr)
# 파일에 직접 출력
with open("log.txt", "w", encoding="utf-8") as f:
print("이것은 파일에 기록됩니다", file=f)
print("두 번째 줄", file=f)
# 5. flush: 버퍼를 즉시 비움 (기본값: False)
import time
for i in range(5):
print(f"\r진행 중: {i+1}/5", end="", flush=True) # 같은 줄 덮어쓰기
time.sleep(0.5)
print() # 마지막 줄바꿈
버퍼링(buffering)이 무엇인지 이해하는 것이 중요합니다. 파이썬은 출력 성능을 위해 작은 출력들을 모았다가 한 번에 전송합니다(버퍼링). flush=True는 이 버퍼를 즉시 비워 화면에 즉각 표시되게 합니다. 진행률 바를 구현하거나 실시간 로그가 필요할 때 필요합니다.
📝 문자열 리터럴의 모든 종류
파이썬에서 문자열을 표현하는 방법은 여러 가지입니다:
# 1. 기본 따옴표 (작은따옴표 vs 큰따옴표)
s1 = '작은따옴표 문자열'
s2 = "큰따옴표 문자열"
# 두 종류가 있는 이유: 문자열 안에 따옴표를 쓸 때 편리
s3 = "이것은 '작은따옴표'가 포함된 문자열"
s4 = '이것은 "큰따옴표"가 포함된 문자열'
# 2. 삼중 따옴표 (여러 줄 문자열)
multi = """첫 번째 줄
두 번째 줄
세 번째 줄"""
print(multi)
# 3. 이스케이프 시퀀스
print("탭:\t들여쓰기") # 탭 문자
print("줄바꿈:\n다음 줄") # 줄바꿈
print("역슬래시: \\") # 역슬래시 자체
print("따옴표: \"인용\"") # 큰따옴표
# 4. raw 문자열 접두사 r (역슬래시를 그대로 처리)
path = r"C:\Users\홍길동\Documents\file.txt"
print(path) # C:\Users\홍길동\Documents\file.txt
# r 없이: \U가 유니코드 이스케이프로 해석될 수 있음!
# 5. bytes 문자열 접두사 b
b1 = b"hello" # bytes 타입
print(type(b1)) # <class 'bytes'>
print(b1[0]) # 104 (h의 ASCII 값)
# b"한글"은 불가 — bytes는 ASCII 범위만 리터럴 가능
실수 포인트: Windows 파일 경로에서 raw 문자열을 쓰지 않으면 \n이 줄바꿈으로, \t가 탭으로 해석됩니다. r"C:\new_folder\task.txt"처럼 r 접두사를 붙이거나, 슬래시를 두 번 쓰거나, 포워드 슬래시("C:/new_folder")를 사용하세요.
⌨️ input() 완전 분석
input()은 사용자로부터 한 줄의 텍스트를 읽습니다. 매우 단순해 보이지만, 중요한 특성이 있습니다:
# input()은 항상 str을 반환한다
name = input("이름을 입력하세요: ")
print(type(name)) # <class 'str'> — 항상!
# 숫자를 입력해도 문자열로 반환됨
age_str = input("나이를 입력하세요: ")
print(type(age_str)) # <class 'str'>
# 숫자로 사용하려면 명시적 변환 필요
age = int(age_str) # 문자열 → 정수
print(type(age)) # <class 'int'>
# 더 안전한 방법: 변환 실패 처리
age_input = input("나이: ")
try:
age = int(age_input)
print(f"입력한 나이: {age}")
except ValueError:
print(f"'{age_input}'은 유효한 숫자가 아닙니다")
왜 input()은 항상 str을 반환할까요? Python 2에서 input()은 입력을 자동으로 eval()했습니다. 사용자가 악의적인 코드를 입력하면 즉시 실행되는 보안 취약점이었습니다. Python 3는 이것을 단순히 문자열 반환으로 수정했고, 타입 변환은 프로그래머가 명시적으로 하도록 변경했습니다.
# EOF(End of File) 처리
# Ctrl+D (macOS/Linux) 또는 Ctrl+Z Enter (Windows)를 입력하면 EOFError 발생
try:
text = input("입력: ")
except EOFError:
print("입력 스트림이 종료됐습니다")
💡 첫 완성 프로그램 — 나이 계산기
지금까지 배운 것을 종합해 첫 완성 프로그램을 작성합니다:
# age_calculator.py
from datetime import datetime
current_year = datetime.now().year # 예: 2026
# 이름 입력 받기
name = input("이름을 입력하세요: ")
# 나이 입력 — 유효하지 않은 입력은 다시 요청
while True:
age_input = input("나이를 입력하세요: ")
try:
age = int(age_input)
if age <= 0 or age > 150:
print("유효한 나이를 입력해주세요 (1~150)")
continue
break
except ValueError:
print(f"'{age_input}'은 숫자가 아닙니다. 다시 입력해주세요.")
# 계산
birth_year = current_year - age
is_adult = age >= 20 # 한국 기준 만 20세
# 결과 출력
print()
print(f"안녕하세요, {name}님!")
print(f"태어난 연도: {birth_year}년 (추정)")
print(f"현재 상태: {'성인' if is_adult else '미성년자'}")
if age == 20:
print("올해 성인이 되셨군요! 축하합니다!")
elif age < 10:
print("파이썬을 이렇게 일찍 배우다니 대단해요!")
elif age >= 60:
print("평생 학습의 자세가 멋집니다!")
이 프로그램에서 주목할 점: while True와 break로 유효한 입력이 들어올 때까지 반복하고, try/except로 숫자가 아닌 입력을 안전하게 처리합니다. 각각 13강(루프)과 38강(예외 처리)에서 깊이 다룹니다.
⚠️ 자주 하는 실수
print()에 괄호를 빠뜨림: Python 2 습관에서 오는 실수. Python 3에서print "hello"는SyntaxError입니다.input()결과를 바로 숫자 연산에 사용:input()은 항상str을 반환합니다.int()또는float()로 변환 후 연산하세요.- Windows 경로에서 이스케이프 오류:
"C:\new"에서\n이 줄바꿈으로 해석됩니다.r"C:\new"또는"C:\\new"를 사용하세요. - stderr 무시: 디버깅 메시지와 오류 메시지는
file=sys.stderr로 출력하세요. stdout과 섞이면 로그 파싱이 어려워집니다.
📝 정리 및 다음 강의 예고
- 표준 스트림(stdin/stdout/stderr)은 프로그램과 환경 사이의 데이터 파이프입니다.
print(*objects, sep, end, file, flush)— 5개 매개변수 모두 실용적인 용도가 있습니다.- 문자열 리터럴에는 기본·삼중 따옴표·raw(r)·bytes(b) 종류가 있습니다.
input()은 항상str을 반환합니다. 타입 변환은 명시적으로 해야 합니다.
다음 강의: 변수란 무엇인가? C 언어의 "박스 모델"과 파이썬의 "이름표 모델"을 비교해 참조, 객체, 메모리 관리(참조 카운팅, 가비지 컬렉션)를 깊이 이해합니다.
관련 주제
- 표준 입출력(stdin·stdout·stderr)
- print() 매개변수(sep·end·file)
- 이스케이프 시퀀스
- raw 문자열
- input() 반환형
- EOFError
- 개발·프로그래밍
- 개발·프로그래밍 강의
- 파이썬 기초 40강 — 처음 배우는 프로그래밍
- 무료강의
- 무료 온라인 강의
- NUGUNA
- 누구나
