Devin.KR

문자열과 숫자 구분하기

55분 안팎

학습 목표

변수와 정수·문자열의 역할을 설명합니다.

개념

왜 입력과 계산을 분리하는가

지난 모듈에서는 data/sample.txt의 제목을 화면에 출력했습니다. 이제 제목과 읽은 쪽수를 함께 받습니다. 화면에 12가 보이더라도 프로그램 안에서 문자열인지 정수인지에 따라 다음 계산이 달라집니다. 신입에게 입력 처리 코드를 맡길 때 저는 출력 화면보다 입력 직후의 자료형을 먼저 확인하게 합니다. 같은 표시가 같은 의미를 보장하지 않기 때문입니다. 이번 목표는 제목은 문자열로 유지하고 쪽수는 정수로 바꾼 뒤 정해진 기록 한 줄을 만드는 것입니다. 파일 저장과 여러 기록 처리는 뒤 모듈에서 확장합니다.

변수는 값에 붙이는 이름

title = "달빛 도서관"은 문자열 값에 title이라는 이름을 연결합니다. pages = 12는 정수 값에 pages라는 이름을 연결합니다. 등호 하나는 대입이며 두 값이 같은지 묻는 비교가 아닙니다. 오른쪽 값을 먼저 구한 뒤 왼쪽 이름에 연결합니다. pages = pages + 1은 현재 쪽수에 1을 더한 결과를 다시 pages에 연결합니다. 이를 수학의 등식으로 해석하면 이해하기 어렵습니다. 코드에서는 실행 순서에 따라 이름이 가리키는 값이 바뀝니다. raw_pages처럼 원문임을 드러내는 이름과 pages처럼 변환된 이름을 나누면 조사할 지점이 명확해집니다.

문자열·정수·불린을 구분한다

문자열 str은 제목이나 입력된 글자를 나타냅니다. 정수 int는 쪽수처럼 소수 부분이 없는 수를 나타냅니다. bool의 True와 False는 조건 판단 결과입니다. 따옴표 안의 "12"는 str이고 따옴표 없는 12는 int입니다. type(raw_pages).__name__으로 str이라는 이름을 확인할 수 있습니다. 불린은 True처럼 첫 글자를 대문자로 쓰며 "True"라는 문자열과 구별합니다. 실수 float도 있지만 이 프로젝트의 쪽수 계약에서는 사용하지 않습니다. 2.5쪽을 받지 않기로 했다면 계산 편의 때문에 실수로 읽고 버리는 것이 아니라 그 입력을 거부할 근거를 마련해야 합니다.

표준 입력은 먼저 문자열이다

브라우저 실습에서는 첫 줄에 제목, 둘째 줄에 쪽수를 넣습니다. input()은 한 줄을 읽어 줄 끝의 개행을 제거한 문자열을 반환합니다. 제목 안의 공백이나 앞뒤 공백을 자동으로 모두 없애지는 않습니다. input("제목: ")처럼 안내 문구를 붙이면 그 문구도 표준 출력에 들어가 채점 결과에 섞입니다. 이번 실습은 안내 없이 input()으로 두 줄을 읽고 결과 한 줄만 출력합니다. 따옴표는 소스에서 문자열을 적는 표시이므로 입력창에는 달빛 도서관만 적습니다. 제목 전체를 split()으로 나누면 제목의 띄어쓰기를 입력 구분자로 오해하게 됩니다.

변환 지점을 한 곳에 둔다

raw_pages = input() 다음 pages = int(raw_pages)로 정수를 만듭니다. 그러면 pages + 1은 숫자 덧셈입니다. 반대로 raw_pages + "1"은 두 문자열을 이어 붙이는 작업입니다. 예를 들어 원문이 12이면 계산 결과와 이어 붙인 결과는 다릅니다. 정수와 문자열을 +로 직접 섞으면 TypeError가 발생할 수 있습니다. 이때 무작정 str()을 붙여 오류만 없애지 않습니다. 숫자 계산이 목적이면 입력을 int로 바꾸고, 화면 표시가 목적이면 f-string으로 조합합니다. 변환 위치를 입력 직후에 모아 두면 뒤의 계산에서 같은 값을 반복 변환하지 않아도 됩니다.

출력 형식도 입력 계약의 일부

기록 출력은 OK|제목|쪽수처럼 정합니다. f"OK|{title}|{pages}"에서 중괄호 안 표현식을 평가해 문자열에 넣습니다. 정수도 표시 과정에서 문자열로 나타나므로 쪽수 0은 0으로 출력합니다. 출력 끝의 개행은 print가 붙입니다. 쪽수 앞의 0001은 정수 변환 후 1로 표시됩니다. 이는 숫자의 표현을 통일한 것이며 원래 입력 철자를 보존한 것은 아닙니다. 도서 ID처럼 앞의 0 자체가 중요한 값은 정수로 바꾸면 안 됩니다. 이번 계약에서 쪽수는 수량이고 제목은 텍스트라는 선택을 먼저 설명한 뒤 변환을 적용합니다.

오류를 자료형과 값으로 나눈다

