HowtoAI
ai-automation2026-08-05 5 min read

업무 자동화에서 공휴일 빼는 법 — 대체공휴일까지 잡는 공공데이터 특일정보 API 연동 5단계

🤖
HowtoAI 편집팀AI 전문 에디터

AI 기술을 누구나 쉽게 활용할 수 있도록 실전 가이드를 작성합니다. ChatGPT, Claude, AI 자동화, SEO 분야를 전문으로 다룹니다.

📅 2026-08-05⏱️ 5 min read🌐 how-toai.com
목차 보기

매일 아침에 도는 자동화를 만들어 두면 처음 몇 주는 기분이 좋아요. 그러다 어느 날 아침, 쉬는 날인데 보고 메일이 날아오고 팀 채널에 일일 집계가 올라오고 담당자 호출이 나가요. 받는 사람도 당황하고 만든 사람도 민망해져요.

결론부터 말할게요. 이건 실행 주기를 잘못 잡아서 생긴 문제가 아니에요. 주기는 얼마나 자주 확인하러 가느냐를 정하는 값이고, 지금 필요한 건 오늘 실행할 것이냐를 정하는 조건이에요. 층이 다르니까 스케줄 화면을 아무리 만져도 안 풀려요. 손댈 자리는 트리거 바로 다음, 자동화의 첫 단계예요.

그리고 그 조건에 넣을 날짜 목록은 손으로 관리하면 안 돼요. 대체공휴일은 날짜가 아니라 규칙으로 정해지고, 임시공휴일은 미리 알 수 없거든요. 대신 공공데이터포털에 무료로 열려 있는 한국천문연구원 특일 정보 API에서 받아 오면 돼요. 아래에 법령 원문과 공식 문서에 실제로 적혀 있는 문장만 근거로 연동 5단계와 함정을 정리했어요.

황동 테두리 체가 돌 상판 위에 놓이고 체 안에는 짙은 색 알갱이가 남아 있으며 둘레에는 고운 가루가 퍼져 있는 정물, 옆에서 들어온 부드러운 빛, 걸러 낼 것과 통과시킬 것을 나누는 판정을 은유한 이미지

고칠 곳은 실행 주기가 아니라 실행 여부예요

자동화가 원하지 않는 때에 돌면 먼저 스케줄 설정을 열게 되거든요. 매일을 평일로 바꿔 보고, 시간을 옮겨 보고, 간격을 늘려 봐요. 그런데 이 방향으로는 답이 안 나와요. 스케줄은 실행 시점을 정하는 장치지 실행을 취소하는 장치가 아니니까요.

구조를 이렇게 나눠 보면 정리가 돼요. 자동화 하나는 크게 세 층으로 되어 있어요. 언제 깨어날지를 정하는 트리거, 깨어난 다음 진행할지 말지를 정하는 조건, 그리고 실제로 일을 하는 액션이에요. 공휴일 문제는 두 번째 층의 문제예요. 트리거는 그대로 매일 깨어나되, 조건에서 걸러 액션까지 못 가게 막으면 돼요.

이렇게 두면 얻는 게 하나 더 있어요. 실행 기록이 남아요. 자동화 도구의 실행 로그에 "깨어났고, 공휴일이라 여기서 멈췄음"이 찍히거든요. 스케줄을 꺼서 아예 안 도는 것과는 다른 상태예요. 나중에 "그날 왜 안 왔지"를 확인할 때 이 기록이 있고 없고가 크게 갈려요.

참고로 트리거가 언제 깨어나는지, 왜 즉시 안 도는지는 이 글의 범위가 아니에요. 그쪽이 궁금하시면 웹훅과 폴링 차이, 도구별 실행 주기를 정리한 글을 따로 보시는 게 빨라요. 이 글은 깨어난 다음에 무엇을 보고 멈출지만 다뤄요.

공휴일 목록을 손으로 넣으면 왜 금방 깨지나요

가장 흔한 방식은 연초에 달력을 보고 날짜를 배열로 적어 두는 거예요. 짧게는 되는데, 다음 세 지점에서 어긋나기 시작해요.

첫째, 법이 바뀌어요. 그것도 2026년에만 두 번 바뀌었어요. 먼저 법률 제21338호가 2026년 2월 10일 공포되고 2026년 5월 11일 시행됐어요. 개정문에 적힌 문장은 이거예요. "제2조제1호 중 "국경일 중 3ㆍ1절, 광복절, 개천절 및 한글날"을 "국경일"로 한다." 개정이유 및 주요내용 절은 그 취지를 이렇게 설명해요. "헌법 제정과 공포를 기념하는 제헌절은 민주주의의 근간을 확인하는 중요한 국경일임에도 불구하고 공휴일에서 제외됨으로 인하여 그 상징성과 기념 의식이 약화되고 국민적 관심도 저조한 상황인바, 제헌절을 공휴일로 지정하여 헌법정신에 대한 국민의식을 제고하려는 것임."

그리고 같은 해에 개정이 하나 더 있었어요. 법률 제21543호가 2026년 4월 9일 공포, 2026년 5월 1일 시행으로 노동절을 공휴일에 넣었어요. 「관공서의 공휴일에 관한 규정」의 개정이유 및 주요내용 절이 두 개정을 나란히 적어 두었어요. "제헌절을 공휴일로 지정하여 헌법정신에 대한 국민의식을 제고하고, 노동절을 공휴일로 지정하여 공휴일 운영의 통일성과 효율적인 행정 운영을 도모하는 내용으로 「공휴일에 관한 법률」이 개정(법률 제21338호, 2026. 2. 10. 공포, 5. 11. 시행 및 법률 제21543호, 2026. 4. 9. 공포, 5. 1. 시행)됨에 따라"라고요. 자동화 입장에서 이건 그냥 조문 이야기가 아니에요. 「관공서의 공휴일에 관한 규정」 제2조에도 노동절이 제6호로 새로 들어갔으니, 5월 1일을 대하는 기준이 작년과 달라졌다는 뜻이거든요. 작년에 만든 배열은 이 두 변경을 모른 채로 남아 있어요.

