DEV Community

Cover image for 브라우저에서 데이터베이스까지: 웹 테이블의 가장 빠른 경로
circobit
circobit

Posted on

브라우저에서 데이터베이스까지: 웹 테이블의 가장 빠른 경로

웹사이트에서 데이터를 찾았습니다. 데이터베이스에 넣어야 합니다.

A 지점에서 B 지점까지 가장 빠른 경로는 무엇일까요?

이 가이드에서는 HTML 테이블을 SQLite, PostgreSQL, MySQL 및 기타 데이터베이스에 최소한의 마찰로 가져오는 실용적인 워크플로를 다룹니다.

일반적인 워크플로

모든 브라우저-데이터베이스 파이프라인은 같은 단계를 거칩니다:

  1. 추출 — 웹페이지에서 테이블 가져오기
  2. 정제 — 서식, 타입, 구조 수정
  3. 적재 — 데이터베이스에 삽입

문제는 각 단계를 어디서 어떤 도구로 수행할 것인가입니다.

경로 1: CSV를 중간 매개체로 사용

가장 일반적인 접근 방식입니다. 모든 데이터베이스에서 작동합니다.

1단계: CSV로 내보내기

HTML Table Exporter 같은 브라우저 확장 프로그램을 사용하거나 스프레드시트에 복사-붙여넣기 후 CSV로 저장합니다.

핵심 고려사항: 구분자 선택. 쉼표는 데이터에 쉼표가 포함되지 않는 한 잘 작동합니다. 세미콜론이나 탭은 복잡한 데이터에 더 안전합니다.

2단계: 데이터베이스에 로드

SQLite:

sqlite3 mydb.db
.mode csv
.import data.csv tablename
Enter fullscreen mode Exit fullscreen mode

헤더 포함:

sqlite3 mydb.db <<EOF
.mode csv
.headers on
.import data.csv tablename
EOF
Enter fullscreen mode Exit fullscreen mode

PostgreSQL:

COPY tablename FROM '/path/to/data.csv' 
WITH (FORMAT csv, HEADER true);
Enter fullscreen mode Exit fullscreen mode

psql 사용 시:

\copy tablename FROM 'data.csv' WITH (FORMAT csv, HEADER true);
Enter fullscreen mode Exit fullscreen mode

MySQL:

LOAD DATA INFILE '/path/to/data.csv'
INTO TABLE tablename
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;
Enter fullscreen mode Exit fullscreen mode

장단점

✅ 범용 호환성

✅ 중간 파일 쉽게 검사 가능

✅ 로딩 전 수동 수정 가능

❌ 추가 단계 필요

❌ 타입 추론이 기본적

경로 2: SQL 문 직접 생성

테이블을 INSERT 문으로 직접 내보냅니다.

SQL로 내보내기

일부 내보내기 도구는 SQL을 직접 생성합니다. 출력은 다음과 같습니다:

INSERT INTO table_name (col1, col2, col3) VALUES
('value1', 'value2', 123),
('value4', 'value5', 456);
Enter fullscreen mode Exit fullscreen mode

로드

SQL 파일을 실행하면 됩니다:

# SQLite
sqlite3 mydb.db < data.sql

# PostgreSQL
psql -d mydb -f data.sql

# MySQL
mysql mydb < data.sql
Enter fullscreen mode Exit fullscreen mode

장단점

✅ 내보내기에서 데이터베이스까지 한 단계

✅ 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)
Enter fullscreen mode Exit fullscreen mode

타입 매핑

Pandas는 타입을 추론하지만 명시적으로 지정할 수도 있습니다:

df.to_sql('tablename', engine, 
          if_exists='replace', 
          index=False,
          dtype={
              'id': Integer(),
              'name': String(100),
              'created_at': DateTime(),
              'amount': Float()
          })
Enter fullscreen mode Exit fullscreen mode

장단점

✅ 정제와 타입에 대한 완전한 제어

✅ 복잡한 변환 처리 가능

✅ 반복 가능하고 스크립트화 가능

❌ 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';
Enter fullscreen mode Exit fullscreen mode

브라우저에서 쿼리까지 몇 초만에

# 브라우저에서 CSV로 테이블 내보내기
# 그리고 바로 쿼리:
duckdb -c "SELECT column1, SUM(column2) FROM 'data.csv' GROUP BY column1;"
Enter fullscreen mode Exit fullscreen mode

스키마 정의 없음. 임포트 단계 없음. 바로 쿼리.

장단점

✅ 임시 분석에 가장 빠름

✅ 우수한 타입 추론

✅ SQL 인터페이스

❌ 전통적인 데이터베이스가 아님 (영속성을 위해서는 결과를 내보내야 함)

일반적인 문제 처리

공백이 있는 열 이름

웹 테이블에는 "총 매출"이나 "연초 대비" 같은 헤더가 자주 있습니다.

내보내기 시 수정: 일부 도구는 헤더를 자동으로 정규화합니다.

임포트 시 수정:

df.columns = df.columns.str.replace(' ', '_').str.lower()
Enter fullscreen mode Exit fullscreen mode

또는 임포트 후 SQL에서:

ALTER TABLE mytable RENAME COLUMN "Total Sales" TO total_sales;
Enter fullscreen mode Exit fullscreen mode

혼합된 숫자 형식

유럽식 (1.234,56)과 미국식 (1,234.56) 형식은 임포트를 망칩니다.

임포트 전 수정: 정제 프리셋이 있는 도구를 사용하거나:

# 유럽식을 표준으로
df['value'] = df['value'].str.replace('.', '').str.replace(',', '.').astype(float)
Enter fullscreen mode Exit fullscreen mode

Null 표현

웹 테이블은 빈칸, "N/A", "—", "-"로 결측 데이터를 표시합니다.

df = df.replace(['N/A', '', '-', ''], pd.NA)
Enter fullscreen mode Exit fullscreen mode

DuckDB에서:

SELECT NULLIF(column, 'N/A') AS column FROM 'data.csv';
Enter fullscreen mode Exit fullscreen mode

다양한 형식의 날짜

df['date'] = pd.to_datetime(df['date'], format='mixed', dayfirst=True)
Enter fullscreen mode Exit fullscreen mode

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';
-- 중복 확인
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

총 소요 시간: 2분.

핵심 교훈

가장 짧은 경로가 항상 가장 직접적인 것은 아닙니다.

내보내기 단계에서 30초를 정제에 투자하면 임포트 오류 디버깅에 10분을 절약할 수 있습니다. 올바른 중간 형식(CSV vs SQL vs JSON)을 사용하는 것은 대상 데이터베이스와 데이터 복잡성에 따라 다릅니다.

대부분의 웹 테이블 → 데이터베이스 워크플로에서:

  1. 숫자/날짜 정제와 함께 CSV로 내보내기
  2. 데이터베이스의 기본 CSV 임포트로 로드
  3. 복잡한 변환이 필요할 때만 Python 사용

단순한 파이프라인이 유지 가능한 파이프라인입니다.

Python 워크플로에 대해 자세히 알아보려면 Python & Pandas용 웹 테이블을 JSON으로 내보내기 가이드를 참조하세요.


데이터베이스에 바로 사용할 수 있는 깔끔한 내보내기가 필요하신가요? gauchogrid.com/ko/html-table-exporter에서 자세히 알아보거나 Chrome 웹 스토어에서 HTML Table Exporter를 무료로 사용해 보세요.

Top comments (0)