웹사이트에서 데이터를 찾았습니다. 데이터베이스에 넣어야 합니다.
A 지점에서 B 지점까지 가장 빠른 경로는 무엇일까요?
이 가이드에서는 HTML 테이블을 SQLite, PostgreSQL, MySQL 및 기타 데이터베이스에 최소한의 마찰로 가져오는 실용적인 워크플로를 다룹니다.
일반적인 워크플로
모든 브라우저-데이터베이스 파이프라인은 같은 단계를 거칩니다:
- 추출 — 웹페이지에서 테이블 가져오기
- 정제 — 서식, 타입, 구조 수정
- 적재 — 데이터베이스에 삽입
문제는 각 단계를 어디서 어떤 도구로 수행할 것인가입니다.
경로 1: CSV를 중간 매개체로 사용
가장 일반적인 접근 방식입니다. 모든 데이터베이스에서 작동합니다.
1단계: CSV로 내보내기
HTML Table Exporter 같은 브라우저 확장 프로그램을 사용하거나 스프레드시트에 복사-붙여넣기 후 CSV로 저장합니다.
핵심 고려사항: 구분자 선택. 쉼표는 데이터에 쉼표가 포함되지 않는 한 잘 작동합니다. 세미콜론이나 탭은 복잡한 데이터에 더 안전합니다.
2단계: 데이터베이스에 로드
SQLite:
sqlite3 mydb.db
.mode csv
.import data.csv tablename
헤더 포함:
sqlite3 mydb.db <<EOF
.mode csv
.headers on
.import data.csv tablename
EOF
PostgreSQL:
COPY tablename FROM '/path/to/data.csv'
WITH (FORMAT csv, HEADER true);
psql 사용 시:
\copy tablename FROM 'data.csv' WITH (FORMAT csv, HEADER true);
MySQL:
LOAD DATA INFILE '/path/to/data.csv'
INTO TABLE tablename
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;
장단점
✅ 범용 호환성
✅ 중간 파일 쉽게 검사 가능
✅ 로딩 전 수동 수정 가능
❌ 추가 단계 필요
❌ 타입 추론이 기본적
경로 2: SQL 문 직접 생성
테이블을 INSERT 문으로 직접 내보냅니다.
SQL로 내보내기
일부 내보내기 도구는 SQL을 직접 생성합니다. 출력은 다음과 같습니다:
INSERT INTO table_name (col1, col2, col3) VALUES
('value1', 'value2', 123),
('value4', 'value5', 456);
로드
SQL 파일을 실행하면 됩니다:
# SQLite
sqlite3 mydb.db < data.sql
# PostgreSQL
psql -d mydb -f data.sql
# MySQL
mysql mydb < data.sql
장단점
✅ 내보내기에서 데이터베이스까지 한 단계
✅ SQL은 데이터베이스 간 이식 가능 (대부분)
❌ 대규모 데이터셋 = 거대한 SQL 파일
❌ 테이블 스키마를 먼저 정의해야 함
경로 3: Python + Pandas 파이프라인
최대한의 유연성. 반복 임포트나 복잡한 정제에 최적입니다.
전체 워크플로
import pandas as pd
from sqlalchemy import create_engine
# 1단계: CSV 로드 (브라우저에서 내보낸 것)
df = pd.read_csv('data.csv')
# 2단계: 정제
df.columns = df.columns.str.lower().str.replace(' ', '_') # 열 이름 정규화
df['date'] = pd.to_datetime(df['date']) # 날짜 파싱
df['amount'] = df['amount'].str.replace('[$,]', '', regex=True).astype(float) # 통화 정제
# 3단계: 데이터베이스에 로드
engine = create_engine('sqlite:///mydb.db')
# 또는: create_engine('postgresql://user:pass@localhost/mydb')
# 또는: create_engine('mysql+pymysql://user:pass@localhost/mydb')
df.to_sql('tablename', engine, if_exists='replace', index=False)
타입 매핑
Pandas는 타입을 추론하지만 명시적으로 지정할 수도 있습니다:
df.to_sql('tablename', engine,
if_exists='replace',
index=False,
dtype={
'id': Integer(),
'name': String(100),
'created_at': DateTime(),
'amount': Float()
})
장단점
✅ 정제와 타입에 대한 완전한 제어
✅ 복잡한 변환 처리 가능
✅ 반복 가능하고 스크립트화 가능
❌ Python 환경 필요
❌ 일회성 임포트에는 과도함
경로 4: DuckDB (현대적 지름길)
DuckDB는 CSV를 직접 읽고 대부분의 정제를 자동으로 처리합니다.
직접 쿼리
-- 임포트 없이 CSV 쿼리
SELECT * FROM 'data.csv';
-- 타입 추론 포함
SELECT * FROM read_csv_auto('data.csv');
-- CSV에서 테이블 생성
CREATE TABLE mytable AS SELECT * FROM 'data.csv';
브라우저에서 쿼리까지 몇 초만에
# 브라우저에서 CSV로 테이블 내보내기
# 그리고 바로 쿼리:
duckdb -c "SELECT column1, SUM(column2) FROM 'data.csv' GROUP BY column1;"
스키마 정의 없음. 임포트 단계 없음. 바로 쿼리.
장단점
✅ 임시 분석에 가장 빠름
✅ 우수한 타입 추론
✅ SQL 인터페이스
❌ 전통적인 데이터베이스가 아님 (영속성을 위해서는 결과를 내보내야 함)
일반적인 문제 처리
공백이 있는 열 이름
웹 테이블에는 "총 매출"이나 "연초 대비" 같은 헤더가 자주 있습니다.
내보내기 시 수정: 일부 도구는 헤더를 자동으로 정규화합니다.
임포트 시 수정:
df.columns = df.columns.str.replace(' ', '_').str.lower()
또는 임포트 후 SQL에서:
ALTER TABLE mytable RENAME COLUMN "Total Sales" TO total_sales;
혼합된 숫자 형식
유럽식 (1.234,56)과 미국식 (1,234.56) 형식은 임포트를 망칩니다.
임포트 전 수정: 정제 프리셋이 있는 도구를 사용하거나:
# 유럽식을 표준으로
df['value'] = df['value'].str.replace('.', '').str.replace(',', '.').astype(float)
Null 표현
웹 테이블은 빈칸, "N/A", "—", "-"로 결측 데이터를 표시합니다.
df = df.replace(['N/A', '—', '-', ''], pd.NA)
DuckDB에서:
SELECT NULLIF(column, 'N/A') AS column FROM 'data.csv';
다양한 형식의 날짜
df['date'] = pd.to_datetime(df['date'], format='mixed', dayfirst=True)
format='mixed'는 같은 열에서 일관되지 않은 날짜 형식을 처리합니다.
올바른 경로 선택
| 시나리오 | 추천 경로 |
|---|---|
| 일회성 임포트, 작은 테이블 | CSV + 데이터베이스 직접 임포트 |
| 일회성 임포트, 정제 필요 | Python + Pandas |
| 빠른 분석, 영속성 불필요 | DuckDB |
| 같은 소스에서 정기적 임포트 | Python 스크립트 (자동화) |
| 공유/버전 관리를 위한 SQL 형식 필요 | SQL 직접 내보내기 |
예시: 전체 워크플로
웹사이트에 제품 데이터 테이블이 있다고 합시다.
1단계: HTML Table Exporter로 내보내기 → 정제된 숫자가 포함된 CSV
2단계: DuckDB에서 빠른 검증:
SELECT COUNT(*), COUNT(DISTINCT product_id) FROM 'products.csv';
-- 중복 확인
3단계: PostgreSQL에 로드:
import pandas as pd
from sqlalchemy import create_engine
df = pd.read_csv('products.csv')
engine = create_engine('postgresql://user:pass@localhost/inventory')
df.to_sql('products', engine, if_exists='replace', index=False)
총 소요 시간: 2분.
핵심 교훈
가장 짧은 경로가 항상 가장 직접적인 것은 아닙니다.
내보내기 단계에서 30초를 정제에 투자하면 임포트 오류 디버깅에 10분을 절약할 수 있습니다. 올바른 중간 형식(CSV vs SQL vs JSON)을 사용하는 것은 대상 데이터베이스와 데이터 복잡성에 따라 다릅니다.
대부분의 웹 테이블 → 데이터베이스 워크플로에서:
- 숫자/날짜 정제와 함께 CSV로 내보내기
- 데이터베이스의 기본 CSV 임포트로 로드
- 복잡한 변환이 필요할 때만 Python 사용
단순한 파이프라인이 유지 가능한 파이프라인입니다.
Python 워크플로에 대해 자세히 알아보려면 Python & Pandas용 웹 테이블을 JSON으로 내보내기 가이드를 참조하세요.
데이터베이스에 바로 사용할 수 있는 깔끔한 내보내기가 필요하신가요? gauchogrid.com/ko/html-table-exporter에서 자세히 알아보거나 Chrome 웹 스토어에서 HTML Table Exporter를 무료로 사용해 보세요.
Top comments (0)