/cit srp r=hts/cnjdlv.e/p/emi@0ds/emi.i.s>/cit srp r=.iae/uiitrciev.s>/cit
본문 바로가기
카테고리 없음

티스토리 API 자동화, 3가지 숨은 오류와 해결법

by Money복사기 2026. 9. 24.

티스토리 API 자동화 작업 중 문서에 없는 동작 때문에 새벽까지 디버깅을 한 경험이 있다면, 이 글이 바로 그 답입니다. 오늘 밤(2026-09-23) 5개의 글을 수정하다 발견한 API의 '조용한 거짓말' 3가지를 실제 디버깅 로그 기반으로 풀어보겠습니다.

핵심 요약 * POST 요청에 id를 넣으면 수정이 아닌 새 글 발행이 됨 (212번 유지, 213번 생성) * 본문 내 이미지만으로는 썸네일이 생성되지 않음, thumbnail 필드 필수 * HTML 추출 시 & 이스케이프 처리 누락 시 썸네일 깨짐 (218번 글 사례)

도입: 문서가 빠뜨린 디테일, 새벽 디버깅의 기록

어젯밤, 블로그 자동화 파이프라인의 글 5개를 일괄 수정하는 작업을 진행했습니다. 1인 개발자로서 자동화 스크립트를 직접 만지작거리다 보면, '이 정도면 되겠지'라는 안일함은 곧바로 에러 코드로 찾아옵니다. 특히 비공식 API를 다룰 때는 공식 문서에 없는 '실제 동작'과 '문서상 동작'의 괴리를 체감하게 됩니다.

제가 겪은 상황은 단순했습니다. 기존 글 5개의 제목과 본문을 업데이트하는 작업이었죠. 하지만 스크립트가 종료된 후 블로그를 확인했을 때, 원본 글은 그대로 남아 있었고 그 옆에 똑같은 제목의 새 글이 5개 더 생성되어 있었습니다. 총 10개의 글이 나란히 줄을 선 모습이었죠. 이 순간, 뭔가 근본적인 부분이 잘못되었다는 걸 직감했습니다.

새벽 시간대의 코딩 작업 공간
📷 Photo by Daniil Komov on Pexels

Q. 티스토리 글 수정 API는 어떤 요청을 보내야 하나요?

글을 수정하려면 PUT /manage/post/{id}.json 요청을 보내야 합니다. 단순히 POST 요청에 id 파라미터를 포함시키는 방식은 수정이 아닌 새 글 생성으로 처리됩니다. 이는 티스토리 API의 RESTful 원칙과 다른 독특한 동작입니다.

거짓말 1: POST에 id를 넣으면 수정되는 줄 알았는데

예상했던 것: 일반적인 REST API 관례에 비추어 보았을 때, 리소스 식별자(id)를 포함하여 POST 요청을 보내면 해당 리소스를 업데이트하거나, 그렇지 않으면 생성하는 로직을 기대했습니다. 많은 프레임워크에서 'upsert' 개념을 지원하거든요. 그래서 저는 POST /manage/post.json 엔드포인트에 기존 글의 id 값을 본문에 담아 전송했습니다.

실제 동작: 서버는 id 필드를 무시하고, 요청된 데이터를 바탕으로 새로운 글을 발행했습니다. 결과적으로 원본 글(212번)은 그대로 있었고, 동일한 제목과 내용으로 새 글(213번)이 생성되었습니다. 5개 글을 수정하려다 보니, 5개의 원본과 5개의 중복 글이 총 10개로 늘어나버렸습니다.

해결: 문서를 다시 정독하니, 글 수정은 반드시 PUT /manage/post/{id}.json을 사용해야 한다고 적혀 있었습니다. 저는 이 부분을 무시하고 있었죠. 스크립트를 수정하여 HTTP 메서드를 PUT으로 변경하고, URL 경로에 글 번호를 직접 매핑하도록 로직을 바꿨습니다.

"문서가 말하지 않아도, 메서드가 답합니다. POST는 생성, PUT은 수정."

[CHART: compare | 요청 방식별 결과 | POST+id:새글생성/PUT+id:정상수정 | 예상 | 실제]

