DART Open API 사용

FMB819: R을 이용한 데이터분석

고려대학교 경영대학 정지웅

API(Application Programming Interface) 개요

  • 금융 데이터 분석에서 API는 데이터 소스(금융감독원 DART)와 사용자(분석가) 사이의 규약된 통로. 웹 브라우저에서 눈으로 데이터를 확인하는 대신, 프로그래밍 코드를 통해 필요한 데이터만 직접 요청하고 구조화된 형태로 받을 수 있음.

API의 핵심 요소

  • Endpoint (URL): 데이터가 저장된 주소 (예: https://opendart.fss.or.kr/api/...)
  • Authentication (인증키): 허가된 사용자임을 증명하는 고유 Key.
  • Request Parameters (요청 인자): 수집하고 싶은 데이터의 조건 (기업코드, 기간, 보고서 종류 등).
  • Response (응답 데이터): 서버가 돌려주는 데이터로, 주로 JSON 또는 XML 형식을 사용합니다.

DART Open API의 특징과 체계

  • 금융감독원 전자공시시스템(DART)은 상장법인 등의 공시 서류를 제공. Open API를 사용하면 수천 개 기업의 데이터를 반복적으로 수집하는 과정을 자동화할 수 있음.

주요 제공 데이터 (API 그룹)

  1. 공시 검색 (DS001): 특정 기간 내 발생한 공시 목록 조회.
  2. 기업 개황 (기업 정보): 업종, 주소, 상장 여부 등 기본 정보.
  3. 상장기업 재무정보: 주요 재무제표 항목.
  4. 단일회사 전체 재무제표: 특정 시점의 전체 재무제표(XBRL 데이터 포함).
  5. 사업보고서 주요 정보: 배당, 최대주주 현황, 임원 연봉 등.

사전 준비 및 인증키 설정

  1. API Key를 .Renviron 파일에 추가. 다음 명령을 실행
file.edit("~/.Renviron")
  1. DART_API_KEY="발급받은_키_번호"을 적어서 저장.
    • 윈도우에서는 일반적으로 "C:\Users\[사용자명]\Documents\.Renviron" 에 저장이 됨.
    • 이름이 .으로 시작하는 파일은 윈도우나 맥 탐색기에서 기본적으로 숨겨져(Hidden) 있음.
  2. 파일을 저장한 뒤 R을 재시작
    • .Renviron 파일은 R이 시작될 때 딱 한 번 읽어옴
  3. 인증키 불러오기
dart_api_key <- Sys.getenv("DART_API_KEY")

사전 준비 및 인증키 설정

# 필요한 R 패키지 로드
library(httr)
library(jsonlite)
library(xml2)
library(stringr)
library(dplyr)

# API 인증키 설정
dart_api_key <- Sys.getenv("DART_API_KEY")
  • “이 패키지들은 하나의 조립 라인(Assembly Line)과 같음”
    • httr로 원재료(데이터)를 가져오고, xml2/jsonlite로 포장을 뜯고, rvest로 알맹이를 골라내며, stringr로 예쁘게 다듬어 최종 데이터프레임을 만듬.

필요 패키지

  1. library(httr): 데이터 운반 (HTTP Request)
    • R과 DART 서버 사이의 통신을 담당.
    • “이 URL로 데이터를 보내줘”라고 요청하는 GET() 함수를 제공. 브라우저 주소창에 주소를 치고 엔터를 누르는 행위를 코드로 대신해 주는 도구.
  2. library(xml2): 데이터 추출 (Scraping/Harvesting)
    • 웹페이지나 XML 문서에서 필요한 정보만 골라내기 위해 사용.
    • DART에서 받은 XML 파일 안에는 수많은 태그들이 섞여 있음. 이 중 우리가 원하는 corp_code나 stock_code 같은 특정 항목만 집어낼 때(xml_find_all, xml_text) 필수적.
  3. library(jsonlite): 데이터 해석 (JSON Parsing)
    • 서버로부터 받은 JSON 형식의 텍스트를 R 객체로 변환.
    • 최근 대부분의 현대적 API(DART 포함)는 데이터를 JSON 형태로 응답. fromJSON() 함수 한 줄이면 복잡한 텍스트 뭉치를 R에서 바로 분석 가능한 데이터프레임으로 바꿔줌.
  4. library(stringr): 데이터 정제 (String Manipulation)
    • 텍스트 데이터의 가공과 수정을 담당.
    • 금융 데이터 분석에서 가장 빈번한 오류 중 하나가 0으로 시작하는 종목코드 처리. (예: 삼성전자 ’005930’이 ’5930’으로 읽히는 경우). str_pad() 함수 등을 사용하여 자릿수를 맞추거나, URL 주소 문자열을 깔끔하게 조립할 때 매우 유용.

실습: 기업 고유번호(Corp Code) 수집

  • DART API는 주식 시장의 ‘종목코드(6자리)’ 대신 자체적인 ‘고유번호(8자리)’를 사용. 따라서 종목코드와 고유번호를 매칭하는 과정이 선행되어야.

  • 고유번호 파일 다운로드 및 파싱

    • DART는 모든 기업의 고유번호를 하나의 ZIP 파일(XML 포함) 형태로 제공.
  • https://opendart.fss.or.kr/guide/detail.do?apiGrpCd=DS001&apiId=2019018

# 1. 고유번호 파일 요청 URL
codezip_url <- paste0('https://opendart.fss.or.kr/api/corpCode.xml?crtfc_key=', dart_api_key)

# 2. 데이터 다운로드
response <- GET(codezip_url)

# 3. 데이터 수령 -> 저장 -> 압축 해제 -> 내용 판독
tf <- tempfile(fileext = '.zip')
writeBin(content(response, as = "raw"), tf)

# 압축 파일 내의 파일 목록 확인
nm <- unzip(tf, list = TRUE)

# 임시 폴더(tempdir)에 압축 해제하여 작업 공간 오염 방지
extracted_file <- unzip(tf, files = nm$Name[1], exdir = tempdir())

# XML 읽기
code_data <- read_xml(extracted_file)

# 4. 데이터프레임 변환
corp_code <- code_data %>% xml_find_all('//corp_code') %>% xml_text()
corp_name <- code_data %>% xml_find_all('//corp_name') %>% xml_text()
stock_code <- code_data %>% xml_find_all('//stock_code') %>% xml_text()

corp_list <- data.frame(
  code = corp_code,
  name = corp_name,
  stock = stock_code,
  stringsAsFactors = FALSE
)

# 상장사(stock_code가 6자리인 기업)만 필터링 (공백 문자가 들어올 수 있으므로 trimws())
corp_list_listed <- subset(corp_list, nchar(trimws(stock)) == 6)

# 5. 메모리 정리 (임시 파일 삭제)
unlink(tf)
unlink(extracted_file)

# 6. 결과 확인
head(corp_list_listed)

명령어 의미

  1. tf <- tempfile(fileext = '.zip')
    • 임시 저장 공간(빈 상자) 만들기
    • 컴퓨터에 데이터를 잠시 보관할 임시 파일 경로를 생성. 이름이 .zip으로 끝나는 일회용 빈 상자를 하나 준비하는 것과 같음. 작업 폴더를 지저분하게 만들지 않고 메모리 효율을 높이기 위해 사용.
  2. writeBin(content(response, as = "raw"), tf)
    • 받은 데이터를 상자에 담기
    • DART 서버에서 보내준 원시 이진 데이터(Raw Binary)를 위에서 만든 임시 파일(tf)에 실제로 저장. API로부터 받은 “디지털 택배물”을 상자에 물리적으로 채워 넣는 단계.
  3. nm <- unzip(tf, list = TRUE)
    • 압축 파일 내부 명단(송장) 확인
    • 압축을 실제로 풀기 전에, 그 안에 어떤 파일들이 들어있는지 목록만 확인. DART 고유번호 ZIP 파일 안에는 보통 CORPCODE.xml이라는 파일이 들어있는데, 이 파일의 이름을 정확히 알아내기 위해 사용.
  4. code_data <- read_xml(unzip(tf, nm$Name, exdir = tempdir()))
    • 내용물 꺼내서 읽기
    • unzip(tf, nm$Name, exdir = tempdir()): 상자 안에서 실제 데이터 파일(CORPCODE.xml)만 압축을 풀어 꺼냄. 임시폴더에 저장
    • read_xml(...): 꺼낸 XML 파일을 R이 읽을 수 있는 구조화된 데이터 객체로 변환.

명령어 의미

  1. xml_find_all('태그이름'):
    • 수많은 데이터 중 특정 이름표(태그)가 붙은 것들만 하이라이트.
    • 거대한 엑셀 시트에서 특정 열(Column) 전체를 마우스로 드래그하는 것과 같음.
  2. xml_text():
    • 하이라이트 된 부분에서 <tag>...</tag> 같은 XML 문법 기호는 버리고, 그 안의 순수한 글자만 추출.
    • 귤 껍질(태그)을 까서 알맹이(텍스트)만 남기는 과정.

실습: 재무제표 데이터 추출

  • 특정 기업의 재무 상태를 분석하기 위해 ‘상장기업 재무정보’ API를 활용하여 주요 항목을 가져옴.

  • 주요 요청 인자 (Parameters):

    • bsns_year: 사업연도 (예: 2023)
    • reprt_code: 보고서 코드 (1분기: 11013, 반기: 11012, 3분기: 11014, 사업보고서: 11011)
  • https://opendart.fss.or.kr/guide/detail.do?apiGrpCd=DS003&apiId=2019016

# 삼성전자(고유번호: 00126380)의 2023년 사업보고서 재무제표 요청
target_corp <- "00126380"
# 수정 후:
url <- paste0("https://opendart.fss.or.kr/api/fnlttSinglAcnt.json?",
              "crtfc_key=", dart_api_key,
              "&corp_code=", target_corp,
              "&bsns_year=2023",
              "&reprt_code=11011")

# JSON 데이터 수집 및 변환
data_json <- fromJSON(url)
financial_table <- data_json$list

# 주요 항목 확인 (자산총계, 매출액, 당기순이익 등)
financial_table[, c("account_nm", "fs_nm", "thstrm_nm", "thstrm_amount")]

THE END