Seung Hun

Notion api로 블로그 만들기 image 기간 제한 없이 사용하는 방법

notion.so_logo.png

안녕하세요. 오랜만에 글을 쓰네요. 오늘은 이 블로그를 만들면서 하나의 문제였던 image 기간 때문에 블로그 이미지가 사라지는 문제를 해결한 경험을 공유하겠습니다.

원본 코드는 이곳에 있습니다.

Notion Api 응답은 어떻게 올까?

우선 저는 @notionhq/client 이 라이브러리를 사용하여 만들었습니다. 이제 React의 useEffectEvent는 뭘까 ? 글을 기준으로 응답을 살펴보겠습니다.

notion.databases.query 응답

{ "tags": { "id": "%3Ch%60t", "type": "multi_select", "multi_select": [] }, "id": { "id": "DegF", "type": "number", "number": 4 }, "description": { "id": "M%5CZ%5B", "type": "rich_text", "rich_text": [ { "type": "text", "text": { "content": "useEffectEvent의 필요성, 사용 방법, 폴리필까지 한번에 알아보자", "link": null }, "annotations": { "bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default" }, "plain_text": "useEffectEvent의 필요성, 사용 방법, 폴리필까지 한번에 알아보자", "href": null } ] }, "publish": { "id": "M_%3E%60", "type": "checkbox", "checkbox": true }, "thumbnail": { "id": "pWE%60", "type": "files", "files": [ { "name": "thumbnail-maker_202537.jpg", "type": "file", "file": { "url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/0cde9f09-34e9-4761-9262-2c7efcbe4b59/993873e6-77db-4795-9890-686743b5c04d/thumbnail-maker_202537.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466Z775I5YQ%2F20250603%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250603T050127Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEDUaCXVzLXdlc3QtMiJGMEQCIBlp2maakipYfpUM9GC%2BImqQsuXTr1lLnUAbdq9S6sqaAiA8BT8cgpIrpjiuSX9cT%2B%2B3MOGBqwl%2B0FOkiIidQbGAtiqIBAj%2B%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAAaDDYzNzQyMzE4MzgwNSIMC50wq%2F4J29FabnCwKtwDKr5pSHoVb01pkAHFpjMKVAKm2wK4qFsUNGRXmOWAelkeqW8mmoFopZyKBe1iYZzQ8tTDyWA%2Fh6VPBfOnS5t9y05BYR1DhjTV3KmhylVNnFZwVa14A5lgGzPuwtHj0O3SYA4fmJPwPmLr06BzjnCzzel9GTY3bzf%2BMPDX9Wehmfs6Z1YzF%2B3FFR7NyJj4scAr6mTG3xoQEdjZ6HMKvTFsNCmBK40KAZ3PnUeHgC8HQN%2FyCf1Ukpwoq4wPhAvOo7DKJOJwabfNH4wsjmCmaY%2FBo4KfWJd6mg%2BxbdzSbAhtXGR%2BGCVHN6QqE0ECcoaP6Bwqr%2B0MZ2oBFSoms%2FTP0jCSFTF4xBl%2BK2ua22tDrczfzAx4rzHvNDWw0XOn0OUIn6iWjkkdw4z8RhALzIGNhRMG7qNmJKp73qkI6WcwhOF1kPmiyOdoToJ%2FvWB8R0WwR81zXZfEiQukOZ4CK%2FKd7w5CytPzSo4psjXHVigk74nx4xiOsE6UbjkBFbPQtTavOMGiKtsXrCFLzOgPDJhx1su4Up1VtFHPegyJRZ8rEF1BgfCHPsIRsF0QDp4QEsOeGUdL9j0tNSxlic3ls2toWVk7u2EP8obJUwU0%2BiAZWIJWDTHeln0ReuHj4IAmf0owroH6wQY6pgEi%2FVhezj6VtAKYc1my3nTkx7rL08RWwTRwW73hl5kSCzZzU0ofzWx4G%2FwZcnL9%2FofUxDJxiJpwy7mSDlagYLwsMNx62bkMYF9YqBXxynHS0tVLStnMDXnuIdgObMXlV0ozgXhQYaVnFW5IpxRf6or3HcWcREBMsj%2FxoRL4RfEMy8tbWy3c7oHtzB%2FkQTyhYy4LSGFStQilsGMPjg3rU3mbQFGuTz1X&X-Amz-Signature=16a090a38992071538513e0c354d58d53cce51a93af9aaf89222c6c22acd07a2&X-Amz-SignedHeaders=host&x-id=GetObject", "expiry_time": "2025-06-03T06:01:27.952Z" } } ] }, "publishDate": { "id": "sZx%3B", "type": "date", "date": { "start": "2025-03-07", "end": null, "time_zone": null } }, "title": { "id": "title", "type": "title", "title": [ { "type": "text", "text": { "content": "React의 useEffectEvent는 뭘까 ?", "link": null }, "annotations": { "bold": false, "italic": false, "strikethrough": false, "underline": false, "code": false, "color": "default" }, "plain_text": "React의 useEffectEvent는 뭘까 ?", "href": null } ] } }

