본문으로 건너뛰기
취준생을 위한 n8n 실전 워크플로우 레시피 · 19/44시리즈 보기 →

공공데이터를 대시보드까지 — 중대재해 사고 현황을 n8n으로 모아 Tableau에 연결하기

· 약 11분
Datapopcorn CEO / AI automation educator
이 글과 연결된 글 보기
7편 · 20개 연결
100%
n8n Data Table 처음 써보기 — 트렌드 3개를 합쳐 매일 아침 분석 주제 뽑는 워크플로우n8n으로 정적 웹서버 운영하기 — 수료증 발급부터 진위 확인까지, 멱등 처리로 안전하게벡터DB 없이 실시간으로 사이트를 읽는 챗봇 — 경복대학교 안내 챗봇 해부n8n으로 반복업무 자동화 포트폴리오 만들기공공데이터를 대시보드까지 — 중대재해 사고 현황을 n8n으로 모아 Tableau에 연결하기구글시트에 쌓인 데이터를 인스타그램 카드뉴스로 — n8n 시트 인스타그램 자동발행서브워크플로우를 Tool로 감싸 AI Agent에게 서버 점검시키기 — 그리고 시스템 프롬프트만으로는 부족한 이유

드래그로 이동 · 휠/두 손가락으로 확대 · 방향키로 글 선택 · 0으로 맞춤. 실선: 본문 링크, 점선: 시리즈·주제의 대표 연결.

표시된 글 7편 목록
전체 글 연결 탐색

공공데이터포털의 사고사망 게시판 API를 n8n으로 매일 긁어, HTML이 섞인 속보 문장을 사건번호·일시·위치·사고현장·사망원인 컬럼으로 정리해 구글시트에 쌓아 두면, 그 시트를 Tableau나 무료 Data Studio에 연결하는 것만으로 "이번 달 사망원인별 사고 건수" 같은 대시보드가 나옵니다. 이 편을 따라 하면 API 한 번 부르는 수준에서 끝나던 공공데이터 워크플로우가 수집 → 전처리 → 저장 → BI 연결이라는 파이프라인 한 벌로 확장됩니다.

이 워크플로우 하나로 보여줄 수 있는 것​

응급실 API 편이 "공공데이터를 시트에 쌓는다"였다면, 이 편은 "쌓은 데이터를 사람이 보는 화면까지 보낸다"입니다. 원본 캔버스에는 스티키 노트로 1. 데이터 수집(API), 2. 데이터 전처리, 3. 데이터 저장, 4. 데이터 분석, 5. 리포트라는 다섯 구역이 그려져 있는데, 이 구역 나누기 자체가 면접에서 설명할 수 있는 역량입니다.

  • API 수집을 운영 수준으로 — 키를 credential에 넣고, 페이지네이션을 n8n에 맡기고, 호출 간격을 두는 설계
  • 비정형 텍스트를 컬럼으로 — HTML 태그가 섞인 속보 문장을 전처리하고 AI로 정해진 스키마에 맞춰 뽑는 경험
  • 저장소와 BI 도구의 역할 분리 — 워크플로우는 시트·S3까지만 책임지고, 시각화는 BI 도구가 시트를 읽게 하는 구조

세 번째가 이 편의 핵심입니다. 대시보드를 만드는 건 BI 도구지만, 대시보드가 매일 새 데이터를 보여주게 하는 건 그 앞의 파이프라인입니다. 이 구분을 알고 만든 사람은 "Tableau 써봤어요"가 아니라 "대시보드에 데이터가 들어오는 길을 만들어 봤어요"라고 말할 수 있습니다.

배경 — 게시판 글은 있는데 차트는 없는 데이터​