TypeError는 하려는 연산에 값의 자료형이 맞지 않는 상황을 알려 줍니다. ValueError: invalid literal for int()는 int로 바꾸려던 문자열 내용이 허용되지 않는 경우의 대표 메시지입니다. 예를 들어 열둘이나 1.5를 int에 직접 전달하면 이 변환을 할 수 없습니다. traceback의 마지막 줄에서 오류 종류를 찾고 바로 위의 소스 위치에서 어떤 값이 들어갔는지 확인합니다. 이번 따라하기는 오류 종류만 출력하도록 제공된 try/except 예제를 사용합니다. 예외 문법 전체는 오류와 테스트 모듈에서 다루며 여기서는 정상 입력 범위와 변환 실패 범위를 구분합니다.

자료형을 바꾸면 뜻도 확인한다

int("0")의 결과는 0이며 읽지 않은 기록을 표현할 수 있습니다. bool("0")은 문자열이 비어 있지 않아서 True입니다. 따라서 bool(raw_pages)을 쪽수 유효성 검사로 쓰면 0인지 양수인지 판단하지 못합니다. 문자열의 참·거짓과 정수의 범위는 다른 질문입니다. 마찬가지로 "10"과 "9"를 직접 비교하면 수량 크기 비교가 아니라 문자열 순서 비교가 됩니다. 출력이 그럴듯해 보여도 자료형이 틀리면 판단이 달라질 수 있습니다. 검사할 때는 입력값, 자료형, 기대 결과를 나란히 적어 오류 없이 틀린 경우도 확인합니다.

실습을 끝내는 순서

브라우저 starter는 제목과 쪽수 원문을 읽지만 쪽수에 1을 덧붙이고 있습니다. TODO를 찾아 변환과 출력 줄을 고칩니다. 이 레슨에서는 쪽수 입력이 0 이상의 ASCII 숫자로 주어진다고 가정합니다. 빈 제목 거부와 음수 거부는 다음 레슨에서 연결합니다. 한글 제목, 쪽수 0, 쪽수 1, 두 자리 수, 앞의 0이 있는 수를 각각 실행해 결과를 확인합니다. 예상 출력과 실제 출력에서 다른 구분자나 불필요한 문장이 없는지도 살핍니다. 정답 코드를 보기 전에 왜 문자열 결합이 잘못된 결과를 만들었는지 자신의 말로 설명하면 변환 이유를 익힌 것입니다.

미션과 더 읽기의 연결

이번 레슨 코드는 파일을 바꾸지 않고 표준 입력과 출력만 연습합니다. 모듈 미션에서는 앞 모듈 app.py의 파일 읽기 경로를 유지하면서 전달받은 제목과 쪽수를 검증합니다. 그때도 원문과 변환 결과 이름을 나누고 검증 성공 이후에만 OK 기록을 출력합니다. 더 읽기의 자료형 장은 다른 수 표현과 동적 타이핑의 선택을 다룹니다. 이 수업에서는 독서 기록의 수량 처리만 구현하고, 돈 계산처럼 별도 반올림 규칙이 필요한 문제는 뒤의 지출 레슨으로 넘깁니다. 맡은 기능의 계약을 좁혀 정확히 구현하는 것이 첫 실무 과제를 완성하는 방법입니다.

따라하기

값과 자료형 확인

새 Python 파일에 코드를 저장하고 python3 파일이름.py로 실행합니다. 각 단계는 독립된 파일로 실행할 수 있습니다.

title = "달빛 도서관"
raw_pages = "12"
pages = int(raw_pages)
print(type(title).__name__, type(raw_pages).__name__, type(pages).__name__)
print(raw_pages + "1", pages + 1)

실행 결과

str str int
121 13

두 줄 입력을 기록으로 출력

표준 입력에 다음 두 줄을 순서대로 넣습니다. 제목 줄은 달빛 도서관, 쪽수 줄은 12입니다. 로컬에서는 실행 후 입력하고 각 줄 끝에서 Enter를 누릅니다.

title = input()
raw_pages = input()
pages = int(raw_pages)
print(f"OK|{title}|{pages}")

실행 결과

OK|달빛 도서관|12

0을 보존하고 앞의 0을 정리

수량 표시와 문자열의 참·거짓 판정이 다른지 확인합니다.

print(int("0"))
print(int("0001"))
print(bool("0"))

실행 결과

0
1
True

실패한 변환의 오류 종류 읽기

제공된 예외 처리 코드를 그대로 실행합니다. int 변환 줄과 ValueError의 관계를 확인합니다.

try:
    pages = int("열둘")
except ValueError as error:
    print(type(error).__name__)

실행 결과

ValueError

확인 문제

실습

첫 줄 제목, 둘째 줄 0 이상의 ASCII 정수 문자열이 주어집니다. 제목은 그대로 유지하고 쪽수는 정수로 변환해 OK|제목|쪽수 한 줄을 출력합니다. 안내 문구는 출력하지 않습니다. 이 레슨에서는 제목 정리와 잘못된 입력 거부를 요구하지 않습니다.

모범 답안
title = input()
raw_pages = input()
pages = int(raw_pages)
print(f"OK|{title}|{pages}")

더 읽기

면접 질문

  • input()으로 받은 "12"와 정수 12의 차이를 덧셈 예시로 설명해 주세요.
  • 앞의 0이 있는 도서 ID와 쪽수를 각각 어떤 자료형으로 다루겠습니까?