교재 홈: 바이브 코더를 위한 코딩 기초 학습

이 장에서는 글자로 저장한 표 형식인 CSV를 읽고, 사용할 수 있는 기록과 오류가 있는 기록을 나눕니다. 표의 가로줄을 행(row), 세로로 같은 종류의 항목을 모은 것을 **열(column)**이라고 합니다. 값의 종류와 범위를 규칙과 대조하는 것이 검증이고, 그 규칙에 맞는 값이 유효한 값입니다. **정제(cleaning)**는 공백 정리나 오류 분류처럼 정한 기준에 따라 자료를 다듬는 일입니다. 처리 전 자료인 원자료를 보존하면서 바뀐 내용을 설명하는 것이 목표입니다.

먼저 03. 자료구조 — 여러 값을 어떤 관계로 묶을 것인가의 「없는 값과 기본값」절의 ‘0과 미입력의 차이’, 04. 함수와 모듈 — 입력·처리·반환을 나누기의 「매개변수와 인수, 반환값」절의 ‘함수의 입력과 반환’을 확인하면 코드를 따라가기 쉽습니다.

경로와 인코딩

**경로(path)**는 파일이나 폴더의 위치를 적은 주소입니다. 절대경로는 컴퓨터의 정해진 시작점부터 위치 전체를 적고, 상대경로는 현재 기준 폴더에서 어디로 갈지 적습니다. Path("data") / "reading.csv"의 /는 여기서는 나눗셈이 아니라 경로를 이어 붙이는 연산입니다. 현재 폴더 아래 data 안의 reading.csv를 뜻합니다.

Path(__file__).resolve().parent는 코드 파일의 위치를 기준으로 그 파일이 담긴 폴더를 구합니다. __file__은 코드 파일의 위치, resolve()는 실제 기준에 맞춰 경로를 정리하는 기능, parent는 바로 위 폴더를 가리킵니다. 터미널을 어디에서 열었는지에 영향받지 않고 코드 옆의 자료를 찾을 때 유용합니다.

from pathlib import Path

BASE = Path(__file__).resolve().parent
input_path = BASE / "data" / "reading.csv"
print(input_path)

이 예제는 .py 파일에 저장해 실행합니다. 명령을 한 줄씩 입력하고 바로 결과를 보는 대화형 Python이나, 문서 안의 코드 칸을 따로 실행하는 노트북(notebook) 환경에는 __file__이 없을 수 있습니다. 이 교재의 기본 실행 방식은 1장에서 배운 파일 저장 후 실행입니다. pathlib는 경로를 다루는 표준 모듈이며 Windows와 macOS의 경로 표기 차이를 일부 대신 처리해 줍니다.

**인코딩(encoding)**은 글자를 저장하고 전달할 수 있는 숫자 정보로 표현하는 규칙입니다. **바이트(byte)**는 컴퓨터 자료 크기를 세는 기본 단위의 하나이며, 글자 하나가 항상 1바이트인 것은 아닙니다. UTF-8과 CP949는 서로 다른 글자 저장 규칙의 이름입니다. 저장할 때와 읽을 때의 규칙이 다르면 한글이 깨지거나 오류가 날 수 있습니다.

BOM은 일부 텍스트 파일 맨 앞에 붙어 인코딩을 구별하는 데 쓰이는 표시입니다. 이 교재의 utf-8-sig는 일반 UTF-8과 UTF-8 BOM이 있는 파일을 읽도록 선택한 값입니다. 모든 인코딩을 자동 판별하는 기능은 아닙니다. 해석할 수 없는 글자를 버리는 errors="ignore"는 원자료의 일부가 사라진 사실을 숨길 수 있으므로 원인을 확인하는 대신 사용하지 않습니다.

텍스트 파일은 path.read_text(encoding="utf-8")로 읽을 수 있습니다. 저장에는 open("x", encoding="utf-8")를 사용하면 기존 파일이 있을 때 실패하여 덮어쓰기를 피할 수 있습니다. "w"는 기존 내용을 지우고 새로 쓰므로 사용 목적을 확인해야 합니다.

CSV와 JSON

**CSV(Comma-Separated Values)**는 표의 값을 보통 쉼표로 구분해 저장하는 텍스트 형식입니다. 표의 한 칸을 **셀(cell)**이라고 합니다. 셀 내용 안에도 쉼표나 줄바꿈이 들어갈 수 있어, 파일의 쉼표마다 무조건 자르는 방식은 정확하지 않습니다. csv 모듈이 정해진 표기 규칙을 해석하게 합니다. 저장된 글을 규칙에 따라 해석해 사용 가능한 값으로 바꾸는 일을 파싱(parsing), 그 일을 하는 코드를 **파서(parser)**라고 합니다.

**JSON(JavaScript Object Notation)**은 이름과 값의 짝, 목록 등의 구조를 글로 저장하거나 전달하는 형식입니다. JSON의 객체는 이름과 값의 묶음이고 배열은 순서가 있는 목록입니다. Python의 딕셔너리·리스트와 비슷하게 읽을 수 있지만 표기 규칙은 다릅니다. Python의 None은 JSON에서 null, True는 true가 됩니다. 03. 자료구조 — 여러 값을 어떤 관계로 묶을 것인가의 「리스트·튜플·딕셔너리·집합」절에서 묶음의 차이를 다시 볼 수 있습니다.

json.load()는 파일에서 JSON을 읽고 json.loads()는 이미 읽은 문자열을 JSON으로 해석합니다. 글을 Python 코드로 실행하는 eval()은 자료를 읽는 용도로 쓰지 않습니다. 자료에 적힌 내용을 명령으로 실행하는 문제는 12. 보안과 개인정보 — 실행 권한과 데이터 이동을 읽기의 「명령 실행과 샌드박스」절와 연결됩니다.

CSV의 30은 읽은 직후 문자열입니다. JSON에서는 숫자 30으로 저장할 수도 있습니다. 파일이 정상적으로 파싱되었다는 사실과 각 필드가 요구한 자료형이라는 사실은 다릅니다.

실습 데이터와 처리 규칙

첫 줄의 열 이름을 **헤더(header)**라고 합니다. 각 데이터 행에는 독서 기록 한 건을 적습니다. id는 기록 식별자, title은 제목, minutes는 분 단위 시간, completed는 완료 여부입니다. 여기서 완료 여부는 yes와 no라는 두 글 중 하나로 적는 약속입니다. 이 표에서 R001 같은 ID는 사람의 이름이 아니라 기록을 구분하기 위해 만든 표지입니다.

data 폴더에 reading.csv를 UTF-8 텍스트로 저장합니다. 도서명과 기록은 모두 실습용으로 만든 가상 자료입니다.