국내 공공데이터 API 사용하는 방법 완벽 가이드

국내 공공데이터 API 사용하는 방법 완벽 가이드

들어가며

공공데이터는 정부와 공공기관이 보유한 다양한 정보를 누구나 활용할 수 있도록 개방한 데이터를 말합니다. 우리나라의 공공데이터포털(data.go.kr)에서는 현재 11만 건 이상의 데이터11,499개의 오픈 API를 제공하고 있어, 개발자와 연구자들에게 무료로 활용할 수 있는 풍부한 데이터 자원을 제공합니다.

이 글에서는 공공데이터 API를 처음 사용하는 분들도 쉽게 따라할 수 있도록 회원가입부터 실제 코드 구현까지 모든 과정을 단계별로 상세히 설명하겠습니다.

출처 : 공공데이터 포털

1. 공공데이터포털 이해하기

공공데이터란?

공공데이터란 공공기관이 만들어내는 모든 자료나 정보로, 국민 모두의 소통과 협력을 이끌어내는 공적인 정보를 의미합니다. 각 공공기관이 보유한 데이터를 포털에 등록하면 모두가 공유할 수 있는 양질의 공공데이터로 재탄생하게 됩니다.

주요 제공 데이터 분야

  • 교육: 학교 정보, 교육 통계
  • 환경기상: 날씨 정보, 대기질 데이터
  • 교통물류: 지하철, 버스 운행 정보
  • 부동산: 실거래가, 아파트 정보
  • 보건의료: 병원 정보, 의료 통계
  • 국토관리: 지역 정보, 주소 데이터
  • 재정금융: 정부 예산, 경제 지표

2. 단계별 API 사용 가이드

Step 1: 회원가입 및 로그인

  1. 공공데이터포털(data.go.kr) 접속
  2. 상단 우측 '회원가입' 클릭
  3. 일반회원 또는 기업회원으로 가입 선택
  4. 이메일 인증 완료

Step 2: 원하는 API 검색 및 선택

  1. 메인 페이지 상단 검색창 활용
  2. '오픈API' 필터 체크하여 검색
  3. 카테고리별 검색 (환경기상, 교통물류 등)
  4. 원하는 API 서비스 선택

Step 3: API 인증키 발급

  1. 선택한 API 상세 페이지에서 '활용신청' 버튼 클릭
  2. 활용목적 및 상세내용 작성
  3. 신청 완료 후 1-2시간 대기 (인증키 활성화 시간)
  4. 마이페이지 → 'API 키 발급/관리'에서 확인

중요: 인증키는 '일반인증키(Decoding)'와 '인코딩된 키' 두 가지로 제공됩니다. 대부분의 경우 Decoding된 키를 사용하는 것이 안전합니다.

Step 4: API 테스트

  1. API 상세 페이지에서 '미리보기' 기능 활용
  2. 필수 파라미터 입력
  3. 'OpenAPI 실행' 버튼으로 테스트
  4. 정상 응답 확인 후 URL 복사

3. 실제 코드 예제

Python 예제: 기상청 날씨 데이터

import requests
import json
from urllib.parse import urlencode

def get_weather_data():
    # API 기본 정보
    service_key = "발급받은_인증키"  # Decoding된 키 사용
    base_url = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getUltraSrtNcst"
    
    # 요청 파라미터
    params = {
        'serviceKey': service_key,
        'numOfRows': 10,
        'pageNo': 1,
        'base_date': '20250719',
        'base_time': '0600',
        'nx': 55,
        'ny': 127,
        'dataType': 'JSON'
    }
    
    try:
        response = requests.get(base_url, params=params)
        response.raise_for_status()  # HTTP 에러 체크
        
        data = response.json()
        print("날씨 데이터 조회 성공:")
        print(json.dumps(data, indent=2, ensure_ascii=False))
        
    except requests.exceptions.RequestException as e:
        print(f"API 요청 실패: {e}")
    except json.JSONDecodeError as e:
        print(f"JSON 파싱 실패: {e}")

if __name__ == "__main__":
    get_weather_data()

