Skip to content

R에서 데이터 가져오기: 빠르고, 정확하며, 재현 가능한 로딩

문제

느린 파일 로딩과 깨진 문자 인코딩 때문에 분석이 시작도 못 하고 막히는 경우가 많습니다. 팀은 CSV나 Excel 파일이 올 때마다 불필요하게 import 코드를 다시 짜느라 시간을 낭비합니다.

문제 심화

잘못된 인코딩 설정은 비 ASCII 텍스트를 깨뜨리고, ID의 선행 0이 사라지며, 큰 CSV는 메모리를 과도하게 잡아먹어 실패하기 쉽습니다. 매번 다시 불러올 때마다 데이터셋에 대한 신뢰가 떨어지고, 모델링이나 리포팅이 계속 지연됩니다.

해결책

목적에 맞게 설계된 R용 reader를 사용하고, 로케일(locale), 구분자(delimiter), 컬럼 타입을 명시적으로 제어하세요. 아래 패턴들을 쓰면, 머신이 달라도 import 속도는 빠르고 타입은 안정적으로 유지되며, 결과를 재현하기 쉬워집니다.

CSV와 TSV: readr 기본값 + 명시적 locale

library(readr)
 
orders <- read_csv(
  "data/orders.csv",
  locale = locale(encoding = "UTF-8", decimal_mark = ".", grouping_mark = ","),
  col_types = cols(
    order_id = col_character(),
    order_date = col_date(format = "%Y-%m-%d"),
    revenue = col_double(),
    region = col_character()
  )
)
  • col_types를 설정해 R이 임의로 factor를 만들거나 ID를 잘라내지 않도록 합니다.
  • 탭 구분 파일에는 read_tsv()를, 세미콜론 구분 파일에는 read_delim(delim = ";")을 사용합니다.

Excel: xls/xlsx용 readxl

library(readxl)
 
budget <- read_excel(
  "data/budget.xlsx",
  sheet = "FY24",
  range = "A1:G200",
  col_types = c("text", "numeric", "numeric", "date", "text", "numeric", "numeric")
)
  • readxl은 Java 설치가 필요 없고, 셀 서식을 비교적 안정적으로 유지합니다.
  • skip =으로 머리글 행을 건너뛰고, range로 필요한 영역만 읽어 속도를 높이세요.

대용량 CSV: data.table::fread

library(data.table)
 
clicks <- fread(
  "data/clicks.csv",
  encoding = "UTF-8",
  colClasses = list(character = "user_id"),
  nThread = 4
)
  • 구분자를 자동으로 감지하지만, 필요하면 sep = "\t" 등으로 덮어쓸 수 있습니다.
  • select =를 써서 필요한 컬럼만 로딩하면 메모리를 크게 아낄 수 있습니다.

열 지향·다국어 데이터: arrow

library(arrow)
 
events <- read_parquet("data/events.parquet", as_data_frame = TRUE)
 
# Or stream a large dataset by batches
ds <- open_dataset("s3://bucket/events/")  # works locally on folders, too
events_summary <- ds %>%
  filter(country %in% c("DE", "FR")) %>%
  group_by(country) %>%
  summarise(count = n())
  • Arrow는 타입을 보존하고, 기본적으로 UTF-8을 처리합니다.
  • Python/SQL 엔진과의 상호 운용, 그리고 메모리에 모두 적재하지 않고(out-of-memory) 필터링할 때 유용합니다.

인코딩과 구분자 다루기

  • 다국어 데이터에는 항상 encoding을 명시하고, 가능하면 전 과정에서 UTF-8을 사용하는 것이 좋습니다.
  • 유럽식 CSV에는 locale(decimal_mark = ",", grouping_mark = ".")를 설정하세요.
  • 구분자가 일정하지 않을 때는 read_delim(..., n_max = 20)으로 일부만 읽어 파싱 결과를 확인해 보세요.

간단 벤치마크 (100만 행, 8개 컬럼, SSD 기준)

Reader파일 유형대략 로딩 시간메모리 사용량비고
data.table::freadCSV약 3–4초낮음평면 파일에서 가장 빠른 편; 타입 추론도 우수.
readr::read_csvCSV약 6–8초낮음–중간파싱 에러를 명확히 보여주며, 로케일 제어가 뛰어남.
arrow::read_parquetParquet약 2–3초낮음열 지향 포맷; 지연 필터링과 다중 파일 데이터셋 지원.
readxl::read_excelXLSX약 8–12초중간업무용 워크북에 적합하지만, 매우 넓은 시트에서는 느릴 수 있음.

측정값은 하드웨어에 따라 달라지므로, 이 표는 상대적인 참고용으로만 사용하세요.

재현 가능한 import 체크리스트

  • col_typescolClasses로 컬럼 타입을 고정합니다.
  • 숨은 문자 깨짐을 막기 위해 localeencoding을 명시합니다.
  • 스키마를 가볍게 유지하세요: import 단계에서 사용하지 않는 컬럼은 바로 제거합니다.
  • 매 로딩 후 nrow()summary()를 기록해, 이상 징후를 초기에 발견합니다.

관련 가이드