둘째, 대체공휴일은 날짜가 아니라 규칙이에요. 「공휴일에 관한 법률」 제3조 제1항은 "제2조에 따른 공휴일이 토요일이나 일요일, 다른 공휴일과 겹칠 경우에는 대체공휴일로 지정하여 운영할 수 있다."라고만 적고, 제2항에서 "제1항의 대체공휴일의 지정 및 운영에 관한 사항은 대통령령으로 정한다."라고 넘겨요. 즉 세부 규칙은 다른 문서에 있어요.

셋째, 임시공휴일이 있어요. 「관공서의 공휴일에 관한 규정」 제4조는 "제2조제11호에 따른 공휴일을 지정하려는 경우에는 국무회의의 심의를 거쳐야 한다."라고 적고 있어요. 국무회의 심의를 거쳐 정해지는 날이니 연초에 미리 배열에 넣어 둘 방법이 없어요.

법령 두 개를 섞지 마세요

공휴일을 다루는 법령은 하나가 아니에요. 「공휴일에 관한 법률」은 법률이고 소관부처는 인사혁신처와 고용노동부이며, 「관공서의 공휴일에 관한 규정」은 대통령령이고 소관부처는 인사혁신처예요. 그리고 두 문서의 제2조는 호 번호가 서로 어긋나요.

2026년 5월 11일 시행 기준으로 「공휴일에 관한 법률」 제2조는 열한 개 호이고, 순서는 국경일, 1월 1일, 설날 연휴, 부처님 오신 날, 노동절, 어린이날, 현충일, 추석 연휴, 기독탄신일, 선거일, 기타 정부에서 수시 지정하는 날이에요. 「관공서의 공휴일에 관한 규정」 제2조는 일요일, 국경일, 1월 1일, 설날 연휴, 부처님 오신 날, 노동절, 어린이날, 현충일, 추석 연휴, 기독탄신일, 선거일(제10의2호), 그 밖에 정부에서 수시 지정하는 날이고요.

두 목록을 나란히 놓으면 어긋나는 지점이 보여요. 대통령령 쪽 맨 앞에 일요일이 하나 더 있고, 그 한 칸 때문에 뒤가 전부 밀려요. 같은 노동절이 법률에서는 제5호인데 대통령령에서는 제6호예요. 일요일은 법률 제2조 각 호에는 아예 없고 대통령령 제2조제1호에만 있고요. 그래서 "법으로 공휴일"이라고 뭉뚱그린 설명을 그대로 코드에 옮기면 조건이 틀어져요. 조문을 인용할 때는 어느 법령의 몇 조 몇 호인지를 같이 적어 두세요.

대체공휴일 규칙은 조건 하나로 안 끝나요

"주말과 겹치면 다음 평일"이라고 한 줄로 짜 두는 경우가 많은데, 「관공서의 공휴일에 관한 규정」 제3조는 그것보다 훨씬 잘게 나뉘어 있어요. 제1항 본문부터 볼게요. "제2조제2호부터 제10호까지의 공휴일이 다음 각 호의 어느 하나에 해당하는 경우에는 그 공휴일 다음의 첫 번째 비공휴일(제2조 각 호의 공휴일이 아닌 날을 말한다. 이하 같다)을 대체공휴일로 한다."

여기서 이미 두 가지가 정해져요. 대상은 제2조제2호부터 제10호까지이고, 옮겨 가는 자리는 다음 날이 아니라 "다음의 첫 번째 비공휴일"이에요. 공휴일이 연달아 있으면 그만큼 더 밀린다는 뜻이에요.

그다음 각 호에서 조건이 갈려요. 제1호는 "제2조제2호, 제5호부터 제7호까지 또는 제10호의 공휴일이 토요일이나 일요일과 겹치는 경우"예요. 이 호가 가리키는 것은 국경일, 부처님 오신 날, 노동절, 어린이날, 기독탄신일이에요. 제2호는 "제2조제4호 또는 제9호의 공휴일이 일요일과 겹치는 경우"이고, 여기 해당하는 것은 설날 연휴와 추석 연휴예요. 두 호를 나란히 놓고 읽어 보세요. 제1호에는 토요일이 들어 있는데 제2호에는 토요일이 없어요.

제3호는 결이 또 달라요. "제2조제2호, 제4호부터 제7호까지, 제9호 또는 제10호의 공휴일이 토요일ㆍ일요일이 아닌 날에 같은 조 제2호부터 제10호까지의 규정에 따른 다른 공휴일과 겹치는 경우"예요. 주말이 아니라 공휴일끼리 겹치는 상황을 다루는 조항이에요.

제2항과 제3항은 겹침이 또 생겼을 때의 처리예요. 제2항은 "제1항에 따른 대체공휴일이 같은 날에 겹치는 경우에는 그 대체공휴일 다음의 첫 번째 비공휴일까지 대체공휴일로 한다."이고, 제3항은 "제1항 및 제2항에 따른 대체공휴일이 토요일인 경우에는 그 다음의 첫 번째 비공휴일을 대체공휴일로 한다."예요.

여기서 실무적으로 중요한 결론이 나와요. 제3조제1항 제1호와 제2호가 가리키는 호 번호 바깥에 있는 공휴일은 토요일이나 일요일과 겹쳐도 이 규칙으로는 대체공휴일이 붙지 않아요. 예를 들어 현충일은 「관공서의 공휴일에 관한 규정」 제2조제8호인데, 제1호가 열거한 호 목록에 제8호가 없어요. 그러니 "공휴일이 주말과 겹치면 무조건 다음 평일"로 짠 코드는 있어야 할 날을 만들어 내는 쪽으로 틀려요. 규칙을 직접 구현하려고 들면 이 함정을 전부 통과해야 하는데, 그럴 이유가 없어요. 이미 계산된 결과를 받아 오면 되거든요.

어두운 표면 위에 가로로 놓인 삼끈 가운데에 매듭이 지어져 있고 잔털이 삐져나온 접사, 낮은 채도의 차분한 빛, 조건이 걸리는 지점을 은유한 이미지

공휴일 데이터는 어디서 받나요

공공데이터포털의 "한국천문연구원_특일 정보" 데이터셋이에요. 제공기관은 한국천문연구원이고 관리부서명은 천문전산융합센터예요. 포털에 적힌 설명은 이래요. "(천문우주정보)국경일정보, 공휴일정보, 기념일정보, 24절기정보, 잡절정보를 조회하는 서비스 입니다. 활용시 날짜, 순번, 특일정보의 분류, 공공기관 휴일 여부, 명칭을 확인할 수 있습니다."

