path
Jin's Lab
코드로 실험하고 기록하는 개발 일지 · J.Lab

Jin's Lab

코드로 실험하고 기록하는 개발 일지. 커리어와 삶의 방향을 탐색하며 기록하는 공간입니다

api-error

Blogger API 400 오류 해결기: 밀리초 누락과 백데이팅 실패 대처법

J.Lab ·
목차

    최근 개인 프로젝트의 일환으로 과거 기록들을 블로그로 옮기는 마이그레이션 작업을 진행하고 있었다. Gemini API를 활용한 메타데이터와 이미지 생성 단계까지는 아무런 문제 없이 물 흐르듯 성공했다. 하지만 기쁨도 잠시, 본격적으로 데이터를 블로그에 발행하는 publishToBloggerMig 단계에서 청천벽력 같은 400 에러를 마주했다.

    호기롭게 준비해 둔 대기 큐의 169건의 데이터가 전부 대기 상태로 멈춰 서 있는 모습을 보니 눈앞이 아득해졌다. 로그에 찍힌 에러 메시지는 명확하게 INVALID_ARGUMENT를 가리키고 있었지만, 도대체 어떤 인자가 잘못되었는지 구체적으로 알려주지 않아 답답함이 밀려왔다. 무엇이 문제였는지 차근차근 디버깅하며 삽질했던 해결 과정을 공유해 보려고 한다.

    JSON 페이로드 에러 메시지가 표시된 모니터 화면의 아이소메트릭 일러스트

    원인 분석: 정상 작동 스크립트와의 처절한 페이로드 비교

    이 문제를 해결하기 위해 가장 먼저 한 일은 기존에 정상적으로 잘 작동하고 있던 IssueLog 스크립트의 페이로드와 이번 마이그레이션용 페이로드를 하나하나 대조해 보는 것이었다. 두 API 호출은 거의 동일한 구조를 가지고 있었기에, 아주 미세한 차이가 Blogger API 400 오류를 유발하고 있을 것이라 확신했다.

    꼼꼼히 비교해 본 결과, 눈에 띄는 단 하나의 차이점은 바로 글이 발행될 시간을 지정하는 published 필드였다. 기존 정상 작동 스크립트는 이 필드 없이 현재 시간으로 자동 발행되도록 하고 있었고, 이번 마이그레이션 스크립트는 과거 날짜로 백데이팅하기 위해 특정 날짜 데이터를 밀어 넣고 있었다. 바로 이 지점이 400 badRequest 에러의 출발지였다.

    두 개의 코드 파일을 시각적으로 비교 분석하는 아이소메트릭 일러스트

    범인은 RFC3339 포맷의 밀리초(.000) 누락

    구글 Blogger API의 공식 문서를 다시 뒤져보니 published 필드는 RFC3339 포맷의 시간 문자열을 요구하고 있었다. 내가 기존에 자바스크립트로 생성해서 보내던 ISO 문자열도 언뜻 보기에는 RFC3339 규격에 맞는 것처럼 보였기에 처음에는 무엇이 문제인지 이해하기 어려웠다.

    하지만 결정적인 단서는 API가 정상적으로 응답할 때 보내주는 날짜 데이터 형태에 있었다. Blogger API가 반환하는 모든 시간 값에는 소수점 아래 세 자리의 밀리초가 항상 포함되어 있었다. 마이그레이션용으로 생성하던 날짜 문자열에 밀리초가 누락되어 검증기를 통과하지 못하고 계속 400 에러를 뱉어냈던 것이다.

    API 에러를 해결하고 데이터가 순조롭게 파이프라인을 통과하는 모습의 아이소메트릭 일러스트

    헬퍼 함수와 안전한 자동 폴백 구현

    원인을 파악했으니 해결책을 적용할 차례였다. 가장 먼저 날짜 오프셋을 정규화하고 반드시 밀리초 포맷을 포함하도록 보정해 주는 toBloggerRfc3339() 헬퍼 함수를 작성했다. 이 함수는 어떤 날짜가 들어오든 Blogger API가 안전하게 받아들일 수 있는 완벽한 RFC3339 문자열로 변환해 준다.

    동시에 코드의 안정성을 높이기 위해 Blogger API 호출부를 공통 래퍼 함수인 postToBlogger()로 완전히 분리해 주었다. 여기에 만약 백데이팅을 시도하다가 날짜 포맷 문제나 기타 이유로 실패할 경우, published 필드를 아예 제거하고 현재 시간으로 우선 발행을 완료하게 만드는 자동 재발행 폴백 로직을 추가했다.

    이 덕분에 오랜 시간 멈춰 서 있던 169건의 대기 큐 데이터가 단 하나의 누락도 없이 깔끔하게 백데이팅에 성공하며 발행을 마칠 수 있었다. 사소한 포맷 규격 하나가 전체 자동화 시스템을 마비시킬 수 있다는 뼈아픈 교훈을 얻은 값진 경험이었다.

    api-error blogger-api google-blogger javascript-automation payload-validation rfc3339
    ← 이전 글
    최근 게시물
    다음 글 →
    이전 게시물
    ≡ 글 목록으로
    소개
    path
    J.Lab

    커리어와 삶의 방향을 탐색하며
    기록하는 공간입니다

    카테고리
    403 Forbidden Error 1 AdSense 1 AdSense Bot Detection 1 AI Automation 1 AI Image Generation 1 ai-automation 2 AI-Prompting 1 AIBlogAutomation 1 AICodeLog 1 AIContentGeneration 1 AIImageGeneration 1 AIWritingErrors 1 API Automation 2 API Retry Design 1 api-automation 1 API-Deprecation 1 api-error 1 api-fallback 1 api-retry-strategy 1 api-troubleshooting 1 APIDebugging 1 APIError 1 APIErrorHandling 1 APIIntegration 1 APITokenRenewal 1 AppsScript 1 appsScriptAutomation 1 AutomatedBlogging 1 automation 1 Automation 2 AutomationTroubleshooting 1 Backoff Algorithm 1 Base64Encoding 1 BatchProcessing 1 blog-automation 1 blog-customization 1 blog-migration 3 Blog-Sorting 1 blog-strategy 1 blog-theme-customization 1 blog-workflow 1 blogautomation 1 BlogAutomation 2 Blogger 4 Blogger API 2 Blogger Automation 1 Blogger SEO 1 blogger-api 3 blogger-automation 1 blogger-error-400 1 blogger-labels 1 blogger-seo 1 blogger-tips 1 Blogger-Tips 1 BloggerAPI 3 BloggerBypath 1 BloggerCustomization 2 BloggerFavicon 1 BloggerTemplate 1 BloggerTemplateEditing 1 BloggerTheme 1 BloggerThemeCustomization 1 BloggerXMLStructure 1 Blogging-Automation 1 BloggingTools 1 BlogQuality 1 BlogSpot 1 BWidgetBIncludable 1 CardClickHandler 1 CDATA 1 clamping-text 1 Code Integration 1 codelog 1 CodeLog 1 codeRefactoring 1 contentsequencing 1 cost-reduction 1 CSSOverlay 1 data-parsing 1 DatabaseDesign 1 DataRecovery 1 DateInjection 1 Debugging 2 dev-journey 1 DeveloperJourney 2 DevJourney 1 display-none-seo 1 dom-manipulation 1 dynamic-menu 1 Error-Handling 1 ErrorHandling 1 Execution Timeout 1 ExecutionLimit 1 exponential-backoff 1 FactChecking 1 FaviconEmbedding 1 Feed-API 1 filesystem 1 Flat Illustration 1 FluxModel 1 FreeAIImage 1 FrontEndDev 1 FrontendTips 1 GAS Blogger API 1 gas-automation 1 gas-optimization 1 gas-trigger 1 GASTimeout 1 gasTriggerManagement 1 GCP Project Linkage 1 Gemini 1 Gemini API 1 gemini-api 1 GeminiAPI 1 GeminiPrompt 1 GeminiPromptEngineering 1 GmailRestrictions 1 Google Apps Script 7 Google Discover 1 google-apps-script 3 Google-Apps-Script 1 google-blogger 1 googleAppsScript 1 GoogleAppsScript 6 googlesapps-script 1 hero-image 1 HTMLWidgetBlogger 1 http-429 1 HuggingFace 1 HuggingFaceAPI 1 ico-generator 1 Image Optimization 1 image-automation 1 image-optimization 1 In-App Browser 1 invalid-argument 1 javascript 3 JavaScript 2 javascript-automation 1 javascript-toc 1 jlab-codelog 1 JLabDevLog 1 json-schema 1 label-length-limit 1 linux 1 meta-description 1 Negative Prompt 1 notion-api 1 notion-database 1 notion-gas-integration 1 NotionAPI 1 NotionAutomation 1 notionintegration 1 NotionIntegration 1 OAuth Scope 1 pagination 1 payload-validation 1 permalink-management 1 PersonaDesign 1 pil-image-processing 1 Pinterest 1 Pollinations 1 Pollinations Flux 1 pollinations-api 1 PollinationsAI 1 PositionAbsolute 1 Prompt Design 1 Prompt Engineering 1 prompt-engineering 1 Prompt-Engineering 1 PromptEngineering 1 publishorder 1 python-favicon 1 queue-stuck 1 RandomDelay 1 rate-limiting 1 Refactoring 1 rfc3339 2 Robots Meta Tag 1 RSS Feed 1 scriptNotFound 1 Search Engine Optimization 2 Search-Engine-Optimization 1 SEO Tips 1 seo-optimization 4 SEO-Optimization 1 seriesmanagement 1 SidebarLinks 1 SNSMarketing 1 SVGIcon 1 table-of-contents 1 TechJournal 1 Template 1 ThreadsAPI 1 tistory-migration 1 transparent-favicon 1 triggerCleanup 1 Troubleshooting 1 unzip 1 URL Slug 1 vanilla-js 1 Web Development 1 Web Publishing 2 Web Security 1 web-development 1 Web-Development 1 web-development-tips 1 web-performance 1 web-scraping 1 WebAccessibility 1 WebDevelopment 3 WebDevelopmentTips 1 WebDevJourney 1 windows 1 WorkflowAutomation 1 XMLParser 1 XMLSpecialCharacters 1 XMLTheme 1 zip 1
    인기 글
    GAS에서 Blogger API 403 오류 완전 정복 — appsscript.json 스코프와 GCP 프로젝트 연결
    GAS에서 Blogger API 403 오류 완전 정복 — appsscript.json 스코프와 GCP 프로젝트 연결
    Google Apps Script 실행 시간 6분 제한 — Gmail 계정 함정과 랜덤 딜레이 설계
    Google Apps Script 실행 시간 6분 제한 — Gmail 계정 함정과 랜덤 딜레이 설계
    Blogger 테마 XML 직접 뜯어봤더니 알게 된 것들
    Blogger 테마 XML 직접 뜯어봤더니 알게 된 것들
    다른 블로그
    IssueLog
    IssueLog
    issuelog.jinbytes.com
    KidStory
    KidStory
    kidstory.jinbytes.com
    IT Story
    IT Story
    jinbytes.com
    © Jin's Lab · J.Lab · All Rights Reserved
    jinbytes.com · Powered by Blogger