Q. 중복된 글은 어떻게 삭제해야 하나요?

관리자 페이지의 '글 목록'에서 중복된 글(213번 등)을 선택하여 삭제하면 됩니다. API를 통한 일괄 삭제는 위험할 수 있으므로, 소량(5개)이라면 직접 삭제하는 것이 안전합니다. 이후 스크립트 실행 전 항상 '현재 존재하는 글 목록'을 조회하여 id 매핑을 확인하는 단계를 추가해야 합니다.

거짓말 2: 본문에 이미지가 있으면 썸네일이 생기는 줄 알았는데

예상했던 것: 블로그 플랫폼의 일반적 동작 방식에 따르면, 본문 안에 <img> 태그로 이미지가 포함되어 있다면, 목록 화면에서 자동으로 해당 이미지를 썸네일로 추출해 보여줄 거라 생각했습니다. 자동화 스크립트는 본문 HTML에 이미지만 제대로 삽입하면 나머지는 플랫폼이 알아서 처리해줄 것이라고 믿었거든요.

실제 동작: 스크립트 실행 후 블로그 목록을 확인했을 때, 5개 글 중 4개는 정상적으로 썸네일이 표시되었습니다. 하지만 1개 글(218번)은 썸네일 영역이 하얀색으로 비어 있었습니다.

잠시 당황했습니다. 4개는 되는데 왜 1개만 안 되는 걸까요? 코드 차이를 비교해보니, 성공한 4개는 본문에 이미지가 1장 이상 있었지만, 실패한 1개는 본문에 이미지가 없었지만 thumbnail 필드가 비어 있었습니다. 아니, 더 정확히 말하면, 저는 썸네일을 위해 별도의 필드를 설정하지 않았습니다.

해결: 티스토리 API에서는 본문 이미지와 무관하게, 목록 썸네일은 thumbnail 필드를 통해 명시적으로 지정해야 합니다. 이 필드는 kage@로 시작하는 특수한 URL 형식을 요구합니다.

  • 필드 형식: thumbnail=kage@<a>/<b>/<c>/<file>?<q>
  • 적용 방법: PUT 요청 시 thumbnail 파라미터에 위 형식의 값을 넣어야 합니다.

그 1개 글(218번)은 제가 본문에 이미지를 넣지 않은 채로 실험했던 글이었기 때문에, thumbnail 필드가 비어있어 썸네일이 생성되지 않은 것이었습니다. 5개 중 4개가 된 이유는 나머지 4개는 우연히 본문에 이미지가 있었고, 플랫폼이 이를 기본 썸네일로 채택했기 때문일 수 있지만, 신뢰할 수 있는 방법은 thumbnail 필드를 항상 명시하는 것입니다.

노트북으로 글을 쓰는 모습
📷 Photo by Polina Kovaleva on Pexels

Q. thumbnail 필드의 kage@ 형식은 어디서 찾을 수 있나요?

기존에 발행된 글의 HTML 소스를 확인하거나, 이미지 업로드 시 API가 반환하는 kage URL을 기록해 두면 됩니다. 이 URL은 공개 이미지 경로이므로, 이를 thumbnail 필드에 그대로 사용해야 합니다.

거짓말 3: HTML에서 긁은 이미지 URL을 그대로 쓰면 될 줄 알았는데

예상했던 것: 공개된 블로그 페이지의 HTML 소스에서 이미지 URL을 추출하여 thumbnail 필드에 넣으면 되리라 생각했습니다. 브라우저에서 보이는 URL이니까, API에서도 동일하게 동작할 거라 믿었거든요.

실제 동작: HTML 소스에서 추출한 URL은 &amp; 형태로 이스케이프되어 있었습니다. 이를 그대로 thumbnail 필드에 넣었더니, 썸네일이 깨진 상태로 표시되었습니다. 218번 글의 썸네일이 하얀색으로 보인 진짜 이유였습니다.

해결: HTML 엔티티를 디코딩하는 과정이 필요합니다. &amp;&로 변환하는 unescape 또는 html.unescape (파이썬 기준) 처리를 반드시 수행해야 합니다.

import html

raw_url = "kage@.../file.jpg?width=500&amp;height=500"
decoded_url = html.unescape(raw_url)
# 결과: kage@.../file.jpg?width=500&height=500