기본 정보 표를 보면 API 유형은 REST, 데이터 포맷은 XML, 등록일은 2015-12-21, 수정일은 2023-03-29이에요. 이용 조건 및 라이선스 정보 표에서 비용부과유무는 무료, 이용허락범위는 "이용허락범위 제한 없음", 심의유형은 개발단계와 운영단계 모두 자동승인이고요. 신청 가능 트래픽 항목에는 "개발계정 : 10,000 / 운영계정 : 활용사례 등록시 신청하면 트래픽 증가 가능"이라고 적혀 있어요. 서비스 URL은 apis.data.go.kr 아래 B090041/openapi/service/SpcdeInfoService 경로예요.

이 서비스 안에는 오퍼레이션이 다섯 개 들어 있어요. 공식 활용가이드의 오퍼레이션 목록 표에 적힌 순서대로 정리하면 이래요.

오퍼레이션요청 주소 끝부분공식 문서가 적은 기능이 글에서 받아 본 실제 응답 값
국경일 정보조회getHoliDeInfo연, 월별로 구분(국경일), 요일, 공휴일 여부 등의 정보를 제공이 글에서 확인하지 않음
공휴일 정보조회getRestDeInfo월별로 구분(공휴일), 요일, 공휴일 여부 등의 정보를 제공이 글에서 확인하지 않음
기념일 정보조회getAnniversaryInfo연, 월별로 기념일 정보를 제공이 글에서 확인하지 않음
24절기 정보조회get24DivisionsInfo월별로 구분(24절기), 요일, 공휴일 여부 등의 정보를 제공이 글에서 확인하지 않음
잡절 정보조회getSundryDayInfo월별로 구분(잡절), 요일, 공휴일 여부 등의 정보를 제공이 글에서 확인하지 않음

세 번째 열은 공공데이터포털 상세기능 화면과 공식 활용가이드 v1.4에 적힌 문장을 옮긴 것이에요. 네 번째 열은 유효한 서비스키가 없어 실제 응답 본문을 받아 보지 못했기 때문에 열 전체를 닫아 두었어요. 아래에 나오는 응답 필드와 예제 값도 모두 공식 문서 쪽 근거이지, 특정 연월을 실제로 조회해 확인한 값이 아니에요.

응답 항목이 조금 다른 자리도 하나 있어요. 활용가이드의 24절기 정보 조회 응답 메시지 명세 표에는 kst(한국표준시각)와 sunLongitude(태양황경) 항목이 더 들어 있어요. 쉬는 날을 거르는 목적에는 쓸 일이 없는 값이니 참고만 하시면 돼요.

쉬는 날을 걸러 내는 목적이라면 고를 것은 getRestDeInfo예요. 포털의 기능 설명은 이 오퍼레이션을 "월별로 구분(휴일), 요일, 휴일 여부 등의 정보를 제공하는 공휴일 정보조회 기능.(대체공휴일의 경우, 법제처 심사, 국무회의, 대통령의 승인 등 절차를 거쳐 관보에 정식 공포 된 이후에 적용)"이라고 적어요. 괄호 안 문장을 흘려 읽지 마세요. 뒤에서 캐시 이야기를 할 때 다시 나와요.

공휴일 제외 자동화 연동 5단계

1단계. 서비스키 발급받기

공공데이터포털에서 특일 정보 데이터셋을 찾아 활용신청을 넣으면 돼요. 심의유형이 개발단계와 운영단계 모두 자동승인이라 승인을 기다리는 절차가 없어요. 개발계정 트래픽은 10,000으로 적혀 있고, 운영계정은 활용사례를 등록하고 신청하면 늘릴 수 있다고 안내돼 있어요. 하루 한 번 조회하는 자동화라면 개발계정으로도 여유가 넉넉해요.

발급받은 키는 자동화 도구의 환경변수나 자격증명 저장소에 넣고, 워크플로 화면에 그대로 타이핑하지 마세요. 화면을 공유하거나 내보내기를 하는 순간 같이 나가거든요. 키와 토큰을 자동화 안에서 다루는 감각이 아직 낯설다면 카카오톡 나에게 보내기 API로 알림 채널을 만드는 글에서 만료 대비까지 묶어 둔 부분을 먼저 보셔도 좋아요.

2단계. 오퍼레이션과 파라미터 정하기

getRestDeInfo를 고르고 연월을 넣어요. 여기서 문서끼리 어긋나는 지점이 하나 있어요. 포털 화면의 요청변수 표는 solYear(항목크기 4, 샘플 2015)와 solMonth(항목크기 2, 샘플 09)를 둘 다 필수로 적어 두었는데, 공식 활용가이드 v1.4의 요청 메시지 명세 표는 solYear를 항목구분 1(필수), solMonth를 0(옵션)으로 적고 있어요. 어느 쪽을 믿을지 고민할 필요는 없어요. 월을 넣어 열두 번 부르면 두 문서 어느 쪽 기준으로도 통과하니까요.

같이 챙길 파라미터가 둘 더 있어요. 활용가이드의 요청 메시지 명세 표를 보면 _type은 항목명(국문)이 "json 타입 (디폴트 XML)", 항목설명이 "json 타입으로 활용시 추가", 항목구분이 0이에요. 같은 표 아래에 "항목구분 : 필수(1), 옵션(0)"이라고 적혀 있으니 0은 옵션이라는 뜻이고요. 파싱이 편하니 붙이는 편이 좋아요. 같은 표에서 numOfRows의 항목설명은 "한페이지에 모든 결과를 확인할 때 추가(디폴트 10)"예요. 이 값을 안 넣으면 한 페이지에 열 건만 오는데, 결과가 조용히 잘려도 에러는 안 나요. 넉넉하게 지정해 두세요.

3단계. 호출해서 응답 구조 확인하기

응답은 response 아래에 header와 body가 있고, header에는 resultCode와 resultMsg가, body에는 items와 numOfRows, pageNo, totalCount가 들어 있어요. resultCode의 항목설명은 "00:성공"이고 resultMsg의 샘플데이터는 "NORMAL SERVICE"예요. items 아래 item 하나는 다섯 요소로 되어 있고요.