JavaScript (Node.js) 예제: 대중교통 정보

const axios = require('axios');

async function getBusInfo() {
    const serviceKey = '발급받은_인증키';
    const url = 'http://ws.bus.go.kr/api/rest/buspos/getBusPosByRtid';
    
    const params = {
        serviceKey: serviceKey,
        busRouteId: '100100118',
        resultType: 'json'
    };
    
    try {
        const response = await axios.get(url, { params });
        console.log('버스 위치 정보:', response.data);
    } catch (error) {
        console.error('API 호출 에러:', error.message);
    }
}

getBusInfo();

Java (Spring Boot) 예제: 부동산 데이터

@RestController
public class PublicDataController {
    
    @Value("${public.api.service-key}")
    private String serviceKey;
    
    @GetMapping("/apartment-data")
    public ResponseEntity<String> getApartmentData(
            @RequestParam String locationCode,
            @RequestParam String searchDate) {
        
        String url = "http://openapi.molit.go.kr/OpenAPI_ToolInstallPackage/service/rest/RTMSOBJSvc/getRTMSDataSvcAptTradeDev";
        
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url)
                .queryParam("serviceKey", serviceKey)
                .queryParam("LAWD_CD", locationCode)
                .queryParam("DEAL_YMD", searchDate)
                .queryParam("numOfRows", 100)
                .queryParam("pageNo", 1);
        
        RestTemplate restTemplate = new RestTemplate();
        
        try {
            String response = restTemplate.getForObject(builder.toUriString(), String.class);
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            return ResponseEntity.status(500).body("API 호출 실패: " + e.getMessage());
        }
    }
}

4. 자주 발생하는 문제와 해결방법

🚨 인코딩 문제 해결

증상: "SERVICE_KEY_IS_NOT_REGISTERED_ERROR" 발생

원인: 서비스키가 이중 인코딩되거나 잘못된 형태로 전송

해결방법:

  • Decoding된 서비스키 사용
  • URL 인코딩을 수동으로 처리
  • 프레임워크의 자동 인코딩 기능 비활성화
# Python에서 인코딩 문제 해결
import urllib.parse

# 방법 1: URL 인코딩 비활성화
params_string = f"serviceKey={service_key}&numOfRows=10"
url_with_params = f"{base_url}?{params_string}"

# 방법 2: 수동 인코딩
encoded_key = urllib.parse.quote(service_key, safe='')

🚨 JSON 파싱 문제

증상: 때로는 성공, 때로는 실패하는 불안정한 응답

원인: 에러 발생 시 XML로 응답, 정상 시 JSON으로 응답

해결방법:

def safe_json_parse(response):
    try:
        return response.json()
    except json.JSONDecodeError:
        # XML 응답인 경우 처리
        import xml.etree.ElementTree as ET
        root = ET.fromstring(response.text)
        error_msg = root.find('.//returnReasonCode')
        if error_msg is not None:
            raise Exception(f"API 에러: {error_msg.text}")
        return response.text

🚨 응답 속도 및 안정성 문제

해결방법:

  • 요청 간격 조정 (최소 1초 이상)
  • 타임아웃 설정
  • 재시도 로직 구현
  • 캐싱 활용
import time
from functools import wraps

def retry_on_failure(max_retries=3, delay=1):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_retries - 1:
                        raise e
                    time.sleep(delay * (attempt + 1))
            return None
        return wrapper
    return decorator

@retry_on_failure(max_retries=3, delay=2)
def api_call_with_retry():
    # API 호출 로직
    pass

5. 인기 API 활용 사례

📊 데이터 분석 프로젝트

  • 부동산 시장 분석: 아파트 실거래가 데이터 활용
  • 대기질 모니터링: 미세먼지 데이터로 환경 분석
  • 교통 패턴 분석: 지하철/버스 이용 현황 분석

🔧 실용적인 애플리케이션

  • 날씨 앱: 기상청 날씨 예보 API
  • 부동산 정보 사이트: 실거래가 및 아파트 정보
  • 대중교통 앱: 실시간 버스/지하철 정보
  • 병원 찾기 서비스: 의료기관 정보 API