이 작은 이스케이프 처리를 놓치는 순간, 썸네일은 깨지고 맙니다. 특히 자동화 스크립트에서 HTML 파서를 사용할 때, 원본 문자열을 그대로 가져오는 경우가 많기 때문에 주의가 필요합니다.

Q. & 오류는 어떻게 방지할 수 있나요?

HTML 파서(BeautifulSoup 등)를 사용할 때, img 태그의 src 속성을 가져오면 자동으로 디코딩된 값을 반환합니다. 원본 HTML 문자열을 직접 정규식으로 추출하는 경우, 반드시 html.unescape를 적용해야 합니다.

정리: 디버깅 시간, 가장 비싼 자원

이번 경험을 통해 깨달은 점은, 자동화를 망치는 건 AI의 성능이 아니라 문서에 없는 API의 실제 동작이라는 것입니다. 특히 비공식 API를 다룰 때는, 문서가 '상식적으로' 작동한다고 가정하는 순간이 가장 위험합니다.

비공식 API를 사용할 때 체크리스트 3줄을 정리해 보겠습니다.

  1. HTTP 메서드 확인: 수정은 PUT, 생성은 POST로 명확히 구분한다.
  2. 필드 명시: 본문에 의존하지 않고, thumbnail 등 메타데이터 필드를 항상 명시적으로 설정한다.
  3. 인코딩 검증: HTML에서 추출한 URL은 반드시 이스케이프 해제(unescape) 후 사용한다.

[CHART: timeline | 디버깅 과정 | 22:00:스크립트 실행, 23:30:중복 글 발견, 00:15:PUT 수정, 01:00:썸네일 오류 확인, 01:30:unescape 적용, 02:00:정상 동작]

Q. 비공식 API 사용 시 가장 큰 리스크는 무엇인가요?

서비스 정책 변경 시 API가 갑자기 폐지되거나 동작이 바뀌는 점입니다. 따라서 항상 '실패 시 수동 복구' 절차를 준비해 두어야 합니다.

다음 글 예고

이 삽질들로 뜯어고친 발행 파이프라인을 기반으로, 다음 실험은 '자동 태그 부여'와 '이미지 최적화'를 시도해 볼 예정입니다. API가 제공하는 태그 목록을 분석하여, 콘텐츠 유형에 맞는 태그를 자동으로 매핑하는 로직을 개발 중입니다.

자주 묻는 질문

Q. 티스토리 API 키는 어디에서 발급받나요?

티스토리 개발자 센터(https://www.tistory.com/apps)에서 '내 앱'을 등록하여 Client ID와 Client Secret을 발급받을 수 있습니다.

Q. PUT 요청 시 전체 필드를 보내야 하나요?

아니요, 수정하려는 필드만 보내도 됩니다. 하지만 title, content, thumbnail 중 하나라도 누락하면 해당 필드가 초기화될 수 있으므로, 기존 값을 조회하여 함께 보내는 것이 안전합니다.

Q. 썸네일 이미지는 어떤 해상도가 적당하나요?

목록 화면에서 선명하게 보이려면 최소 500x500 픽셀 이상의 정사각형 이미지를 권장합니다. 너무 작으면 픽셀화가 심해집니다.

Q. API 호출 빈도 제한이 있나요?

네, 비공식 API이지만 과도한 호출 시 IP 차단될 수 있습니다. 1초당 1회 이하로 요청 간격을 두고, 불필요한 조회를 피하는 것이 좋습니다.

Q. 이 방법은 공식 API와 다른가요?

네, 티스토리 공식 API 문서에는 이 정도의 디테일(특히 thumbnail 필드의 정확한 형식과 unescape 필요성)이 명시되어 있지 않을 수 있어, 직접 테스트를 통한 검증이 필수적입니다.

혹시 티스토리 API로 자동화를 시도하면서 비슷한 '조용한 거짓말'에 걸려본 적 있으신가요? 댓글로 공유해 주세요.

티스토리API #블로그자동화 #개발자삽질 #API디버깅 #인디해커 #티스토리글수정 #웹크롤링

댓글


TOP

Designed by 티스토리