항목명공식 가이드 예제 값이 글에서 받아 본 실제 값
locdate날짜20190301이 글에서 확인하지 않음
seq순번1이 글에서 확인하지 않음
dateKind특일정보의 분류01이 글에서 확인하지 않음
isHoliday공공기관 휴일여부Y이 글에서 확인하지 않음
dateName명칭삼일절이 글에서 확인하지 않음

두 번째 열은 공공데이터포털의 출력결과 표에 적힌 항목 설명이고, 세 번째 열은 공식 활용가이드 v1.4에 실린 getHoliDeInfo 예제 응답 XML의 값이에요. 네 번째 열은 앞의 표와 같은 이유로 닫아 두었어요. dateKind가 무엇을 뜻하는지는 활용가이드의 Datekind 분류 표에 네 줄로 적혀 있어요. 01은 국경일이고 예시로 어린이 날, 광복절, 개천절이 붙어 있어요. 02는 기념일이고 예시는 의병의 날, 정보보호의 날, 4·19 혁명 기념일이에요. 03은 24절기이고 예시는 청명, 경칩, 하지, 04는 잡절이고 예시는 단오와 한식이에요.

여기서 하나 조심할 게 있어요. 잡절 조회 쪽 명세에는 휴일여부 항목이 ishHoliday로 적혀 있는데, 같은 문서의 바로 아래 예제 응답 XML에는 같은 요소가 isHoliday로 나와요. 문서 안에서 철자가 갈리는 자리이니, 필드명을 문서만 보고 코드에 박지 말고 실제 응답을 한 번 찍어 보고 맞추세요.

호출 코드는 이 정도면 돼요.

import requests

url = "https://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService/getRestDeInfo"

def fetch_month(key, year, month):
    params = dict(serviceKey=key, solYear=year, solMonth=month,
                  numOfRows="100", _type="json")
    res = requests.get(url, params=params, timeout=10)
    res.raise_for_status()
    return res.json()

4단계. 결과를 캐시로 두기

매번 부르지 말고 한 번 받아서 저장해 두세요. 이유는 두 가지예요. 하나는 트래픽을 아끼는 것이고, 다른 하나는 API가 잠깐 응답하지 않을 때 자동화가 통째로 멈추지 않게 하는 것이에요.

저장 형태는 단순할수록 좋아요. isHoliday가 Y인 항목의 locdate만 모아 문자열 집합으로 두면 판정이 한 줄로 끝나요.

def build_holiday_set(key, year):
    dates = set()
    for m in range(1, 13):
        data = fetch_month(key, str(year), "%02d" % m)
        items = data["response"]["body"]["items"]
        if not items:
            continue
        rows = items["item"]
        if isinstance(rows, dict):
            rows = [rows]
        for row in rows:
            if str(row.get("isHoliday", "")).strip() == "Y":
                dates.add(str(row["locdate"]))
    return dates

rows를 리스트로 감싸는 줄이 왜 있는지 짚고 갈게요. XML을 JSON으로 바꿔 주는 방식에서는 항목이 하나뿐일 때 배열 대신 객체 하나로 오는 형태가 나올 수 있어서, 두 형태를 모두 받아 두는 방어예요. 이 API가 실제로 어느 쪽으로 내려주는지는 이 글에서 확인하지 못했으니, 내 키로 한 달치를 찍어 보고 확인하세요. 어느 쪽이든 이 줄이 있으면 깨지지 않아요.

5단계. 자동화 첫머리에 조건 붙이기

이제 마지막이에요. 트리거 다음에 조건을 하나 넣고, 오늘이 쉬는 날이면 거기서 끝내면 돼요.

from datetime import date

def should_run(today, holiday_dates):
    if today.weekday() >= 5:
        return False, "주말이라 실행하지 않아요"
    if today.strftime("%Y%m%d") in holiday_dates:
        return False, "공휴일이라 실행하지 않아요"
    return True, "실행합니다"

ok, reason = should_run(date.today(), holiday_dates)
if not ok:
    log(reason)
else:
    run_daily_job()

주말 판정을 API가 아니라 weekday로 하는 이유를 짚고 갈게요. 요일은 네트워크를 타지 않고도 어느 언어에서나 바로 계산되는 값이에요. 그런데도 공공데이터포털에는 "한국천문연구원_일요일 정보조회"라는 별개 데이터셋이 데이터셋 번호 15125130으로 따로 올라와 있어요. 일요일을 굳이 다른 데이터셋으로 떼어 두었다는 건, 특일 정보 쪽 응답에서 일요일을 기대하지 않는 편이 안전하다는 신호로 읽을 만해요. 이 데이터셋의 설명은 "(천문우주정보)일요일정보를 조회하는 서비스 입니다. 활용시 연, 월의 요청 조건에 따라 해당 연, 월의 일요일에 대한 정보(연, 월, 일, 요일)를 확인 할 수 있습니다."이고, 데이터 포맷은 JSON+XML이며 등록일과 수정일은 모두 2023-11-24이에요. 정리하면 이래요. 쉬는 날 중에서 규칙과 지정으로 정해지는 부분만 API에 묻고, 요일처럼 달력만 있으면 알 수 있는 부분은 코드에서 끝내세요.

노코드 도구를 쓰신다면 같은 구조를 필터 모듈이나 IF 노드로 옮기면 돼요. 서버 쪽에 워크플로를 직접 두는 방식이 궁금하시면 n8n 자동화 워크플로우 초보 가이드에서 노드 구성을 먼저 보고 오시면 조건 분기를 어디에 끼울지 감이 잡혀요.

젖은 모래 위에 둥근 돌을 쌓아 올린 탑, 뒤로 흐릿한 산과 물과 뿌연 하늘, 차분한 확산광, 규칙이 층층이 얹히는 구조를 은유한 이미지

오퍼레이션을 잘못 고르면 생기는 일

getRestDeInfo와 getHoliDeInfo는 이름이 비슷해서 헷갈리기 쉬운데, 공식 활용가이드가 둘을 이렇게 갈라놨어요.

