--- title: "DART Open API 사용" subtitle: "FMB819: R을 이용한 데이터분석" author: "고려대학교 경영대학 정지웅" format: revealjs: theme: simple transition: fade transition-speed: fast scrollable: true chalkboard: true slide-number: true revealjs-plugins: - revealjs-text-resizer # Thanks to https://github.com/gadenbuie/revealjs-text-resizer#readme --- ```{r setup, include = FALSE, warning = FALSE, message = FALSE} options(htmltools.dir.version = FALSE) knitr::opts_chunk$set( message = FALSE, warning = FALSE, dev = "svg", cache = TRUE, fig.align = "center", comment = "##" #fig.width = 11, #fig.height = 5 ) # Load packages library(tidyverse) library(pander) library(ggthemes) library(gapminder) library(countdown) library(xaringanExtra) ``` ## 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. **사업보고서 주요 정보**: 배당, 최대주주 현황, 임원 연봉 등. --- ## 사전 준비 및 인증키 설정 - DART 데이터를 받기 위해서는 [DART Open API 홈페이지](https://opendart.fss.or.kr/)에서 인증키(API Key)를 발급받아야 함. 1. API Key를 `.Renviron` 파일에 추가. 다음 명령을 실행 ```r file.edit("~/.Renviron") ``` 2. `DART_API_KEY="발급받은_키_번호"`을 적어서 저장. - 윈도우에서는 일반적으로 `"C:\Users\[사용자명]\Documents\.Renviron"` 에 저장이 됨. - 이름이 `.`으로 시작하는 파일은 윈도우나 맥 탐색기에서 기본적으로 숨겨져(Hidden) 있음. 3. 파일을 저장한 뒤 R을 재시작 - `.Renviron` 파일은 R이 시작될 때 딱 한 번 읽어옴 4. 인증키 불러오기 ```r dart_api_key <- Sys.getenv("DART_API_KEY") ``` --- ## 사전 준비 및 인증키 설정 ```{r} #| label: dart-setup #| eval: False #| echo: True # 필요한 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`로 예쁘게 다듬어 최종 데이터프레임을 만듬. --- ## 필요 패키지 {background-color="#ebf8ff"} 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](https://opendart.fss.or.kr/guide/detail.do?apiGrpCd=DS001&apiId=2019018) ```{r} #| label: get-corp-code #| eval: False #| echo: True # 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) ``` --- ## 명령어 의미 {background-color="#ebf8ff"} 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이 읽을 수 있는 구조화된 데이터 객체로 변환. --- ## 명령어 의미 {background-color="#ebf8ff"} 1. `xml_find_all('태그이름')`: - 수많은 데이터 중 특정 이름표(태그)가 붙은 것들만 하이라이트. - 거대한 엑셀 시트에서 특정 열(Column) 전체를 마우스로 드래그하는 것과 같음. 2. `xml_text()`: - 하이라이트 된 부분에서 `...` 같은 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](https://opendart.fss.or.kr/guide/detail.do?apiGrpCd=DS003&apiId=2019016) ```{r} #| label: get-financial-data #| eval: False #| echo: True # 삼성전자(고유번호: 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