Skip to main content

문자열 (String)

학습 목표

  • 문자열의 불변(Immutable) 특성을 이해한다
  • f-string과 다양한 문자열 포매팅 방법을 사용할 수 있다
  • 인덱싱과 슬라이싱으로 문자열의 일부를 추출할 수 있다
  • 주요 문자열 메서드를 활용할 수 있다

왜 중요한가

문자열은 프로그래밍에서 가장 빈번하게 다루는 데이터 타입입니다. 로그 메시지, 파일 경로, API 응답, 사용자 입력 등 거의 모든 데이터가 문자열 형태로 처리됩니다. ML/DL에서도 텍스트 전처리, 토큰화, 프롬프트 구성 등에 문자열 처리 능력이 필수적입니다.

문자열 생성

# 작은따옴표와 큰따옴표 (동일)
single = '안녕하세요'
double = "안녕하세요"

# 따옴표 포함
quote1 = "Python's best feature"
quote2 = 'He said "Hello"'
quote3 = "It's a \"good\" day"  # 이스케이프

# 여러 줄 문자열
multiline = """첫째 줄
둘째 줄
셋째 줄"""

# 문자열 연결
full_name = "김" + "철수"
separator = "-" * 40    # "----------------------------------------"

인덱싱과 슬라이싱

인덱싱

text = "Python"

# 양수 인덱스 (0부터 시작)
print(text[0])     # 'P'
print(text[1])     # 'y'
print(text[5])     # 'n'

# 음수 인덱스 (뒤에서부터)
print(text[-1])    # 'n'
print(text[-2])    # 'o'
print(text[-6])    # 'P'

# 인덱스 시각화
# 문자:   P    y    t    h    o    n
# 양수:   0    1    2    3    4    5
# 음수:  -6   -5   -4   -3   -2   -1

슬라이싱

text = "Hello, Python!"

# 기본 슬라이싱: [시작:끝] (끝은 미포함)
print(text[0:5])       # "Hello"
print(text[7:13])      # "Python"

# 시작/끝 생략
print(text[:5])        # "Hello" (처음부터)
print(text[7:])        # "Python!" (끝까지)
print(text[:])         # "Hello, Python!" (전체 복사)

# 스텝(Step)
print(text[::2])       # "Hlo yhn" (2칸씩)
print(text[::-1])      # "!nohtyP ,olleH" (역순)

# 실용적 활용
filename = "data_2024.csv"
name = filename[:-4]    # "data_2024" (확장자 제거)
ext = filename[-3:]     # "csv" (확장자 추출)

문자열 포매팅

f-string (권장)

Python 3.6부터 지원하며, 가장 직관적인 포매팅 방법입니다.
name = "김철수"
age = 25
score = 95.678

# 기본 삽입
print(f"이름: {name}, 나이: {age}")

# 표현식
print(f"내년 나이: {age + 1}")
print(f"이름 길이: {len(name)}")

# 포맷 지정
print(f"점수: {score:.1f}")        # "점수: 95.7" (소수점 1자리)
print(f"비율: {score:.0%}")        # 정수를 퍼센트로 표시
print(f"번호: {age:05d}")          # "번호: 00025" (0 채우기)
print(f"이름: {name:>10}")         # "이름:      김철수" (우측 정렬)
print(f"이름: {name:<10}")         # "이름: 김철수     " (좌측 정렬)
print(f"이름: {name:^10}")         # "이름:    김철수   " (가운데 정렬)

# 중첩 표현식 (Python 3.12+)
print(f"결과: {f'{score:.2f}점'}")

format() 메서드

# 위치 기반
print("이름: {}, 나이: {}".format("김철수", 25))

# 인덱스 기반
print("{0}{1}살, {0}은 학생".format("김철수", 25))

# 이름 기반
print("이름: {name}, 나이: {age}".format(name="김철수", age=25))

% 포매팅 (레거시)

# 오래된 방식 (기존 코드에서 볼 수 있음)
print("이름: %s, 나이: %d" % ("김철수", 25))
print("점수: %.2f" % 95.678)

주요 문자열 메서드

검색과 판별

text = "Hello, Python World!"