getHoliDeInfo의 오퍼레이션 설명은 "연, 월별로 구분(국경일), 요일, 공휴일 여부 등의 정보를 제공한다. 국경일에 대한 정보 조회로 제헌절은 해당 오퍼레이션에 포함되나 isHoliday=N 으로 출력된다."예요. getRestDeInfo 쪽은 "월별로 구분(공휴일), 요일, 공휴일 여부 등의 정보를 제공한다. 휴일 정보에 대한 조회로 제헌절은 해당 오퍼레이션에서 제공되지 않는다."이고요.

그러니까 getHoliDeInfo를 쓰면서 isHoliday를 확인하지 않고 "응답에 들어 있으면 쉬는 날"로 처리하면 틀려요. 국경일이면서 isHoliday가 N인 항목이 섞여 들어오니까요. 반대로 getRestDeInfo를 쓰면 그런 항목이 애초에 안 온다는 게 문서의 서술이에요.

문서의 시점을 확인하세요

방금 인용한 두 문장이 실린 공식 활용가이드는 버전 1.4이고 변경일은 2020-06-09예요. 개정 이력 표의 마지막 줄에 "입력 파라메터 변경(필수, 옵션), DateKind 추가"라고 적힌 그 버전이에요. 이 문서를 참고문서로 걸어 둔 포털 페이지의 수정일은 2023-03-29이고요. 그런데 「공휴일에 관한 법률」의 제헌절 관련 개정은 2026년 2월 10일 공포에 2026년 5월 11일 시행이고, 노동절 관련 개정은 2026년 4월 9일 공포에 2026년 5월 1일 시행이에요. 문서 두 개의 시점이 모두 그보다 앞서요. 그래서 제헌절이 지금 어느 오퍼레이션에서 어떻게 나오는지는 문서만으로 단정할 수 없어요. 이 글에서도 유효한 서비스키가 없어 실제 응답으로 확인하지 못했어요. 내 키를 발급받은 다음, 코드를 짜기 전에 한 달치를 먼저 찍어 보고 실제 값에 맞추세요.

여기서 얻을 습관은 하나예요. 자동화가 판정을 내리는 자리에는 문서에서 읽은 문장이 아니라 내가 실제로 받아 본 응답을 근거로 두세요. 문서는 갱신이 늦을 수 있지만 응답은 지금 값이니까요.

응답이 안 올 때 어디가 틀렸는지 가르는 법

2026년 8월 5일에 이 서비스에 직접 요청을 넣어 봤어요. 유효한 키가 없는 상태였기 때문에 확인한 것은 게이트웨이가 돌려주는 거절 응답뿐이지만, 그 거절 응답만으로도 진단 순서를 세울 수 있어요.

보낸 요청HTTP 상태errMsgreturnAuthMsgreturnReasonCode
serviceKey 파라미터 자체를 뺌401SERVICE_KEY_IS_NULL서비스 접근거부20
등록되지 않은 문자열을 키로 넣음403SERVICE_KEY_IS_NOT_REGISTERED_ERROR등록되지 않은 서비스키30
존재하지 않는 오퍼레이션명을 넣음400NO_OPENAPI_SERVICE_ERROR해당 오픈API 서비스가 없거나 폐기됨12

이 표에서 읽어야 할 것은 세 번째 줄이에요. 같은 등록되지 않은 키를 그대로 쓰면서 오퍼레이션명만 없는 이름으로 바꿨더니 응답이 403에서 400으로 바뀌었어요. 게이트웨이가 키를 검사하기 전에 경로를 먼저 가른다는 뜻이에요.

그래서 진단 순서를 세 칸으로 세울 수 있어요. 400이 오면 키를 만지지 말고 요청 주소부터, 그러니까 오퍼레이션명 오타를 먼저 보세요. 401이 오면 serviceKey 파라미터가 요청에서 통째로 빠진 경우예요. 403이 오면 그때가 키 문자열과 활용신청 상태를 볼 차례고요. 뒤에서 옮겨 적을 포털 안내의 Unauthorized 문구가 바로 이 401 자리에 붙는 설명이에요. 참고로 getRestDeInfo, getHoliDeInfo, getAnniversaryInfo, get24DivisionsInfo, getSundryDayInfo 다섯 경로 모두 같은 미등록 키로는 403과 코드 30을 돌려줬어요.

키가 정상인데도 실패하는 경우를 대비해 포털의 오픈API 에러코드 안내에 실린 문구도 옮겨 둘게요. Unauthorized는 "API 인증키가 존재하지 않거나 유효하지 않습니다. 공공데이터포털에서 발급받은 인증키 정보를 확인해 주세요."이고, Forbidden은 "API 서비스에 대한 신청내역이 확인되지 않습니다. 해당 API의 활용신청 여부와 승인 상태를 확인해 주세요."예요. API not found는 "API 서비스가 존재하지 않습니다. 호출 URL에 오타가 없는지, 폐기된 API는 아닌지 확인해 주세요."이고, API rate limit exceeded는 "현재 많은 사용자가 API를 호출하고 있어, 서버의 최대 동시 요청 수를 초과하였습니다. 잠시 후 다시 호출해주시기 바랍니다."예요. API token quota exceeded는 "API 서비스의 일일 호출 허용량을 초과하였습니다. 초기화된 이후 다시 이용 바랍니다."고요.

같은 표에는 내 요청이 아니라 기관 서버 쪽을 가리키는 항목도 따로 있어요. Error forwarding request to backend server는 "기관 API 서버와의 연결에 실패했습니다. 일시적인 네트워크 오류일 수 있으니 잠시 후 다시 시도해 주세요."이고, Error receiving response from backend server는 "기관 API 서버로부터 응답을 받지 못했습니다. 문제가 계속될 경우, '관리부서 전화번호' 혹은 '오류신고 및 문의'를 통해 제공기관에 문의바랍니다."예요. 이 밖에 Unexpected error와 SSL 인증서 검증 실패에 관한 항목들도 같은 표에 실려 있고요.

