smithery.ai

data-skill

본 스킬은 대한민국 공공데이터포털(https://www.data.go.kr/)에서 제공하는 각? 공공데이터 API 를 사용하기 위한 설?

First seen Apr 20, 2026

Installation

$ npx skills add https://smithery.ai

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,611 B
  • docs SUMMARY.md 275 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

대한민국 공공데이터포털 API 스킬

🔥 Center 프로젝트 글 생성/수정/관리 작업 시 필수 확인

⚠️ Center 프로젝트에서 글 관련 작업(생성, 수정, 삭제, 배치 생성 등)을 수행할 때는 반드시 다음 순서로 문서를 확인하세요:

1. [api-spec.md](../center-skill/references/api-spec.md) - API 사용 가이드, 테스트용 토큰, curl 예시
2. [createpost.sh](../center-skill/scripts/createpost.sh) - 단일/배치 게시글 생성 스크립트


1. 개요

대한민국 공공데이터포털(data.go.kr)은 중앙정부, 지자체, 공공기관이 보유한 데이터를 개방·제공하는 공식 플랫폼이다.

주요 특징

  • REST API 기반: HTTP GET/POST 방식 호출
  • 응답 형식: JSON 또는 XML 선택 가능
  • 인증 방식: 서비스키(serviceKey) 기반
  • 무료 제공: 대부분의 API는 무료로 사용 가능

2. 실제 API 응답 구조

중요: 공공데이터포털 API 문서와 실제 응답 구조가 다를 수 있다. 아래는 실제 응답 구조이다.

{
  "response": {
    "header": {
      "resultCode": "0",
      "resultMsg": "정상"
    },
    "body": {
      "dataType": "JSON",
      "items": {
        "item": [
          { /* 실제 데이터 항목 */ }
        ]
      },
      "numOfRows": 10,
      "pageNo": 1,
      "totalCount": 225
    }
  }
}

핵심 포인트

항목 문서 (잘못됨) 실제 응답 (올바름)
결과 코드 resultCode (int) response.header.resultCode (string)
데이터 배열 data[] response.body.items.item[]
총 개수 totalCount response.body.totalCount

에러 코드

코드 메시지 설명
0 OK 정상
-1 시스템 내부 오류 서버 에러
-2 파라미터 부적합 요청 파라미터 오류
-4 등록되지 않은 인증키 인증키 미등록
-10 트래픽 초과 일일 호출 횟수 초과
-401 유효하지 않은 인증키 인증키 오류

3. 제공 스크립트

3.1 외교부 공지사항 API 테스트 (scripts/test-mofa-api.sh)

외교부 공지사항 API를 터미널에서 직접 테스트할 수 있는 쉘 스크립트이다.

사용법

# 스크립트 실행
./scripts/test-mofa-api.sh "<URL_ENCODED_API_KEY>"

# 예시
./scripts/test-mofa-api.sh "FAK7%2BJL3rqrFr7Wtn%2FxkKhW8hq1zDsite%2FxQdIwug4pDLD5bsqFJDKzroRXTkY8fm5LXMMMzIaTuvl%2F4iDtQ%2Bw%3D%3D"

출력 내용

  1. API 요청 정보 (엔드포인트, 파라미터)
  2. HTTP 상태 코드
  3. 결과 코드/메시지
  4. 공지사항 목록 (제목, ID, 작성일)
  5. 원본 JSON 응답 (처음 1500자)

주의사항

  • API Key는 반드시 URL 인코딩된 값을 사용해야 한다
  • 공공데이터포털에서 발급받은 키를 그대로 복사하면 이미 인코딩되어 있음
  • 스크립트 실행 전 실행 권한 필요: chmod +x scripts/test-mofa-api.sh

4. 제공 API 레퍼런스

API 문서 설명
외교부 공지사항 [references/mofa-reminder.md](references/mofa-reminder.md) 출국 전 참고 공지사항 목록 조회

4.1 외교부 공지사항 API 빠른 참조

  • 서비스 URL: http://apis.data.go.kr/1262000/NoticeService2/getNoticeList2
  • HTTP Method: GET
  • 응답 형식: JSON/XML
  • 상세 문서: [references/mofa-reminder.md](references/mofa-reminder.md)

5. Flutter 연동 가이드

Flutter 앱에서 공공데이터 API를 사용하는 방법이다. 본 프로젝트의 lib/services/data/ 디렉토리에 구현되어 있다.

5.1 파일 구조

lib/services/data/
├── data.service.dart      # API 호출 및 캐싱 서비스 (싱글톤)
└── mofa_notice.model.dart # 응답 데이터 모델

5.2 모델 클래스 (mofa_notice.model.dart)

MofaNotice - 개별 공지사항

class MofaNotice {
  final String id;           // 공지사항 ID (예: "ATC0000000048200")
  final String title;        // 제목 (HTML 엔티티 포함)
  final String content;      // 내용 (txt_origin_cn)
  final String writtenDate;  // 작성일 (예: "2025-12-15")
  final String fileUrl;      // 첨부파일 URL (없으면 빈 문자열)

  // HTML 엔티티 디코딩된 제목/내용 반환
  String get decodedTitle => _decodeHtmlEntities(title);
  String get decodedContent => _decodeHtmlEntities(content);
}

MofaNoticeResponse - API 응답 래퍼

class MofaNoticeResponse {
  final String resultCode;   // "0" = 성공
  final String resultMsg;    // 결과 메시지
  final int totalCount;      // 전체 공지사항 수
  final int numOfRows;       // 요청한 개수
  final int pageNo;          // 페이지 번호
  final List<MofaNotice> notices; // 공지사항 목록
  final DateTime fetchedAt;  // 조회 시간

  bool get isSuccess => resultCode == '0';

  // API 응답 파싱 (실제 구조에 맞게)
  factory MofaNoticeResponse.fromApiJson(Map<String, dynamic> json) {
    final response = json['response'];
    final header = response['header'];
    final body = response['body'];
    final items = body['items']['item'] as List;
    // ...
  }
}

5.3 서비스 클래스 (data.service.dart)

싱글톤 패턴으로 구현된 API 서비스이다.

핵심 개념

  1. 싱글톤 패턴: 앱 전체에서 하나의 인스턴스만 사용
  2. 캐시 우선 전략: 캐시 → API 호출 → 캐시 저장
  3. 1시간 TTL: 1시간마다 자동으로 캐시 만료
  4. 이중 캐싱: 메모리 + 파일 캐싱으로 성능 최적화

사용법

import 'package:philgo/services/data/data.service.dart';

// 1. 공지사항 로드 (캐시 우선)
final response = await DataService.instance.loadMofaNotices();

// 2. 성공 여부 확인
if (response.isSuccess) {
  // 3. 공지사항 목록 접근
  for (final notice in response.notices) {
    print('제목: ${notice.decodedTitle}');
    print('날짜: ${notice.writtenDate}');
    print('내용: ${notice.decodedContent}');
  }
}

// 4. 캐시 강제 초기화 (새로고침)
await DataService.instance.clearMofaCache();

// 5. 캐시 남은 시간 확인
final remaining = DataService.instance.mofaCacheRemainingTime;

주요 구현 코드

class DataService {
  static DataService? _instance;
  static DataService get instance => _instance ??= DataService._();

  // API Key (이미 URL 인코딩됨)
  static const String apiKey = AppConfig.dataApiKey;

  // 1시간 캐시 TTL
  static const Duration _mofaCacheTtl = Duration(hours: 1);

  // FileCache 사용 (메모리 + 파일 이중 캐싱)
  late final FileCache<MofaNoticeResponse> _mofaCache = FileCache(
    cacheName: 'mofa_notices',
    defaultTtl: _mofaCacheTtl,
    fromJson: MofaNoticeResponse.fromJson,
    toJson: (data) => data.toJson(),
    useMemoryCache: true,
  );

  Future<MofaNoticeResponse> loadMofaNotices() async {
    // 1. 캐시 확인
    final cached = await _mofaCache.get('mofa_notices');
    if (cached != null) return cached;

    // 2. API 호출
    final response = await http.get(Uri.parse(
      '$_mofaApiBaseUrl?serviceKey=$apiKey&returnType=JSON&numOfRows=5&pageNo=1'
    ));

    // 3. UTF-8 디코딩 (한글 깨짐 방지)
    final json = jsonDecode(utf8.decode(response.bodyBytes));

    // 4. 실제 응답 구조에 맞게 파싱
    final data = MofaNoticeResponse.fromApiJson(json);

    // 5. 캐시 저장
    await _mofaCache.set('mofa_notices', data);

    return data;
  }
}

5.4 UI 연동 예시

class _NoticeScreenState extends State<NoticeScreen> {
  bool _isLoading = true;
  MofaNoticeResponse? _response;

  @override
  void initState() {
    super.initState();
    _loadNotices();
  }

  Future<void> _loadNotices() async {
    final response = await DataService.instance.loadMofaNotices();
    setState(() {
      _response = response;
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) {
      return CircularProgressIndicator();
    }

    if (!_response!.isSuccess) {
      return Text('에러: ${_response!.resultMsg}');
    }

    return ListView.builder(
      itemCount: _response!.notices.length,
      itemBuilder: (context, index) {
        final notice = _response!.notices[index];
        return ListTile(
          title: Text(notice.decodedTitle),
          subtitle: Text(notice.writtenDate),
          onTap: () => _showDetail(notice),
        );
      },
    );
  }
}

6. 개발 시 주의사항

  1. 인증키 보안: 인증키를 소스코드에 직접 하드코딩하지 말고 환경변수나 설정 파일로 관리
  2. URL Encode: serviceKey는 반드시 URL Encode 처리
  3. 응답 구조 확인: 문서와 실제 응답 구조가 다를 수 있으므로 반드시 실제 응답 확인
  4. UTF-8 디코딩: 한글 깨짐 방지를 위해 utf8.decode(response.bodyBytes) 사용
  5. HTML 엔티티 디코딩: 제목/내용에 &#39;, &nbsp; 등이 포함될 수 있음
  6. 캐싱: 동일한 데이터를 반복 조회할 경우 캐싱 적용 권장