🎓 교육 및 연구 활용

  • 학술 연구: 정부 통계 데이터 활용
  • 데이터 사이언스 실습: 실제 데이터로 분석 경험
  • 창업 아이디어 검증: 시장 데이터 기반 분석

6. 보안 및 성능 최적화

🔐 보안 고려사항

  • API 키 보호: 환경변수 또는 설정 파일로 관리
  • HTTPS 사용: 가능한 경우 HTTPS 엔드포인트 활용
  • 요청 제한: 일일 호출 제한 확인 및 준수
# 환경변수로 API 키 관리
import os
from dotenv import load_dotenv

load_dotenv()
SERVICE_KEY = os.getenv('PUBLIC_DATA_SERVICE_KEY')

⚡ 성능 최적화

  • 캐싱 전략: Redis 또는 메모리 캐시 활용
  • 배치 처리: 대량 데이터 처리 시 배치 단위로 처리
  • 비동기 처리: 여러 API 동시 호출
# Redis 캐싱 예제
import redis
import json

redis_client = redis.Redis(host='localhost', port=6379, db=0)

def get_cached_data(cache_key, api_func, *args, **kwargs):
    # 캐시에서 데이터 확인
    cached_data = redis_client.get(cache_key)
    if cached_data:
        return json.loads(cached_data)
    
    # 캐시에 없으면 API 호출
    data = api_func(*args, **kwargs)
    
    # 1시간 캐시
    redis_client.setex(cache_key, 3600, json.dumps(data))
    return data

7. 고급 활용 팁

📈 데이터 모니터링

class ApiMonitor:
    def __init__(self):
        self.success_count = 0
        self.error_count = 0
        self.response_times = []
    
    def log_request(self, success, response_time):
        if success:
            self.success_count += 1
        else:
            self.error_count += 1
        self.response_times.append(response_time)
    
    def get_stats(self):
        total_requests = self.success_count + self.error_count
        success_rate = self.success_count / total_requests if total_requests > 0 else 0
        avg_response_time = sum(self.response_times) / len(self.response_times) if self.response_times else 0
        
        return {
            'success_rate': success_rate,
            'total_requests': total_requests,
            'avg_response_time': avg_response_time
        }

🔄 자동화 스크립트

import schedule
import time

def daily_data_collection():
    """매일 정해진 시간에 데이터 수집"""
    try:
        weather_data = get_weather_data()
        save_to_database(weather_data)
        print(f"데이터 수집 완료: {time.strftime('%Y-%m-%d %H:%M:%S')}")
    except Exception as e:
        print(f"데이터 수집 실패: {e}")

# 매일 오전 6시에 실행
schedule.every().day.at("06:00").do(daily_data_collection)

while True:
    schedule.run_pending()
    time.sleep(60)

마무리

공공데이터 API는 정부가 제공하는 신뢰할 수 있는 데이터 자원으로, 다양한 분야의 프로젝트에서 활용할 수 있습니다. 초기 설정과 인코딩 문제만 해결하면 안정적으로 사용할 수 있으며, 무료로 제공되는 만큼 비용 부담 없이 다양한 실험과 개발이 가능합니다.

핵심 포인트 정리:

  • ✅ Decoding된 서비스키 사용으로 인코딩 문제 방지
  • ✅ 에러 처리 로직으로 안정성 확보
  • ✅ 캐싱과 모니터링으로 성능 최적화
  • ✅ 환경변수로 보안 강화
  • ✅ 재시도 로직으로 신뢰성 향상

공공데이터를 활용한 프로젝트를 진행하시면서 궁금한 점이 있으시다면, 공공데이터포털의 고객센터나 개발자 커뮤니티를 통해 도움을 받으실 수 있습니다. 여러분의 창의적인 아이디어와 공공데이터가 만나 더 나은 사회를 만드는 서비스가 탄생하기를 기대합니다!

※ 이미지 출처: Unsplash의 Markus Spiske