자동화에서 특히 신경 쓸 것은 방금 옮긴 backend server 두 줄과 앞의 rate limit 항목이에요. 포털이 안내 문구에 직접 "잠시 후 다시 시도해 주세요", "잠시 후 다시 호출해주시기 바랍니다"라고 적어 둔 종류, 그러니까 재시도가 의미 있는 실패거든요. 반면 일일 호출 허용량 초과는 결이 달라요. 안내 문구가 "초기화된 이후 다시 이용 바랍니다"라서 잠깐 기다렸다 다시 부른다고 풀리지는 않아요. 어느 쪽이든 그동안 캐시가 없으면 판정 자체를 못 한다는 점은 같아요. 앞에서 캐시를 두라고 한 이유가 여기서 다시 나와요.

캐시를 언제 다시 받아야 하나요

한 번 받아서 일 년을 쓰겠다는 계획은 여기서 막혀요. 공식 활용가이드의 기타참고사항 절이 갱신 시점을 이렇게 적어 두었어요. "데이터 업데이트는 각 오퍼레이션 별로 연 1회 진행 됩니다.(1년치 데이터 일괄 업데이트)" 그런데 같은 절이 곧바로 예외를 덧붙여요. "추가로 임시공휴일 등 갑작스럽게 발생하는 데이터가 생길 경우 데이터는 바로 업데이트 되며(최대 1일 이내), 대체공휴일이 추가로 지정되는 경우 대통령령이 공식적으로 시행된 이후에 업데이트 되오니 참고 부탁 드립니다."

포털의 공휴일 정보 조회 기능 설명에도 같은 취지의 괄호가 붙어 있어요. "(대체공휴일의 경우, 법제처 심사, 국무회의, 대통령의 승인 등 절차를 거쳐 관보에 정식 공포 된 이후에 적용)"이에요. 절차가 끝나기 전에는 데이터에 없다는 뜻이니, 뉴스로 먼저 알게 되고 API에는 나중에 들어오는 순서가 생겨요.

내년 이후 날짜를 미리 받아 두려는 경우에는 시점이 또 다르게 적혀 있어요. "특일정보의 경우 6~8월 경 과학기술정보통신부에서 월력요항 정보를 공식적으로 발표한 이후에 차차년도 데이터를 먼저 업데이트 합니다.(현재연도 기준 +2년)"이고, "그 외 기념일, 24절기, 잡절은 11경 업데이트 됩니다."예요. 그래서 먼 미래 날짜를 조회했을 때 빈 결과가 오는 것은 호출 실패가 아니라 아직 채워지지 않은 구간일 수 있어요.

여기서 자동화 설계에 반영할 것은 세 가지예요.

첫째, 갱신 주기를 하루 한 번 정도로 잡으세요. 임시공휴일이 최대 하루 안에 들어온다고 적혀 있으니 그 리듬에 맞추면 돼요.

둘째, 빈 결과와 실패를 구분하세요. 정상 응답인데 항목이 없는 것과 호출이 실패한 것은 다른 상태예요. 이 둘을 같이 처리하면 "받아 온 게 없으니 쉬는 날 아님"이 되어 공휴일에 자동화가 그대로 돌아요.

셋째, 실패했을 때 어느 쪽으로 넘어질지 미리 정하세요. 캐시도 없고 호출도 실패했을 때 실행할 것인지 멈출 것인지를 정해 두라는 뜻이에요. 알림이나 집계처럼 한 번 더 와도 괜찮은 자동화라면 실행 쪽으로, 외부에 나가는 발송이나 결제처럼 되돌리기 어려운 자동화라면 멈추는 쪽으로 두는 편이 무난해요. 이 선택을 안 해 두면 코드가 알아서 정하는데, 대개 실행하는 쪽으로 정해져요.

적용 범위는 관계 법령이 따로 정해요

「공휴일에 관한 법률」 제4조는 이렇게 적고 있어요. "제2조에 따른 공휴일과 제3조에 따른 대체공휴일의 적용은 「국가공무원법」, 「근로기준법」 등 관계 법령에서 정하는 바에 따른다." 그러니까 어떤 날이 공휴일이냐는 판정과, 그날이 우리 회사에서 어떻게 취급되느냐는 판단은 서로 다른 층이에요. 이 글이 다루는 것은 앞쪽, 그러니까 자동화가 오늘 실행할지 말지를 가르는 데이터예요. 근무일이나 휴일 취급 같은 문제는 인사 규정과 관계 법령을 따라야 하니 그쪽은 담당 부서에 확인하세요.

밝은 실내에서 흰 벽에 창틀 그림자가 비스듬히 드리우고 나무 바닥 위에 원형 상판의 나무 스툴이 놓인 장면, 사람이 없는 조용한 공간, 실행되지 않고 비워 둔 하루를 은유한 이미지

자가진단, 내 자동화는 어디서 새고 있나요

지금 돌고 있는 자동화를 하나 열어 두고 아래를 한 줄씩 짚어 보세요. 걸리는 항목이 곧 다음에 사고가 날 자리예요.

  • 공휴일을 거르는 조건이 트리거 뒤 첫 단계에 있나요, 아니면 아예 없나요
  • 날짜 목록을 코드나 시트에 직접 적어 두지는 않았나요
  • 그 목록에 대체공휴일이 들어 있다면 누가 언제 넣었는지 아시나요
  • 주말 판정을 API에 물어보고 있지는 않나요
  • getHoliDeInfo를 쓰면서 isHoliday 값을 확인하지 않고 있지는 않나요
  • numOfRows를 지정하지 않아 결과가 열 건에서 잘리고 있지는 않나요
  • API 호출이 실패했을 때 자동화가 실행 쪽으로 넘어지나요, 멈춤 쪽으로 넘어지나요
  • 응답이 정상인데 항목이 비어 있는 경우와 호출이 실패한 경우를 구분해서 처리하고 있나요
  • 공휴일 데이터를 마지막으로 받아 온 시각이 로그에 남나요
  • 조건에 걸려 멈춘 실행도 로그에 기록으로 남나요

마지막 두 항목이 은근히 중요해요. 이게 없으면 "그날 왜 안 왔지"라는 질문에 답할 수 없거든요. 조건에 걸려 멈춘 것인지, 트리거가 아예 안 깨어난 것인지, 호출이 실패해 판정을 못 한 것인지가 로그에서 갈려야 나중에 원인을 찾아요.

지금 당장 해볼 액션

