모든 강의를 무료로 볼 수 있어요. 회원가입 없이도 학습 가능합니다.

11강 / 전체 32강

f-string과 문자열 포맷팅 완전 정복

9분 읽기 조회 3

파이썬의 모든 문자열 포맷팅 방법을 비교하고 f-string의 모든 기능을 마스터한다.

🎯 이 강의에서 배우는 것

파이썬에서 문자열에 변수 값을 넣는 방법은 시대에 따라 세 번 진화했습니다. % 연산자, str.format(), 그리고 f-string. 각각의 탄생 이유와 한계를 이해하고, f-string의 모든 형식 지정자를 마스터합니다. 올바른 포맷팅 방법 선택이 코드 가독성과 유지보수성을 크게 좌우합니다.

📜 포맷팅의 역사 — 왜 세 가지 방법이 있는가

name = "홍길동"
age = 30
pi = 3.14159

# 방법 1: % 연산자 (Python 2 시대, C printf 스타일)
msg1 = "이름: %s, 나이: %d, 원주율: %.2f" % (name, age, pi)
print(msg1)   # 이름: 홍길동, 나이: 30, 원주율: 3.14

# 방법 2: str.format() (Python 2.6+)
msg2 = "이름: {}, 나이: {}, 원주율: {:.2f}".format(name, age, pi)
print(msg2)   # 이름: 홍길동, 나이: 30, 원주율: 3.14

# 위치 인덱스와 이름 키워드
msg2b = "이름: {0}, 나이: {1}, 다시 이름: {0}".format(name, age)
msg2c = "이름: {name}, 나이: {age}".format(name=name, age=age)

# 방법 3: f-string (Python 3.6+, 권장)
msg3 = f"이름: {name}, 나이: {age}, 원주율: {pi:.2f}"
print(msg3)   # 이름: 홍길동, 나이: 30, 원주율: 3.14

% 포맷팅의 한계: 인자 순서 실수, %s/%d/%f 타입 지정자 암기 필요, 가독성 저하. str.format()이 이를 개선했지만 여전히 장황합니다. f-string은 파이썬 3.6에서 도입되어 가장 읽기 쉽고 가장 빠릅니다.

🚀 f-string 기본 문법과 표현식

f-string의 {} 안에는 어떤 파이썬 표현식도 들어갈 수 있습니다:

x = 10
y = 20

# 변수
print(f"{x}")               # 10

# 산술 표현식
print(f"{x + y}")           # 30
print(f"{x * y}")           # 200

# 함수 호출
words = ["hello", "world"]
print(f"{len(words)} 단어")  # 2 단어
print(f"{words[0].upper()}") # HELLO

# 메서드 호출
name = "홍길동"
print(f"{'안녕하세요 ' + name}님")  # 안녕하세요 홍길동님

# 조건 표현식 (삼항 연산자)
age = 17
print(f"{'성인' if age >= 18 else '미성년자'}")  # 미성년자

# 딕셔너리 접근
person = {"name": "홍길동", "age": 30}
print(f"{person['name']}님은 {person['age']}세입니다")

# 중첩 f-string
precision = 3
print(f"{pi:.{precision}f}")   # 3.142 (precision 변수로 소수점 자리 지정)

📐 형식 지정자 (Format Spec Mini-Language)