# 검색
print(text.find("Python"))       # 7 (위치 반환, 없으면 -1)
print(text.index("Python"))      # 7 (위치 반환, 없으면 ValueError)
print(text.count("l"))           # 3 (등장 횟수)
print("Python" in text)          # True (포함 여부)

# 시작/끝 판별
print(text.startswith("Hello"))  # True
print(text.endswith("!"))        # True

# 타입 판별
print("12345".isdigit())         # True (숫자만)
print("hello".isalpha())        # True (문자만)
print("hello123".isalnum())     # True (문자+숫자)
print("  ".isspace())           # True (공백만)
print("Hello".isupper())        # False
print("Hello".islower())        # False

변환

text = "  Hello, World!  "

# 대소문자 변환
print("hello".upper())          # "HELLO"
print("HELLO".lower())          # "hello"
print("hello world".title())    # "Hello World"
print("hello world".capitalize()) # "Hello world"
print("Hello".swapcase())       # "hELLO"

# 공백 제거
print(text.strip())             # "Hello, World!"
print(text.lstrip())            # "Hello, World!  "
print(text.rstrip())            # "  Hello, World!"

# 교체
print("Hello".replace("l", "r"))  # "Herro"
print("a-b-c".replace("-", "/"))  # "a/b/c"

분할과 결합

# 분할 (split)
csv_line = "김철수,25,서울"
parts = csv_line.split(",")
print(parts)                     # ['김철수', '25', '서울']

sentence = "Python is awesome"
words = sentence.split()        # 공백 기준 분할
print(words)                    # ['Python', 'is', 'awesome']

# 줄 단위 분할
text = "첫째 줄\n둘째 줄\n셋째 줄"
lines = text.splitlines()
print(lines)                    # ['첫째 줄', '둘째 줄', '셋째 줄']

# 결합 (join) - split의 반대
print(",".join(["a", "b", "c"]))  # "a,b,c"
print(" ".join(words))             # "Python is awesome"
print("\n".join(lines))            # 줄바꿈으로 결합

정렬과 채우기

# 정렬
print("hello".ljust(10))        # "hello     "
print("hello".rjust(10))        # "     hello"
print("hello".center(10))       # "  hello   "
print("hello".center(10, "-"))  # "--hello---"

# 0 채우기
print("42".zfill(5))            # "00042"
print("-42".zfill(5))           # "-0042"

AI/ML에서의 활용

# 텍스트 전처리 파이프라인
def preprocess_text(text):
    """텍스트 전처리 함수"""
    text = text.lower()                    # 소문자 변환
    text = text.strip()                    # 공백 제거
    text = text.replace("\n", " ")         # 줄바꿈 -> 공백
    text = " ".join(text.split())          # 연속 공백 제거
    return text

raw = "  Hello,   World!\n  Python  "
clean = preprocess_text(raw)
print(clean)  # "hello, world! python"

# 모델 경로 구성
model_name = "bert-base"
version = "v2"
path = f"models/{model_name}/{version}/checkpoint.pt"
# "models/bert-base/v2/checkpoint.pt"

# 프롬프트 템플릿
def build_prompt(question, context):
    return f"""다음 컨텍스트를 바탕으로 질문에 답하세요.

컨텍스트: {context}

질문: {question}

답변:"""
불변성 덕분에 문자열을 딕셔너리의 키로 사용할 수 있고, 해시 값을 캐싱하여 성능을 높일 수 있습니다. 또한 여러 변수가 같은 문자열 객체를 안전하게 공유할 수 있습니다.
Python 3.6 이상이라면 f-string을 권장합니다. 더 읽기 쉽고, 성능도 format()보다 빠릅니다. format()은 포맷 문자열을 변수로 전달해야 할 때만 사용합니다.
네트워크 통신이나 파일 I/O에서 바이트(bytes)와 문자열 간 변환이 필요할 때 사용합니다. "한글".encode("utf-8")은 바이트로, b.decode("utf-8")은 문자열로 변환합니다.

체크리스트

  • 인덱싱과 슬라이싱으로 문자열의 일부를 추출할 수 있다
  • f-string으로 다양한 포맷의 문자열을 생성할 수 있다
  • split(), join(), replace() 등 주요 메서드를 활용할 수 있다
  • 문자열의 불변 특성을 이해하고 있다

다음 문서