오늘은 여기까지만 하셔도 충분해요.

먼저 공공데이터포털에서 특일 정보 데이터셋에 활용신청을 넣고 서비스키를 받으세요. 자동승인이라 오래 걸리지 않아요. 키가 나오면 getRestDeInfo에 올해 한 달치만 넣어 한 번 호출해 보세요. 이때 _type을 json으로, numOfRows를 넉넉하게 넣는 것을 잊지 마시고요.

응답이 오면 화면에 그대로 찍어 놓고 필드명과 값을 눈으로 확인하세요. isHoliday가 어떤 문자로 오는지, locdate가 문자열인지 숫자인지, 한 건일 때 item이 배열로 오는지 단일 객체로 오는지를 여기서 확인해 두면 나중에 디버깅할 일이 줄어요. 문서에 적힌 예제 값과 다르더라도 놀라지 마세요. 이 글에서 인용한 예제 값도 2020년에 작성된 문서의 것이라 지금 응답과 다를 수 있어요.

그다음에 자동화를 하나만 골라 조건을 붙이세요. 제일 자주 나가는 것, 그러니까 받는 사람이 많은 자동화부터가 좋아요. 조건을 붙였으면 오늘 날짜를 임시로 공휴일 집합에 넣어 두고 한 번 돌려 보세요. 멈추면 성공이고, 그대로 돌아가면 조건이 트리거보다 뒤가 아니라 액션보다 뒤에 붙어 있는 경우가 많아요.

마지막으로 갱신 일정을 하나 걸어 두세요. 하루 한 번 데이터를 다시 받아 캐시를 덮어쓰는 작은 자동화면 충분해요. 임시공휴일이 최대 하루 안에 들어온다고 공식 문서에 적혀 있으니, 이 작은 자동화 하나가 있고 없고에 따라 갑자기 지정된 쉬는 날에 알림이 나가느냐 마느냐가 갈려요.

함께 보면 좋은 글

❓ 자주 묻는 질문 (FAQ)

자동화를 공휴일에 안 돌게 하려면 실행 주기를 바꾸면 되나요?

주기를 바꾸는 것으로는 안 돼요. 주기는 '얼마나 자주 확인하러 가느냐'를 정하는 값이고, 공휴일 문제는 '오늘 실행할 것이냐'를 정하는 문제라 층이 달라요. 매일 아침 아홉 시에 도는 자동화의 주기를 늘리면 평일 실행까지 같이 빠지고, 줄이면 공휴일에 더 자주 돌아요. 그래서 손볼 자리는 스케줄 화면이 아니라 자동화의 첫 단계예요. 트리거 다음에 조건 분기를 하나 넣고, 오늘이 쉬는 날이면 뒤 단계로 넘기지 않고 거기서 끝내는 구조로 만드세요. 이렇게 두면 주기는 그대로 두고 실행 여부만 갈라져요.

공휴일 목록을 코드에 직접 적어 두면 안 되나요?

일 년은 버티는데 그다음부터 어긋나기 시작해요. 이유는 두 가지예요. 첫째로 대체공휴일은 고정된 날짜가 아니라 규칙으로 정해지는 날이에요. 「관공서의 공휴일에 관한 규정」 제3조는 어떤 공휴일이 어떤 요일과 겹쳤을 때 그다음 첫 번째 비공휴일을 대체공휴일로 삼는지 호마다 조건을 다르게 적어 두었어요. 둘째로 임시공휴일이 있어요. 같은 규정 제4조는 '제2조제11호에 따른 공휴일을 지정하려는 경우에는 국무회의의 심의를 거쳐야 한다'고 적고 있는데, 이건 미리 알 수 있는 날짜가 아니에요. 그래서 목록을 박아 두는 대신 데이터를 받아 오는 쪽으로 가야 해요.

공휴일 데이터는 어디서 받나요?

공공데이터포털의 '한국천문연구원_특일 정보' 데이터셋이에요. 포털에 적힌 설명은 '(천문우주정보)국경일정보, 공휴일정보, 기념일정보, 24절기정보, 잡절정보를 조회하는 서비스 입니다. 활용시 날짜, 순번, 특일정보의 분류, 공공기관 휴일 여부, 명칭을 확인할 수 있습니다.'예요. 이용 조건 표를 보면 비용부과유무는 무료이고 이용허락범위는 '이용허락범위 제한 없음'이며 심의유형은 개발단계와 운영단계 모두 자동승인이에요. 신청 가능 트래픽 항목에는 '개발계정 : 10,000 / 운영계정 : 활용사례 등록시 신청하면 트래픽 증가 가능'이라고 적혀 있어요. 서비스 URL은 apis.data.go.kr 아래의 SpcdeInfoService 경로예요.

getRestDeInfo와 getHoliDeInfo 중 뭘 써야 하나요?

쉬는 날을 걸러 내는 목적이라면 getRestDeInfo 쪽이에요. 공식 활용가이드 v1.4는 getRestDeInfo를 '월별로 구분(공휴일), 요일, 공휴일 여부 등의 정보를 제공한다. 휴일 정보에 대한 조회로 제헌절은 해당 오퍼레이션에서 제공되지 않는다.'라고 설명하고, getHoliDeInfo는 '연, 월별로 구분(국경일), 요일, 공휴일 여부 등의 정보를 제공한다. 국경일에 대한 정보 조회로 제헌절은 해당 오퍼레이션에 포함되나 isHoliday=N 으로 출력된다.'라고 설명해요. 다만 이 문서의 변경일은 2020-06-09이고 포털 페이지 수정일은 2023-03-29인데, 「공휴일에 관한 법률」은 2026년에 두 번 개정됐어요. 제헌절을 넣은 개정이 2026-05-11 시행이고, 노동절을 넣은 개정이 2026-05-01 시행이에요. 문서 두 개의 시점이 그보다 앞서요. 그래서 제헌절에 대한 저 두 문장을 코드의 전제로 굳히지 마시고, 내 서비스키로 실제 응답을 받아 확인하는 편이 안전해요.

호출했는데 에러가 나요. 어디부터 봐야 하나요?