한국산업안전보건공단은 사고사망 속보를 게시판으로 공개하고, 공공데이터포털은 이 게시판을 API로 열어 두었습니다. 원본 캔버스 맨 위 스티키 노트에도 "한국산업안전보건공단 홈페이지에서 제공 중인 사고사망 게시판 정보를 실시간으로 조회할 수 있도록 제공하는 데이터"라고 출처가 적혀 있습니다. 문제는 이 API가 돌려주는 게 표가 아니라 게시글이라는 점입니다. 사건번호와 키워드, 그리고 HTML 태그가 섞인 본문 한 덩어리가 오는데, 본문 안에 날짜·지역·사고 유형이 문장으로 들어 있습니다. 이 상태로는 어떤 BI 도구에 넣어도 차트가 그려지지 않습니다.

이 워크플로우는 그 게시글을 매일 받아 컬럼으로 정리하고 시트에 쌓아, 대시보드가 읽을 수 있는 표를 만드는 데이터팝콘의 교육용 워크플로우입니다. 응급실 API 편에서 쓴 공공데이터포털 키를 그대로 쓰고, 따릉이 편에서 다룬 S3 적재가 저장 단계에 한 번 더 나옵니다. 설치나 기본 노드 설명은 n8n으로 반복업무 자동화 포트폴리오 만들기에 있으니 이 글은 파이프라인 자체만 다룹니다.

구조 — Trigger / Task / Target​

  • Trigger — 매일 한 번 도는 스케줄. 옆에 Manual Trigger가 같은 HTTP 노드로 연결돼 있어 테스트는 버튼으로 합니다
  • Task — 페이지네이션 수집 → 게시글 배열 분리 → HTML 제거 → AI 추출 → 평탄화·필터·정렬
  • Target — 구글시트(Append)와 S3, 그리고 시트를 읽는 BI 도구

점선으로 그린 마지막 칸이 이 편의 주제입니다. n8n에는 Tableau 노드가 없고, 원본 캔버스의 "Tableau"라는 노드도 아무 일도 하지 않는 No Operation 노드에 대시보드 주소를 핀으로 붙여 둔 자리표시자입니다. BI 연결은 워크플로우 밖에서 일어납니다.

만들기​

1. Schedule Trigger — 매일 한 번​

Schedule Trigger는 기본 설정(Days, 1일 간격)입니다. 핀으로 남아 있는 테스트 데이터의 시각이 자정 직후인 걸 보면 매일 자정에 도는 걸 상정한 구성입니다. 게시판 속보는 하루에 몇 건 수준이라 그보다 자주 돌 이유가 없습니다.

2. HTTP Request — 키는 credential에, 페이지 넘김은 n8n에​

캔버스에는 HTTP Request 노드가 두 개 있습니다. 하나는 "HTTP Request(Before)"라는 이름으로 본 흐름에서 떨어져 있고, 실제로 연결된 건 "HTTP Request(After)"입니다. 두 노드의 차이가 이 단계에서 배울 것 전부입니다.

