XML / HTML 테이블 / 웹 스크래핑 (정적 HTML)

발행: (2025년 12월 12일 오전 04:49 GMT+9)
7 min read
원문: Dev.to

Source: Dev.to

빠른 작업공간 준비

# Check working directory
getwd()

# Set working directory (if you must)
setwd("/path/to/project")

# Start with a clean environment (use with care)
rm(list = ls())

# Show files in the current directory
list.files()

Base R vs 현대 tidyverse / 고성능 패키지

  • Base R (read.table, read.csv, read.delim) – 어디서든 작동하고 유연합니다.
  • readr (read_csv, read_delim) – 더 빠르고 일관된 파싱, tidyverse와 친화적.
  • data.table::fread – CSV와 유사한 대용량 파일에 대해 매우 빠릅니다.
  • readxl – Excel에 최적 (외부 의존성 없음).
  • haven – SAS/SPSS/Stata에 최적 (ReadStat 사용).
  • jsonlite – 최신 JSON 파싱.
  • DBI + 특정 DB 백엔드 – 관계형 DB에 대한 표준 인터페이스.
  • arrow – Feather/Parquet 및 Python/Spark와의 상호 운용; 대용량 컬럼형 데이터에 탁월.

CSV / 구분 텍스트

권장

  • 소‑중형 파일: readr::read_csv()
  • 매우 큰 파일: data.table::fread() 또는 vroom::vroom()

예시

# readr – tidy defaults, prints parsing problems
install.packages("readr")
library(readr)

df  <- read_csv("data/sales.csv")               # comma‑separated
df2 <- read_delim("data/data.txt", "\t")        # tab‑separated
# data.table – blazing fast, automatic type detection
install.packages("data.table")
library(data.table)

dt <- fread("data/sales.csv")
# vroom – lazy loading, fast for many files
install.packages("vroom")
library(vroom)

df_v <- vroom("data/sales.csv")

유용한 인자

  • locale = locale(encoding = "UTF-8") – 인코딩 처리.
  • col_types = cols(...) – 컬럼 타입 강제 지정 (오파싱 오류 방지).
  • na = c("", "NA", "NULL") – 결측값 토큰 지정.
  • n_max – 처음 N 행만 읽어 빠르게 살펴보기.

Excel (XLS / XLSX)

권장

  • readxl::read_excel() – Java 의존성 없이 신뢰성 높음.
  • tidyxl, openxlsx – 수식 처리 또는 쓰기용.

예시

install.packages("readxl")
library(readxl)

# Read the first sheet
df <- read_excel("data/book.xlsx")

# Read a specific sheet by name or index
df_sheet3 <- read_excel("data/book.xlsx", sheet = "Sales")
df_sheet2 <- read_excel("data/book.xlsx", sheet = 2)

# Read a range
df_range <- read_excel("data/book.xlsx", range = "A1:F100")

JSON

권장

  • jsonlite::fromJSON() – 견고함; 배열을 적절히 데이터프레임으로 변환.
install.packages("jsonlite")
library(jsonlite)

# From a local file
j <- fromJSON("data/doc.json", flatten = TRUE)

# From a URL
j2 <- fromJSON("https://api.example.com/data")

팁: JSON에 중첩 리스트가 있으면 flatten = TRUE를 사용하거나 tidyr::unnest()로 직접 정리합니다.

XML / HTML 테이블 / 웹 스크래핑 (정적 HTML)

권장

  • HTML 스크래핑 / 테이블 추출에 xml2 + rvest.
  • 보다 복잡한 XML 파싱에는 XML (하지만 일반적으로 xml2가 선호됨).
install.packages(c("xml2", "rvest"))
library(xml2)
library(rvest)

page   <- read_html("https://example.com/page-with-tables")
tables <- html_table(html_nodes(page, "table"))  # list of tibbles

Excel‑유사 및 레거시 포맷 (ODS, Google Sheets)

Google Sheets

install.packages("googlesheets4")
library(googlesheets4)

sheet <- read_sheet("https://docs.google.com/spreadsheets/...")

ODS

install.packages("readODS")
library(readODS)

ods_data <- read_ods("data/file.ods")

SAS / SPSS / Stata

권장

  • haven (빠르고 라벨이 붙은 변수 보존).
  • foreign는 오래된 패키지; haven이 선호됩니다.
install.packages("haven")
library(haven)

df_sas   <- read_sas("data/data.sas7bdat")
df_spss  <- read_sav("data/data.sav")
df_stata <- read_dta("data/data.dta")

팁: haven은 값 라벨(labelled 클래스)을 유지합니다. labelled::to_factor()로 팩터로 변환하세요.

MATLAB / Octave

install.packages("R.matlab")
library(R.matlab)

m <- readMat("data/matrix.mat")

Octave 텍스트 데이터의 경우:

install.packages("foreign")
library(foreign)

oct_data <- read.octave("data/file.oct")

Parquet, Feather, Arrow — 현대 컬럼형 포맷

install.packages("arrow")
library(arrow)

# Read Parquet
tbl <- read_parquet("data/data.parquet")

# Write Parquet
write_parquet(df, "out/data.parquet")

장점: Arrow는 메모리 외(out‑of‑memory) 및 제로‑카피 읽기를 지원하며 대규모 파이프라인에 이상적입니다.

ODBC / 관계형 DB (SQL Server, Postgres, MySQL 등)

권장 접근법

  • DBI + 드라이버 패키지(RPostgres, RMySQL, odbc) – 표준 인터페이스.
  • pool은 애플리케이션에서 연결 풀링에 사용.

예시: DBI를 통한 PostgreSQL

install.packages(c("DBI", "RPostgres"))
library(DBI)

con <- dbConnect(RPostgres::Postgres(),
                 dbname = "mydb",
                 host   = "db.example.com",
                 port   = 5432,
                 user   = "me",
                 password = "pw")

# Run a query
df <- dbGetQuery(con, "SELECT * FROM schema.table LIMIT 1000")

# Fetch a big table in chunks
res   <- dbSendQuery(con, "SELECT * FROM big_table")
chunk <- dbFetch(res, n = 10000)

# Clean up
dbClearResult(res)
dbDisconnect(con)

ODBC (Windows / DSN)

install.packages("odbc")
library(DBI)

con <- dbConnect(odbc::odbc(), DSN = "my_dsn", UID = "user", PWD = "pw")
dbListTables(con)
dbDisconnect(con)

팁: 대용량 테이블에 SELECT *를 피하고 필요한 컬럼만 선택하고 SQL 단계에서 필터링하세요.

클라우드 스토리지 (S3, GCS, Azure)

  • S3: aws.s3; Arrow는 S3 URI에서 직접 읽을 수 있습니다.
  • Google Cloud Storage: gcsfs(덜 일반적) 또는 Arrow/GCS 통합.
  • Azure: AzureStor.

aws.s3 예시

install.packages("aws.s3")
library(aws.s3)

# Configure AWS credentials (env vars or ~/.aws/credentials)
s3read_using(FUN = read.csv, object = "s3://my-bucket/data.csv")

Arrow로 S3에서 Parquet 읽기:

arrow::read_parquet("s3://bucket/path/file.parquet")

청크/스트리밍 방식으로 대용량 파일 읽기

  • 데이터베이스 가져오기와 쿼리 부분집합 활용.
  • data.table::fread(select = ...) 로 특정 컬럼만 읽기.
  • vroom + dplyr 로 지연 로드.
  • 복잡한 청크 처리: readr::read_lines_chunked() 또는 LaF, iotools 패키지 사용.

LaF 예시

install.packages("LaF")
library(LaF)

laf   <- laf_open_csv("big.csv",
                      column_types = c("integer", "double", "string"),
                      nrows = 1e8)
block <- laf[1:100000, ]  # first 100k rows

날짜·시간·타입 파싱

올바른 파싱은 이후 문제를 방지합니다.

install.packages("lubridate")
library(lubridate)

df$date     <- ymd(df$date_string)          # "2023-07-01"
df$datetime <- ymd_hms(df$ts)                # "2023-07-01 08:45:00"

readr에서는 col_types, fread에서는 colClasses 로 컬럼 타입을 강제 지정하세요.

인코딩 & 로케일 문제

문자가 깨지는 경우:

# readr
df <- read_csv("file.csv", locale = locale(encoding = "latin1"))

# base read.table
df <- read.table("file.txt", fileEncoding = "UTF-8")

Encoding() 으로 확인하고 필요하면 iconv() 로 변환합니다.

흔한 가져오기 함정 및 트러블슈팅

  • 헤더 정렬 오류 / 주석: skip = n, comment = "#", skip_empty_rows = TRUE 사용.
  • 컬럼 타입 불일치: 컬럼 타입을 미리 지정(col_types 또는 colClasses).
  • NA 토큰: na = c("", "NA", "n/a") 설정.
  • 천 단위 구분자 / 소수점 표시: locale = locale(decimal_mark = ",", grouping_mark = ".").
  • 메모리 오류: SQL에서 필터링하거나 부분집합만 로드하거나 Arrow/Parquet 로 컬럼만 읽어 보세요.

빠른 팁 & 생산성 트릭

  • 클립보드 가져오기 (Windows/Mac):

    df <- read.table("clipboard", header = TRUE, sep = "\t")
  • 전체 가져오기 전에 첫 몇 행 미리 보기:

    readr::read_lines("file.csv", n_max = 10)
  • readr 가져오기 후 파싱 문제 확인:

    problems()
Back to Blog

관련 글

더 보기 »