f-string의 콜론(:) 뒤에 형식 지정자를 붙입니다. 완전한 문법은 {값:[[채우기]정렬][부호][#][0][너비][그룹][.정밀도][타입]}입니다:

n = 42
pi = 3.14159265

# 너비와 정렬
print(f"{n:10}")      # "        42" (오른쪽 정렬, 기본)
print(f"{n:<10}")     # "42        " (왼쪽 정렬)
print(f"{n:^10}")     # "    42    " (가운데 정렬)
print(f"{n:0>10}")    # "0000000042" (0으로 채우기)
print(f"{n:*^10}")    # "****42****" (* 문자로 채우기)

# 소수점
print(f"{pi:.2f}")    # 3.14 (소수점 2자리)
print(f"{pi:.5f}")    # 3.14159 (소수점 5자리)
print(f"{pi:10.3f}")  # "     3.142" (너비 10, 소수점 3자리)

# 천 단위 구분자
big_num = 1234567890
print(f"{big_num:,}")     # 1,234,567,890
print(f"{big_num:_}")     # 1_234_567_890 (밑줄 구분자)

# 부호
print(f"{42:+}")     # +42
print(f"{-42:+}")    # -42
print(f"{42: }")     # " 42" (양수에 공백 — 음수와 정렬 맞추기)

# 진법
n = 255
print(f"{n:b}")     # 11111111 (2진수)
print(f"{n:o}")     # 377      (8진수)
print(f"{n:x}")     # ff       (16진수, 소문자)
print(f"{n:X}")     # FF       (16진수, 대문자)
print(f"{n:#x}")    # 0xff     (0x 접두사 포함)
print(f"{n:#010b}") # 0b11111111 (접두사+너비10+2진수)

# 과학적 표기
big = 1234567.89
print(f"{big:e}")     # 1.234568e+06
print(f"{big:.2e}")   # 1.23e+06
print(f"{big:g}")     # 1.23457e+06 (더 짧은 표현 자동 선택)

🐛 f-string 디버깅 모드 (Python 3.8+)

x = 42
lst = [1, 2, 3]
name = "파이썬"

# = 를 붙이면 변수명=값 형태로 출력
print(f"{x=}")       # x=42
print(f"{lst=}")     # lst=[1, 2, 3]
print(f"{name=}")    # name='파이썬'

# 형식 지정자와 함께 사용
print(f"{x=:.2f}")   # x=42.00

# 함수 호출 디버깅
import math
print(f"{math.sqrt(16)=}")   # math.sqrt(16)=4.0

🔄 변환 플래그 (!r, !s, !a)

class Product:
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return f"상품명: {self.name}"
    def __repr__(self):
        return f"Product({self.name!r})"

p = Product("파이썬 책")

print(f"{p}")       # 상품명: 파이썬 책  (__str__ 호출)
print(f"{p!s}")     # 상품명: 파이썬 책  (__str__ 강제)
print(f"{p!r}")     # Product('파이썬 책')  (__repr__ 강제)
print(f"{p!a}")     # Product('\ud30c\uc774\uc36c \ucc45')  (ASCII만 사용)

# 문자열에서 !r은 따옴표를 포함해서 출력
s = "hello
world"
print(f"{s}")       # hello (줄바꿈)
                    # world
print(f"{s!r}")     # 'hello\nworld'  (이스케이프 문자 그대로)

⚡ 성능 비교 — f-string이 가장 빠른 이유

import timeit

name = "홍길동"
age = 30

# 세 가지 방법의 성능 비교
t1 = timeit.timeit(
    "'이름: %s, 나이: %d' % (name, age)",
    globals={"name": name, "age": age},
    number=1_000_000
)

t2 = timeit.timeit(
    "'이름: {}, 나이: {}'.format(name, age)",
    globals={"name": name, "age": age},
    number=1_000_000
)

t3 = timeit.timeit(
    "f'이름: {name}, 나이: {age}'",
    globals={"name": name, "age": age},
    number=1_000_000
)

print(f"% 연산자:    {t1:.3f}초")
print(f"str.format: {t2:.3f}초")
print(f"f-string:   {t3:.3f}초")
# 일반적으로 f-string이 가장 빠름
# f-string은 컴파일 시점에 최적화된 바이트코드 생성

⚠️ 자주 하는 실수

  • f-string 안에 따옴표 충돌: f-string이 큰따옴표로 시작하면 내부 표현식에서 큰따옴표 사용 불가. 작은따옴표로 전환하거나, Python 3.12+에서는 같은 종류의 따옴표도 중첩 허용.
  • 복잡한 표현식을 f-string에 직접 작성: 가독성을 위해 복잡한 계산은 변수에 먼저 담고 f-string에서 변수를 참조하세요.
  • % 연산자에서 인자가 하나일 때 튜플 빠뜨림: "값: %s" % value에서 value가 튜플이면 오류 발생. "값: %s" % (value,)처럼 항상 튜플로 감싸세요.

📝 정리 및 다음 강의 예고

  • % 연산자 → str.format() → f-string 순으로 발전. 새 코드는 f-string을 사용하세요.
  • f-string의 형식 지정자: 정렬(<>^), 너비, 소수점(.nf), 구분자(,), 진법(b/o/x).
  • f"{x=}"는 디버깅에 매우 유용한 Python 3.8+ 기능입니다.
  • f-string이 세 가지 중 가장 빠르고 가장 읽기 쉽습니다.

다음 강의: 조건문(if/elif/else)을 배웁니다. 들여쓰기가 블록을 정의하는 파이썬 철학, 가드 클로즈 패턴, 그리고 Python 3.10의 구조적 패턴 매칭(match-case)까지 다룹니다.

관련 주제

  • f-string 문법
  • 포맷 지정자(정렬·소수점)
  • %연산자 포맷팅
  • str.format()
  • 디버깅 변수명=값 출력
  • !r !s 변환플래그
  • 개발·프로그래밍
  • 개발·프로그래밍 강의
  • 파이썬 기초 40강 — 처음 배우는 프로그래밍
  • 무료강의
  • 무료 온라인 강의
  • NUGUNA
  • 누구나

📚 시리즈 전체 공유

파이썬 기초 40강 — 처음 배우는 프로그래밍

이 강의가 속한 시리즈는 총 32강, 모두 무료입니다. 처음부터 배우려는 동료에게 시리즈 전체를 알려 주세요.

댓글

0/1000

불러오는 중...