돌아온 코드로 원인을 가를 수 있어요. 2026-08-05에 직접 호출해 본 결과, serviceKey 파라미터를 아예 빼면 HTTP 401이 오고 응답 본문은 OpenAPI_ServiceResponse 아래 cmmMsgHeader로 오는데 errMsg는 SERVICE_KEY_IS_NULL, returnAuthMsg는 '서비스 접근거부', returnReasonCode는 20이었어요. 등록되지 않은 문자열을 키로 넣으면 HTTP 403에 SERVICE_KEY_IS_NOT_REGISTERED_ERROR, '등록되지 않은 서비스키', 코드 30이 돌아왔고요. 그런데 같은 키로 존재하지 않는 오퍼레이션명을 넣었더니 HTTP 400에 NO_OPENAPI_SERVICE_ERROR, '해당 오픈API 서비스가 없거나 폐기됨', 코드 12가 왔어요. 즉 게이트웨이가 키를 검사하기 전에 경로를 먼저 갈라요. 그러니 400이면 오퍼레이션명 오타를 먼저 보고, 401이면 serviceKey 파라미터가 빠졌는지 보고, 403이면 키 문자열과 활용신청 상태를 보세요.

일요일과 토요일도 이 API로 판정하면 되나요?

주말은 API에 묻지 말고 코드에서 요일로 판정하는 편이 나아요. 근거가 두 가지 있어요. 하나는 요일이 네트워크 없이 계산되는 값이라는 점이에요. 어느 언어에나 요일을 구하는 기능이 있으니 호출 한 번을 아끼고 실패 지점도 하나 줄일 수 있어요. 다른 하나는 공공데이터포털에 '한국천문연구원_일요일 정보조회'라는 별개 데이터셋이 데이터셋 번호 15125130으로 따로 올라와 있다는 점이에요. 일요일을 굳이 별도 데이터셋으로 떼어 두었다는 건 특일 정보 쪽 응답에서 그걸 기대하기 어렵다는 신호로 읽는 편이 안전해요.

한 번 받아서 저장해 두면 일 년은 안 받아도 되나요?

그렇게 두면 임시공휴일과 뒤늦게 지정된 대체공휴일을 놓쳐요. 공식 활용가이드의 기타참고사항 절은 '데이터 업데이트는 각 오퍼레이션 별로 연 1회 진행 됩니다.(1년치 데이터 일괄 업데이트)'라고 적어 두었지만, 바로 이어서 '추가로 임시공휴일 등 갑작스럽게 발생하는 데이터가 생길 경우 데이터는 바로 업데이트 되며(최대 1일 이내), 대체공휴일이 추가로 지정되는 경우 대통령령이 공식적으로 시행된 이후에 업데이트 되오니 참고 부탁 드립니다.'라고도 적어요. 포털의 공휴일 정보 조회 기능 설명에도 '(대체공휴일의 경우, 법제처 심사, 국무회의, 대통령의 승인 등 절차를 거쳐 관보에 정식 공포 된 이후에 적용)'이라는 괄호가 붙어 있고요. 그러니 캐시는 두되 갱신 주기를 하루 한 번 정도로 잡아 두세요.

내년, 내후년 날짜도 미리 받아 둘 수 있나요?

받을 수 있는 시점이 정해져 있어요. 공식 활용가이드 기타참고사항 절은 '특일정보의 경우 6~8월 경 과학기술정보통신부에서 월력요항 정보를 공식적으로 발표한 이후에 차차년도 데이터를 먼저 업데이트 합니다.(현재연도 기준 +2년)'라고 적어요. 같은 절은 '그 외 기념일, 24절기, 잡절은 11경 업데이트 됩니다.'라고도 덧붙이고요. 그래서 먼 미래 날짜를 조회했을 때 결과가 비어 있는 것은 호출이 잘못된 게 아니라 아직 채워지지 않은 구간일 수 있어요. 자동화 쪽에서는 이 빈 결과를 '쉬는 날 아님'으로 단정하지 않도록 처리하는 게 중요해요.

📚 함께 읽으면 좋은 글 (Related Posts)

AI 업무 자동화 더 보기 →
카카오톡 나에게 보내기 API로 자동화 알림 채널 만들기 — 토큰 만료 대비까지 2026
ai-automation2026-08-04

카카오톡 나에게 보내기 API로 자동화 알림 채널 만들기 — 토큰 만료 대비까지 2026

자동화는 다 만들었는데 알림만 카카오톡으로 받고 싶을 때 쓰는 나에게 보내기 API를 정리했어요. 앱 만들기와 talk_message 동의항목, 액세스 토큰과 리프레시 토큰의 만료 구조, n8n HTTP 요청 설정, 두 달째에 조용히 멈추는 자리를 막는 자동 갱신 설계까지 카카오 공식 문서 기준으로 담았습니다.

아이폰 단축어 자동화 실전 7가지 2026 — 모델 사용 동작으로 요약·번역·정리까지
ai-automation2026-08-03

아이폰 단축어 자동화 실전 7가지 2026 — 모델 사용 동작으로 요약·번역·정리까지

회사가 외부 자동화 서비스를 막아도 아이폰 한 대면 되는 일이 있어요. iOS 26 단축어 앱의 '모델 사용' 동작이 온디바이스·비공개 클라우드 컴퓨팅·확장 프로그램 세 경로를 고르게 해 주는 지점을 축으로, 업무 레시피 7가지와 개인용 자동화 트리거 분류, 지원 기종·언어 자가진단, 안드로이드 대안까지 애플 공식 안내를 근거로 정리했어요.

AI 전자책·템플릿 환불 요구, 어디까지 거절되나 2026 — 청약철회 제한이 성립하는 2단 조건
ai-revenue2026-08-05

AI 전자책·템플릿 환불 요구, 어디까지 거절되나 2026 — 청약철회 제한이 성립하는 2단 조건

AI로 만든 전자책과 템플릿을 파는 쪽에서 구매자의 환불 요구를 거절할 수 있는 요건을 정리했어요. 전자상거래법 제17조와 시행령 제21조의2 원문을 법제처 공개 API로 직접 받아, 제한 사유에 해당하는 1단과 표시·시험 사용 상품을 갖추는 2단이 어떻게 나뉘는지, 한 단만 빠져도 왜 거절이 성립하지 않는지까지 조문 번호와 함께 짚었어요.