방송대 오픈소스기반데이터분석 5강: 저장 형식 선택과 DataFrame 입출력
분석이 끝났다고 데이터 작업이 끝나는 것은 아니다. 결과를 다시 읽고 다른 사람과 공유하려면 데이터의 구조·크기·접근 방식에 맞는 저장 형식을 골라야 한다. CSV·JSON·데이터베이스의 선택 기준을 세우고, pandas DataFrame의 행·열·인덱스를 이해해 불러오기와 저장 과정에서 정보가 어떻게 보존되는지 확인한다.
저장 형식은 확장자가 아니라 다음 사용 방법으로 결정한다
데이터 저장은 수집한 값을 디스크에 옮기는 단순 작업이 아니다. 누가, 어떤 도구로, 얼마나 자주 읽을지와 어떤 구조를 보존해야 하는지를 결정하는 과정이다. 같은 표라도 엑셀에서 열어 전달할 자료와 서버가 반복 조회할 자료는 적합한 저장 방식이 다르다.
저장 방식 선택 질문: ① 데이터가 평평한 표인가, 중첩 구조인가? ② 한 번에 전체를 읽는가, 일부 행만 자주 조회하는가? ③ 여러 사용자가 동시에 수정하는가? ④ 자료형·제약 조건·보안·변경 이력을 어느 수준까지 보존해야 하는가? ⑤ 상대방이 사용할 프로그램은 무엇인가?
파일은 운영체제의 파일 시스템에 독립된 단위로 저장되어 이동과 공유가 쉽다. 반면 행 단위 갱신, 동시 접근, 무결성 제약과 세밀한 권한 관리에는 한계가 있다. 데이터베이스는 데이터를 체계적으로 저장하고 필요한 부분을 빠르게 검색·갱신하며, 여러 사용자의 접근과 제약을 관리하는 데 적합하다.
| 상황 | 우선 고려할 방식 | 판단 이유 |
|---|---|---|
| 작은 표를 여러 프로그램에서 교환 | CSV | 구조가 단순하고 호환성이 높음 |
| 목록 안에 목록이 있는 계층 데이터 | JSON | 객체·배열의 중첩 구조를 표현 가능 |
| 사용자가 직접 검토·편집하는 보고표 | Excel | 서식, 시트, 수동 검토에 편리 |
| 대량 자료의 반복 조회와 동시 수정 | 데이터베이스 | 검색, 트랜잭션, 제약과 접근 통제에 유리 |
CSV는 평평한 표에 강하지만 자료형과 계층을 직접 보존하지 않는다
CSV는 Comma-Separated Values, 즉 쉼표로 구분한 값이라는 뜻이다. 첫 줄을 열 이름으로 사용하고 이후 줄마다 한 행의 값을 기록하는 방식이 일반적이다. 텍스트라서 Excel, 스프레드시트, 데이터베이스와 여러 프로그래밍 언어에서 쉽게 읽을 수 있다.
student_id,database_score,python_score,watch_rate
101,85,92,0.95
102,76,78,0.87
103,92,85,0.99
CSV에는 “101은 정수”, “0.95는 실수”, “2026-08-30은 날짜”라는 자료형 정보가 별도로 들어 있지 않다. 읽는 프로그램이 문자열 모양을 보고 자료형을 추론한다. 값 자체에 쉼표, 줄바꿈, 따옴표가 있으면 인용 규칙도 적용해야 한다. 따라서 구분자를 직접 이어 붙이기보다 pandas나 표준 CSV 처리 도구를 사용해야 한다.
자주 생기는 오류: DataFrame의 인덱스를 기본 설정으로 CSV에 저장하면 이름 없는 첫 열처럼 다시 읽힐 수 있다. 인덱스가 단순 행 번호라면 index=False로 제외하고, 의미 있는 식별자라면 열 이름과 복원 방법을 명시한다.
JSON은 키와 배열로 데이터의 계층을 표현한다
JSON(JavaScript Object Notation)은 키-값 객체와 배열을 조합해 중첩 구조를 표현하는 텍스트 형식이다. 한 사람에게 여러 관심사가 연결되거나 API 응답 안에 측정값 목록과 부가 정보가 함께 들어 있을 때 CSV보다 자연스럽다.
{
"name": "홍길동",
"age": 25,
"address": "서울",
"interests": ["프로그래밍", "데이터 분석", "여행"]
}
JSON은 문자열, 숫자, 참·거짓, null, 객체, 배열을 구분한다. 그러나 DataFrame은 행과 열의 2차원 표이므로 깊게 중첩된 JSON을 곧바로 표로 만들면 한 셀 안에 목록이나 객체가 남을 수 있다. 분석 목적에 따라 중첩 구조를 펼치거나 관련 표로 분리해야 한다.
| 비교 기준 | CSV | JSON |
|---|---|---|
| 기본 구조 | 행과 열의 평평한 표 | 객체와 배열의 계층 구조 |
| 열 이름 | 보통 첫 행에 한 번 기록 | 각 객체의 키로 표현 |
| 자료형 표현 | 텍스트에서 읽을 때 추론 | 문자열·숫자·불리언·null 구분 |
| 대표 용도 | 표 교환, 간단한 분석 결과 | 웹 API, 설정, 중첩 레코드 |
데이터베이스는 저장뿐 아니라 검색과 무결성을 관리한다
관계형 데이터베이스 관리 시스템(RDBMS)은 데이터를 행과 열로 구성된 테이블에 저장하고 SQL로 생성·조회·수정·삭제(CRUD)한다. 기본키, 외래키, 고유성, 값의 범위 같은 제약을 통해 데이터 무결성을 관리할 수 있다.
비관계형 데이터베이스는 문서, 키-값, 그래프, 넓은 열 등 다양한 모델을 사용한다. MongoDB는 문서, Redis는 키-값과 여러 자료구조, Cassandra는 분산된 넓은 열 저장 방식의 대표 사례다. “비관계형이면 구조가 없다”는 뜻은 아니다. 데이터 모델과 검증 책임을 어디에 둘지가 관계형 시스템과 다르다.
파일과 데이터베이스는 경쟁 관계가 아니다. 원천 데이터를 파일로 보관하고 운영 데이터는 데이터베이스에서 조회하며, 분석 결과를 다시 CSV나 Excel로 내보낼 수 있다. 분석 파이프라인에서는 각 단계의 목적에 맞게 함께 사용한다.
파일에서 데이터베이스로 넘어갈 신호: 자료 전체를 매번 읽는 비용이 커지고, 여러 사용자가 동시에 수정하며, 특정 조건의 행을 반복 조회하고, 중복·누락을 제약으로 막아야 한다면 데이터베이스를 우선 검토한다.
DataFrame은 값과 두 축의 레이블로 이루어진 2차원 자료구조다
pandas의 DataFrame은 행과 열로 구성된 2차원 표 자료구조다. 각 열은 이름을 가지며 서로 다른 자료형을 가질 수 있다. 각 행에는 행 인덱스, 각 열에는 열 레이블이 붙고, 두 레이블의 교차점에 개별 값이 놓인다.
import pandas as pd
data = {
"student_id": [101, 102, 103],
"database_score": [85, 76, 92],
"python_score": [92, 78, 85],
"watch_rate": [0.95, 0.87, 0.99],
}
df = pd.DataFrame(data)
print(df.index)
print(df.columns)
print(df.to_numpy())
별도 인덱스를 지정하지 않으면 0부터 시작하는 RangeIndex가 만들어진다. df.columns는 열 레이블을, df.to_numpy()는 값 부분을 NumPy 배열 형태로 보여 준다. 값만 꺼내면 행·열 레이블이 빠지므로 다른 시스템에 전달할 때 어떤 순서의 열인지 함께 관리해야 한다.
DataFrame을 “같은 자료형만 들어가는 2차원 배열”로 이해하면 안 된다. 숫자 열과 문자열 열을 함께 가질 수 있고, pandas는 열별 자료형과 결측값을 관리한다. NumPy 기반의 빠른 연산을 활용하지만 DataFrame의 핵심은 레이블을 이용한 정렬과 선택에도 있다.
인덱스는 행 번호가 아니라 행을 식별하고 정렬하는 레이블이다
기본 정수 인덱스는 단순한 위치 표시로 쓰기 쉽다. 그러나 학생 번호, 날짜처럼 행을 식별하는 열이 있다면 set_index()로 인덱스로 지정할 수 있다.
indexed = df.set_index("student_id")
print(indexed.loc[102])
set_index()는 기본적으로 원본 df를 바로 바꾸지 않고 새 DataFrame을 반환한다. 따라서 결과를 변수에 받거나 inplace=True를 명시해야 한다. 인덱스로 옮긴 student_id는 기본 설정에서 일반 열 목록에서는 빠지지만 인덱스 이름으로 남는다.
인덱스 오개념: 인덱스는 반드시 유일해야 하는 기본키와 같지 않다. pandas는 중복 인덱스도 허용하므로, 학생 번호처럼 유일해야 하는 값은 indexed.index.is_unique로 직접 검증해야 한다.
행의 레이블을 기준으로 찾을 때는 loc, 정수 위치를 기준으로 찾을 때는 iloc를 사용한다. 인덱스가 101, 102, 103이라면 indexed.loc[102]는 학생 번호 102의 행이고, indexed.iloc[1]은 현재 두 번째 위치의 행이다. 정렬이나 필터링 뒤에는 위치가 바뀔 수 있으므로 두 기준을 구분해야 한다.
입력 함수는 원본 형태에 따라 고른다
DataFrame은 파이썬 객체, 파일, 웹 문서, 데이터베이스 결과에서 만들 수 있다. 메서드 이름은 “DataFrame 클래스의 생성자”와 “pandas 최상위 읽기 함수”를 구분해야 한다.
| 원본 | 대표 함수 | 핵심 확인 사항 |
|---|---|---|
| 열 중심 딕셔너리 | pd.DataFrame(data) 또는 DataFrame.from_dict() | 각 열의 길이가 같은지 |
| 레코드 목록 | DataFrame.from_records() | 필드 이름과 누락 필드 |
| CSV | pd.read_csv() | 인코딩, 구분자, 헤더, 결측값 |
| JSON | pd.read_json() | JSON 방향과 중첩 구조 |
| Excel | pd.read_excel() | 시트 이름, 헤더 행, 병합 셀 |
| HTML 표 | pd.read_html() | 반환되는 DataFrame 목록 중 대상 표 |
| 클립보드 표 | pd.read_clipboard() | 구분자와 복사 범위 |
| SQL 질의·테이블 | pd.read_sql() | 연결, 질의, 자료형과 권한 |
from_html(), from_clipboard(), from_sql()이 아니라 각각 pd.read_html(), pd.read_clipboard(), pd.read_sql()을 사용한다. 함수 이름을 외우기보다 파일·외부 소스에서 읽을 때는 대체로 read_, 이미 메모리에 있는 레코드로 만들 때는 생성자나 from_ 계열이라는 규칙을 기억하면 좋다.
출력 메서드는 목적지와 왕복 조건을 함께 지정한다
DataFrame의 저장·변환 메서드는 대체로 to_로 시작한다. to_csv(), to_json(), to_excel(), to_html(), to_sql()은 각각 파일이나 외부 구조로 내보낸다. to_dict(), to_string(), to_markdown()은 파이썬 객체나 표시용 문자열을 만드는 데도 쓸 수 있다.
df.to_csv("scores.csv", index=False, encoding="utf-8")
df.to_json("scores.json", orient="records", force_ascii=False)
csv_df = pd.read_csv("scores.csv")
json_df = pd.read_json("scores.json", orient="records")
index=False는 기본 행 번호를 별도 열로 저장하지 않게 한다. orient="records"는 JSON을 행별 객체의 배열로 표현한다. force_ascii=False는 한글을 사람이 읽을 수 있는 문자로 기록한다.
저장 성공만 확인해서는 부족하다. 다시 읽은 뒤 행 수, 열 이름, 열 순서, 자료형, 결측값 수, 식별자의 유일성을 비교해야 한다. 이 과정을 왕복(round-trip) 검증이라고 생각하면 형식 변환에서 생기는 정보 손실을 빠르게 찾을 수 있다.
assert len(csv_df) == len(df)
assert list(csv_df.columns) == list(df.columns)
assert csv_df["student_id"].is_unique
왕복 검증 5항목: 행 수, 열 레이블과 순서, 핵심 열의 자료형, 결측값, 식별자 유일성을 저장 전후에 비교한다. 금액·날짜·앞자리 0이 있는 코드값은 특히 주의한다.
공공 API 데이터는 인증·변환·저장의 세 경계를 지난다
공공데이터포털의 대기오염정보 같은 API를 활용하는 과정은 세 단계로 나눌 수 있다. 먼저 필요한 서비스를 신청하고 인증키를 준비한다. 다음으로 HTTP 요청을 보내 JSON 응답을 받고, 응답 상태와 실제 데이터 항목을 확인한 뒤 DataFrame으로 변환한다. 마지막으로 재사용 목적에 맞춰 CSV, JSON, Excel 또는 데이터베이스에 저장한다.
- 인증 경계: 키가 준비됐는지 확인하되 코드에 직접 적거나 공개 저장소에 올리지 않는다.
- 통신 경계: 응답 상태, 시간 초과, 호출 제한, 오류 메시지를 확인한다.
- 구조 경계: JSON의 실제 레코드 위치와 필드 이름을 확인하고 표로 펼친다.
- 저장 경계: 목적에 맞는 형식과 인덱스·인코딩·날짜 처리 옵션을 정한다.
- 검증 경계: 저장 파일을 다시 읽어 원본 DataFrame과 핵심 조건을 비교한다.
API 키는 외부 서비스 접근 권한과 사용량을 식별하는 문자열이다. 키가 노출되면 다른 사람이 할당량을 소진하거나 허가되지 않은 호출에 사용할 수 있다. 환경 변수나 별도의 비공개 설정 파일로 관리하고, 로그·노트북 출력·화면 캡처에도 포함되지 않도록 한다.
실습 범위 구분: 이 강의의 핵심은 특정 API의 현재 주소나 응답 필드를 암기하는 것이 아니라, API 응답을 DataFrame으로 바꾸고 저장 형식을 선택하는 흐름을 이해하는 데 있다. 실제 호출에서는 해당 서비스의 최신 명세를 확인해야 한다.
작은 선택표로 저장 방식을 최종 결정한다
학습용 상황을 적용해 보자. 1만 건의 대기 측정값을 동료에게 전달하고 Excel에서도 열어야 하며, 각 행은 시각·측정소·미세먼지 농도의 평평한 구조라고 가정한다. 이 경우 CSV가 단순하고 호환성이 높다. 날짜 열의 형식과 한글 인코딩을 정하고, 의미 없는 기본 인덱스는 제외한다.
반대로 한 측정소 아래 여러 센서와 시간대별 관측 목록이 중첩되어 있고 웹 서비스와 그대로 교환해야 한다면 JSON이 자연스럽다. 수백만 건을 여러 사용자가 계속 추가하고 측정소·기간 조건으로 반복 조회한다면 데이터베이스가 더 적합하다. 사람이 셀 서식과 여러 시트를 검토해야 한다면 Excel을 고려한다.
| 결정 축 | CSV 쪽 신호 | JSON 쪽 신호 | DB 쪽 신호 |
|---|---|---|---|
| 구조 | 고정된 행·열 | 객체·배열 중첩 | 관계·제약·조회 모델 |
| 접근 | 전체 파일 단위 | 메시지·API 단위 | 조건 조회와 부분 갱신 |
| 협업 | 전달·교환 중심 | 시스템 간 교환 | 동시 읽기·쓰기 |
| 검증 | 읽은 뒤 자료형 확인 | 스키마·중첩 경로 확인 | 제약·트랜잭션·권한 확인 |
핵심 개념 정리
- 저장 형식은 구조, 규모, 접근 빈도, 동시성, 무결성, 공유 도구를 기준으로 선택한다.
- CSV는 평평한 표 교환에, JSON은 계층 구조와 API 교환에, 데이터베이스는 반복 조회와 동시 갱신에 강하다.
- DataFrame은 값뿐 아니라 행 인덱스와 열 레이블을 가지며 열마다 자료형이 다를 수 있다.
set_index()는 식별 열을 행 레이블로 바꾸지만 유일성을 자동으로 보장하지 않는다.- 외부 소스는 주로
pd.read_*함수로 읽고, DataFrame은to_*메서드로 내보낸다. - 저장 후에는 다시 읽어 행·열·자료형·결측값·식별자 유일성을 검증한다.
저장 의사결정 순서: 데이터의 구조와 다음 사용자를 먼저 확인하고 형식을 선택한다. DataFrame으로 변환한 뒤 인덱스와 자료형을 점검하고, 목적에 맞는 to_* 옵션으로 저장한다. 마지막에는 반드시 다시 읽어 핵심 정보가 보존됐는지 확인하며, API 키와 개인정보는 파일 내용과 별도로 안전하게 관리한다.
예상문제 10선
1. CSV의 영문 명칭과 기본 구조를 올바르게 설명한 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
- ① 오답: 실제 약어 풀이가 아니며 CSV는 계층 객체 표현에 적합하지 않다.
- ② 오답: 마지막 단어는 Version이 아니라 Values이고 자료형은 읽을 때 추론된다.
- ③ 오답: 실제 명칭이 아니며 여러 시트는 CSV의 구조가 아니다.
- ④ 정답: 쉼표 같은 구분자로 열을 나눈 텍스트 기반 표 형식을 정확히 설명한다.
2. 한 사용자 아래 여러 주소와 관심사 목록이 중첩된 API 응답을 원래 구조에 가깝게 저장하려면?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
- ① 오답: 구분자와 필드 구조가 없으면 각 값을 안정적으로 복원할 수 없다.
- ② 정답: JSON의 객체와 배열은 중첩된 주소·관심사 구조를 직접 표현할 수 있다.
- ③ 오답: 인덱스만으로는 사용자 속성과 목록을 보존할 수 없다.
- ④ 오답: 문자 목록을 숫자 열로 강제하면 원래 의미와 구조가 손실된다.
3. 파일보다 데이터베이스를 우선 검토해야 할 신호는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ①
- ① 정답: 동시성, 부분 갱신, 조건 검색과 무결성 관리는 데이터베이스의 강점이다.
- ② 오답: 단순 교환 목적의 작은 평면 표에는 CSV 같은 파일이 간편하다.
- ③ 오답: 사람이 직접 읽을 작은 자료는 텍스트 파일의 장점이 살아난다.
- ④ 오답: 일회성 임시 결과에 데이터베이스 운영 비용을 들일 필요가 작다.
4. 별도 설정 없이 세 행으로 DataFrame을 만들었을 때 기본 행 인덱스는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
- ① 오답: pandas의 기본 인덱스는 1이 아니라 0에서 시작한다.
- ② 오답: 첫 열을 인덱스로 쓰려면
set_index()같은 명시적 설정이 필요하다. - ③ 정답: 세 행에는 0부터 2까지의 기본 RangeIndex가 자동으로 붙는다.
- ④ 오답: 열 이름은 열 레이블이며 행 인덱스와 다른 축이다.
5. indexed = df.set_index("student_id")에 대한 설명 중 틀린 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
- ① 오답:
inplace=True를 쓰지 않으면 결과를 새 객체로 반환하는 설명이 맞다. - ② 오답: 지정한 열이 새 행 인덱스로 이동한다는 설명이 맞다.
- ③ 오답:
loc는 인덱스 레이블을 기준으로 행을 찾는다. - ④ 정답: pandas는 중복 인덱스를 허용하므로 유일성을 별도로 검사해야 한다.
6. pandas 입력 함수의 연결이 올바른 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ①
- ① 정답: pandas 최상위의
read_html()함수가 HTML 표를 읽어 DataFrame 목록을 반환한다. - ② 오답: 클립보드 표는
pd.read_clipboard()로 읽는다. - ③ 오답: SQL 결과는
pd.read_sql()계열 함수로 읽는다. - ④ 오답: CSV 파일의 대표 함수는
pd.read_csv()다.
7. 기본 정수 인덱스가 있는 DataFrame을 CSV로 내보낼 때 불필요한 인덱스 열을 막는 옵션은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
- ① 오답: 이 옵션은 열 이름의 출력 여부를 제어하며 행 인덱스와 다르다.
- ② 오답:
to_csv()에서 인덱스 저장을 제어하는 올바른 옵션명이 아니다. - ③ 정답: 행 인덱스를 CSV 필드로 쓰지 않도록 지정한다.
- ④ 오답: 자료형을 거짓값으로 지정해 인덱스 출력을 제어할 수 없다.
8. API 데이터를 저장하는 과정의 순서로 가장 적절한 것은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ②
- ① 오답: 데이터를 받기 전에 저장할 수 없고 인증키 공개는 보안 위험이다.
- ② 정답: 접근 권한, 통신, 구조 변환, 저장, 재검증의 경계를 순서대로 지난다.
- ③ 오답: 인증과 호출보다 데이터 삭제가 먼저일 이유가 없고 순서도 거꾸로다.
- ④ 오답: 실제 응답 구조를 확인하지 않고 결과를 가정하면 변환 오류를 찾을 수 없다.
9. DataFrame 저장이 성공한 뒤에도 다시 읽어 검증해야 하는 가장 중요한 이유는?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ③
- ① 오답: 열 이름이 자동 번역되는 것이 일반적인 저장 동작은 아니다.
- ② 오답: 저장 메서드는 원본 DataFrame을 자동으로 삭제하지 않는다.
- ③ 정답: 텍스트 형식의 추론과 옵션 차이로 핵심 정보가 달라질 수 있어 왕복 확인이 필요하다.
- ④ 오답: 두 형식이 행 순서를 항상 뒤집는다는 규칙은 없다.
10. 평평한 대기 측정표를 동료에게 전달하고 Excel에서도 열게 할 때 가장 적절한 처리 조합은?
정답입니다.
오답입니다. 답안을 다시 선택해 보세요.
정답 및 해설 보기
정답: ④
- ① 오답: 전달 목적을 충족하지 못하고 식별자 품질도 확인하지 않았다.
- ② 오답: 평평한 표에 불필요하게 복잡하며 인증키를 데이터에 넣으면 안 된다.
- ③ 오답: 화면 출력만으로는 재사용과 구조 검증이 불가능하다.
- ④ 정답: 호환성 높은 형식을 선택하고 저장 옵션과 왕복 검증까지 포함한 완전한 절차다.
참고 자료와 작성 기준
이 글은 해당 차시 강의자료를 바탕으로 학습 목적에 맞게 재구성한 비공식 학습자료입니다. 개념 관계, 예제와 문제 해설은 학습자의 이해를 돕도록 구성하고 검토했습니다.
- 작성·편집: 올에이클래스 학습연구팀
- 주요 근거: 한국방송통신대학교 컴퓨터과학과 「오픈소스 기반 데이터분석」 제5강 강의자료(2025)
- 보충 자료: pandas 공식 API 문서의 read_html, read_clipboard, read_sql, DataFrame.to_csv(2026-08-30 확인)
- 편집 원칙: 올에이클래스 편집 정책
- 최종 내용 검토: 2026-08-30
댓글
댓글 쓰기