응답이 오는 것을 확인할 수 있습니다.

"thumbnail": { "id": "pWE%60", "type": "files", "files": [ { "name": "thumbnail-maker_202537.jpg", "type": "file", "file": { "url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/0cde9f09-34e9-4761-9262-2c7efcbe4b59/993873e6-77db-4795-9890-686743b5c04d/thumbnail-maker_202537.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB466Z775I5YQ%2F20250603%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250603T050127Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEDUaCXVzLXdlc3QtMiJGMEQCIBlp2maakipYfpUM9GC%2BImqQsuXTr1lLnUAbdq9S6sqaAiA8BT8cgpIrpjiuSX9cT%2B%2B3MOGBqwl%2B0FOkiIidQbGAtiqIBAj%2B%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAAaDDYzNzQyMzE4MzgwNSIMC50wq%2F4J29FabnCwKtwDKr5pSHoVb01pkAHFpjMKVAKm2wK4qFsUNGRXmOWAelkeqW8mmoFopZyKBe1iYZzQ8tTDyWA%2Fh6VPBfOnS5t9y05BYR1DhjTV3KmhylVNnFZwVa14A5lgGzPuwtHj0O3SYA4fmJPwPmLr06BzjnCzzel9GTY3bzf%2BMPDX9Wehmfs6Z1YzF%2B3FFR7NyJj4scAr6mTG3xoQEdjZ6HMKvTFsNCmBK40KAZ3PnUeHgC8HQN%2FyCf1Ukpwoq4wPhAvOo7DKJOJwabfNH4wsjmCmaY%2FBo4KfWJd6mg%2BxbdzSbAhtXGR%2BGCVHN6QqE0ECcoaP6Bwqr%2B0MZ2oBFSoms%2FTP0jCSFTF4xBl%2BK2ua22tDrczfzAx4rzHvNDWw0XOn0OUIn6iWjkkdw4z8RhALzIGNhRMG7qNmJKp73qkI6WcwhOF1kPmiyOdoToJ%2FvWB8R0WwR81zXZfEiQukOZ4CK%2FKd7w5CytPzSo4psjXHVigk74nx4xiOsE6UbjkBFbPQtTavOMGiKtsXrCFLzOgPDJhx1su4Up1VtFHPegyJRZ8rEF1BgfCHPsIRsF0QDp4QEsOeGUdL9j0tNSxlic3ls2toWVk7u2EP8obJUwU0%2BiAZWIJWDTHeln0ReuHj4IAmf0owroH6wQY6pgEi%2FVhezj6VtAKYc1my3nTkx7rL08RWwTRwW73hl5kSCzZzU0ofzWx4G%2FwZcnL9%2FofUxDJxiJpwy7mSDlagYLwsMNx62bkMYF9YqBXxynHS0tVLStnMDXnuIdgObMXlV0ozgXhQYaVnFW5IpxRf6or3HcWcREBMsj%2FxoRL4RfEMy8tbWy3c7oHtzB%2FkQTyhYy4LSGFStQilsGMPjg3rU3mbQFGuTz1X&X-Amz-Signature=16a090a38992071538513e0c354d58d53cce51a93af9aaf89222c6c22acd07a2&X-Amz-SignedHeaders=host&x-id=GetObject", "expiry_time": "2025-06-03T06:01:27.952Z" } } ] },

이 응답에 주목해 보겠습니다.

expiry_time값이 있는데요. notion은 자체 s3에 expiry_time 시간 동안만 asset을 저장합니다. 저는 블로그를 SSG로 빌드를 해서 배포하기 때문에 저 expiry_time가 만료되면 더 이상 이미지를 불러올 수 없겠죠.

notion-to-md 응답

이번에는 notion-to-mdpageToMarkdown 응답 값을 살펴보겠습니다.