Before 버전은 Query Parameters에 API 키를 값으로 직접 적고, pageNo=1, numOfRows=1000으로 한 번에 1,000건을 요청합니다. 동작은 하지만 워크플로우를 export하는 순간 키가 JSON 파일에 그대로 남습니다. 실제로 이 원본 export에도 남아 있어서 글에 옮기지 않았습니다. After 버전은 이렇게 바뀌었습니다.

  • URL: https://apis.data.go.kr/B552468/news_api01/getNews_api01
  • Authentication: Generic Credential Type → Query Auth. credential에 Name serviceKey, Value에 발급받은 키를 넣습니다
  • Query Parameters: numOfRows = 100
  • Headers: accept = */*
  • Options → Pagination: Update a Parameter in Each Request, Name pageNo, Value {{ $pageCount + 1 }}, Max Pages 10, Interval Between Requests 5000ms

즉 100건씩 최대 10페이지를 5초 간격으로 받아옵니다. 공공데이터포털 개발계정은 이 API의 일 트래픽이 1,000건(2026년 8월 기준)이라 하루 10회 호출은 넉넉합니다. $pageCount는 n8n이 페이지네이션 중에만 채워 주는 변수로 0부터 시작하기 때문에 + 1을 붙여야 첫 페이지가 1이 됩니다.

3. Split Out + Set — 게시글 배열을 풀고 HTML을 벗기기​

API 응답은 body.items.item 아래에 게시글 배열이 들어 있습니다. Split Out 노드의 Field To Split Out에 body.items.item을 넣으면 게시글 하나가 아이템 하나가 됩니다.

다음은 "데이터 전처리"라는 이름의 Edit Fields(Set) 노드입니다. 스티키 노트로 "2. 데이터 전처리" 구역의 첫 노드인데, 하는 일은 필드 세 개를 다시 쓰는 것뿐입니다.

  • arno = {{ $json.arno }} (사건번호)
  • keyword = {{ $json.keyword }}
  • contents = {{ $json.contents.removeTags().replaceAll(' ','').trim() }}

세 번째 줄이 전처리의 실체입니다. 게시판 본문은 태그와  가 섞인 HTML로 오기 때문에, n8n의 문자열 확장 함수 removeTags()로 태그를 지우고  를 빈 문자열로 바꾼 뒤 앞뒤 공백을 정리합니다. Code 노드 없이 표현식 한 줄로 끝나는 전처리이고, 이 줄을 빼고 AI에 넣으면 태그까지 추출 결과에 딸려 들어옵니다.

4. Limit + Information Extractor — 속보 문장을 6개 컬럼으로​

Set 뒤에는 Limit 노드가 Max Items 10으로 걸려 있습니다. 최대 1,000건을 그대로 LLM에 넣지 않도록 막는 안전장치라, 테스트가 끝나고 전체를 처리하려면 이 값을 늘리거나 노드를 빼야 합니다.

Information Extractor 노드에는 Google Gemini Chat Model(gemini-2.0-flash-lite-001)이 붙어 있습니다. 캔버스에 OpenAI와 OpenRouter 모델 노드도 떠 있지만 연결돼 있지 않아서, 실제로 쓰인 건 Gemini입니다. Text에는 이렇게 들어 있습니다.

INPUT)
사건번호 : {{ $json.arno }}
키워드 : {{ $json.keyword }}
콘텐츠 : {{ $json.contents }}
---
OUTPUT)
사건번호, 날짜시간, 위치(시도 시군구 읍면동 단위까지), 사고현장, 사망원인(넘어짐, 깔림, 뒤집힘, 끼임, 떨어짐, 부딪힘, 감전, 물체에 맞음 등), 원본텍스트

으로 JSON 형태로 코드블럭 없이 값만 추출해 줘.
---
OUTPUT 예시)
455705, 2024-04-13 11:00:00, 경기도 용인시, 공장 지붕 보수 공사현장, 떨어짐, 사망사고 속보] …(원문 생략)

Schema Type은 Define Below(JSON)로 두고 arno, datetime, location, accident_space, cause_of_death, original_text 여섯 속성을 정의했습니다. datetime에는 YYYY-MM-DD HH:MM:SS 형식의 정규식 패턴과 설명이 붙어 있어서, 속보 본문의 "2024. 12. 25. (수), 09:36경" 같은 표기가 정렬 가능한 문자열로 바뀝니다. 사망원인을 자유 서술이 아니라 "떨어짐, 끼임, 감전…" 같은 분류 목록으로 프롬프트에 박아 둔 것도 대시보드를 염두에 둔 선택입니다. 값이 흩어지면 막대그래프가 안 그려집니다.

5. Set → Filter → Sort — 대시보드가 먹기 좋은 형태로​

Information Extractor의 결과는 output 필드 아래에 들어옵니다. "필요한 요소만 추출" Set 노드에서 {{ $json.output.arno }}부터 {{ $json.output.original_text }}까지 여섯 개를 최상위 필드로 끌어올립니다. 시트 헤더와 이름이 같아야 다음 단계의 자동 매핑이 붙기 때문입니다.

"날짜가 있는 것만 추출" Filter 노드는 {{ $json.datetime }}이 비어 있지 않은 행만 통과시킵니다. AI가 날짜를 못 찾은 행은 시간축이 없는 데이터라 대시보드에서 쓸 수 없으니 여기서 걸러냅니다. 마지막 Sort 노드는 datetime 기준으로 정렬합니다.

6. Google Sheets + AWS S3 — 저장은 두 갈래​

Sort 노드의 출력이 Google Sheets와 AWS S3 두 노드로 동시에 나갑니다. Google Sheets는 Operation Append, Mapping Column Mode는 Map Automatically이고, 시트 헤더는 위의 여섯 필드 이름과 같습니다. 인증은 OAuth가 아니라 서비스 계정입니다. 매일 사람 없이 도는 워크플로우에서는 토큰 만료 걱정이 없는 서비스 계정이 편합니다.

AWS S3 노드는 Operation Upload에 버킷 이름이 bucket이고 파일명과 바이너리 입력이 비어 있는 뼈대 상태입니다. 따릉이 편처럼 실제로 올리려면 앞에 Convert to File 노드로 CSV를 만들고 파일명을 지정해야 합니다. 이 캔버스에서 실제로 채워져 있는 저장 경로는 구글시트 쪽이고, 다음 단계의 BI 연결도 시트를 기준으로 설명합니다.

7. BI 연결 — Tableau, 그리고 무료 대안​

원본의 Tableau 노드에 핀으로 붙은 주소는 Tableau Public 대시보드였습니다. 즉 이 파이프라인의 끝은 유료 Tableau가 아니라 무료 버전이었고, 취준생이 따라 만들 때도 같은 선택지가 열려 있습니다. 2026년 8월 기준으로 정리하면 이렇습니다.

  • Tableau Cloud — 공식 가격은 Standard 기준 Creator 월 75달러, Explorer 42달러, Viewer 15달러(연간 결제). 대시보드를 직접 만들려면 Creator가 필요합니다
  • Tableau Public — 무료이지만 올린 데이터와 대시보드가 전부 공개됩니다. 이 글의 데이터는 애초에 공공데이터라 문제없지만, 회사 데이터에는 쓸 수 없습니다. 한 가지 더, Tableau의 Google Sheets 커넥터는 2023년 중반에 폐기돼 Google Drive 경유를 안내하고 있으니, 시트를 붙이기 전에 쓰는 에디션에서 어떤 경로가 열려 있는지 확인해야 합니다
  • Data Studio(구 Looker Studio) — 2026년 4월 Looker Studio에서 이름이 돌아온 구글의 무료 도구로, Google Sheets 커넥터가 기본 제공됩니다. 시트 하나를 데이터 소스로 잡고 cause_of_death를 차원, 행 수를 측정값으로 두면 사망원인별 건수 막대가 바로 나옵니다

취준생에게 권하는 경로는 세 번째입니다. 워크플로우가 구글시트에 쌓기만 하면 Data Studio는 시트를 열 때마다 새 행을 읽어 오므로, "매일 갱신되는 대시보드"를 추가 비용 없이 포트폴리오에 넣을 수 있습니다. Tableau를 이력서에 쓰고 싶다면 같은 시트를 Tableau Public에 한 번 더 올리면 됩니다. 어느 쪽이든 워크플로우는 손대지 않습니다.

원본 캔버스에 남아 있는 흔적 — MCP 서버 분기​

이 워크플로우는 교육용이라 실행 로그 같은 운영 데이터는 없습니다. 대신 캔버스 아래쪽에 본 흐름과 별개로 "4. 데이터 분석"과 "5. 리포트" 구역, 그리고 "MCP Server" 스티키 아래 MCP Server Trigger가 하나 더 있습니다. Trigger에는 시트를 읽는 Google Sheets Tool과 다른 워크플로우를 부르는 Call n8n Workflow Tool이 붙어 있어서, 외부 AI 클라이언트가 "이번 달 떨어짐 사고 몇 건이야?"라고 물으면 같은 시트를 읽어 답하게 하려는 확장입니다. 분석 구역의 AI Agent 뒤에 붙은 Gmail·Slack 노드는 본문이 "Hello"인 자리표시자라 아직 완성된 건 아닙니다. 같은 데이터를 대시보드로도 보고 에이전트에게 물어볼 수도 있게 만든 것인데, MCP 서버 자체는 Tier 4에서 별도 편으로 다룹니다.

한계​

  • 중복 적재 — 매일 최대 10페이지를 다시 받아 Append하므로 어제 넣은 사건이 오늘 또 들어갑니다. Append 대신 Append or Update에 arno를 매칭 컬럼으로 두거나, 시트를 먼저 읽어 이미 있는 arno를 제외하는 단계가 필요합니다. 원본에도 Remove Duplicates 노드가 있지만 분석 분기 쪽에만 있습니다
  • Limit 10 — 위에서 말한 대로 하루 10건까지만 처리됩니다. 값을 늘리면 그만큼 LLM 호출이 늘어나니 Gemini 무료 할당량을 보고 정해야 합니다
  • 날짜 없는 행은 버려짐 — Filter가 날짜 없는 행을 제외하므로, AI가 날짜 추출에 실패한 사고는 대시보드에서 사라집니다. 얼마나 버려지는지 세어 보려면 Filter의 Kept/Discarded 출력을 둘 다 시트에 남기는 편이 안전합니다
  • 프롬프트 예시의 어긋남 — OUTPUT 예시의 날짜시간이 2024-04-13인데 그 뒤의 원문에는 2024. 12. 25.가 적혀 있습니다. 예시 하나가 모델의 출력 형식을 정하는 만큼, 따라 만들 때는 예시의 값을 원문과 맞춰 두세요
  • S3 미완성 — 6단계에서 본 대로 S3 노드는 설정이 비어 있습니다. 시트 대신 CSV 파일을 BI 도구에 주고 싶을 때만 채우면 됩니다

포트폴리오·면접 포인트​

포트폴리오에는 워크플로우 캔버스, 쌓인 시트, 대시보드 화면 세 장을 나란히 두면 "데이터가 흐르는 길"이 한눈에 보입니다. 여기에 응용 하나를 더하면 좋습니다. 같은 구조에서 API만 바꾸면 되기 때문입니다. 공공데이터포털에는 텍스트 게시판 형태의 API가 많고, 그중 하나를 골라 스키마를 직접 설계해 본 버전이 이 글을 그대로 따라 한 것보다 훨씬 강한 포트폴리오가 됩니다.

면접에서 "왜 AI 추출을 시트에 넣기 전에 했나요, Tableau에서 계산하면 안 되나요?"라는 질문이 올 수 있습니다. 답은 BI 도구는 컬럼이 있는 표를 그리는 도구이지 문장에서 컬럼을 만드는 도구가 아니라는 것, 그리고 컬럼을 만드는 일을 워크플로우에 두면 대시보드 도구를 바꿔도 파이프라인은 그대로라는 것입니다. 여기에 "키를 credential로 옮긴 이유"와 "사망원인을 분류 목록으로 고정한 이유"를 덧붙이면 운영과 시각화를 둘 다 생각한 사람으로 보입니다.

다음 액션​

데이터 수집 편은 여기까지입니다. 다음 편부터는 AI 활용으로 넘어가는데, 첫 글은 명함 사진을 드라이브에 올리면 OCR로 글자를 읽고 이름·직함·이메일로 나눠 시트에 정리하는 워크플로우입니다. 이 편의 Information Extractor가 문장에서 컬럼을 뽑았다면, 다음 편은 사진에서 문장을 뽑는 단계가 하나 더 앞에 붙습니다. "비정형 입력을 정형 데이터로" 바꾸는 뼈대는 같습니다.