{ "type": "image", "blockId": "1afa463e-8303-8081-87f1-f5d413c0c3b7", "parent": "![1afa463e-8303-8081-87f1-f5d413c0c3b7:thumbnail-maker_202537.jpg](https://prod-files-secure.s3.us-west-2.amazonaws.com/0cde9f09-34e9-4761-9262-2c7efcbe4b59/3fb8b350-da78-45d8-8eba-65206fc344e2/thumbnail-maker_202537.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAZI2LB4663XRA3FW4%2F20250603%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20250603T052040Z&X-Amz-Expires=3600&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEDUaCXVzLXdlc3QtMiJHMEUCIQCI3GmP7S3MeOyO0I4CWG3NILw%2BSeRWo5n2RJpT3F26qwIgQISiWw%2F%2BIQcCKCDEOD2%2Bf9qq%2F2uGnbEWsKBFQi%2FuqnkqiAQI%2Fv%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARAAGgw2Mzc0MjMxODM4MDUiDI3N7GeZYfOTVH6r5yrcAwcnYzY6mmPpVHralqJFCTWdomLxle6Dgne0%2F3xM4lGa0pOd%2Fe%2BRTph54iCIBJDFXetO775Q%2F4zOWK0cseKsJSbgYVHRdgxErxkCIpIb1KobQbLSyJBcTa8FeZB%2FgUJza8W5l%2BFOnL7byZHKAO%2Fqe2DzBLjeWQ2eNPzUDXC9XtcwRj%2B%2BYjG62lBDT0MsxIrk%2FUrDZKuv9D5O5%2BH4S8edPfveEA%2FVRuiYHOyqKyM0fey94ANuqRqigXSLi4DF6xVRMgYPuhevhPR9zXYP4eXFLKhOOGkpeL2mm28j9pweI3OhMUFxnalzMjv5pA%2By%2BiX0BG4hhRa9M6nfIeIF3HN9bfLrjlX%2FmamBf8%2BxARSoKYCoSBA4pgSelHSKwgAEFyqmmaJzN1DGRYFsPrrXPwjACoX6Vq8d41rsxKLHt6wCRe4oXE2bpzfLPZkS9hfB4Z00zZKLfPqg7FrTVTXxObR1vucCs5slSu3ueqTcDnzyWDK%2BRooCrn9JjKWfVN1lsqTDgHxxnm4wbaD8%2Bo328lDS1jwLI7SnAVRT%2FBEF8s8QEl37XoQM6BJAnB5Surjc%2FtTyM2N4fpD%2BLDuwqrlIAQRqcqELvGLqLQL8NG4UDml1NKVRUvt9nHkTwZRZaJ0%2FMLGB%2BsEGOqUBiWNXJJeOAg5qy5HIJmg5OjhWiD6wKSYH7ggi4NpinWDaRSf6koX8P12qUiOaKQFwAftghwai5A9hnG9zu3bIHlewe8wpEBhjEh00TwfNaAcBTC37Y9YMYkR47%2FB3eYaQW3un9GENfQTIpgU%2F8hoXugYTLQmu1K70Poenq7vbkClBAOOI9LVHy0k3T%2BW%2Be43a28jUeF6U31Uv13I7b%2BolRyRR98EJ&X-Amz-Signature=c3d830518020693647a55495eec2d0cf9955dd259b519ec148ab41470741f030&X-Amz-SignedHeaders=host&x-id=GetObject)", "children": [] }

이런 식으로 응답이 오는 것을 확인할 수 있습니다.

publish 기능을 활용하여 image 가져오기

Notion 페이지를 publish를 하면 이런 식으로 https://nimble-monkey-1a1.notion.site/React-useEffectEvent-1afa463e830380b59415c0a2b503a729 url이 나옵니다.

이제 우리는 https://nimble-monkey-1a1.notion.site base url을 얻었습니다. 이제 image src로 들어온 https://prod-files-secure.s3.us-west-2.amazonaws.com/0cde9f09-34e9-4761-9262-2c7efcbe4b59/bb8a9cc…. 값을 수정하여 publish page에서 이미지를 가져오는 함수를 가져오겠습니다.

const NOTION_PUBLIC_URL = "https://nimble-monkey-1a1.notion.site"; interface CreateNotionImageUrlParams { fileUrl: string; id: string; width?: number; } export function createNotionImageUrl({ fileUrl, id, width, }: CreateNotionImageUrlParams): string { const encodedUrl = encodeURIComponent(fileUrl.split("?")[0]); return `${NOTION_PUBLIC_URL}/image/${encodedUrl}?table=block&id=${id}&cache=v2&width=${width}`; }

이제 Image를 사용하는 부분에서

return ( <Image {...rest} className={css({ display: "block", margin: "0 auto", marginBottom: SPACE.sm, })} alt={alt || ""} src={createNotionImageUrl({ fileUrl: src || "", width: IMAGE_SIZE, id: blockId, })} width={IMAGE_SIZE} height={IMAGE_SIZE} /> ); }

이런 식으로 사용할 수 있습니다.

%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2025-06-03_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_2.43.19.png