Post

깃허브 블로그와 노션 연동하기 [프로젝트]

깃허브 블로그와 노션 연동하기 #프로젝트

[관련 포스팅]

깃허브 블로그와 노션 연동하기 [배경]

깃허브 블로그와 노션 연동하기 [인프라]

깃허브 블로그와 노션 연동하기 [프로젝트]

깃허브 블로그와 노션 연동하기 [결과]

깃허브 블로그와 노션 연동하기 [프로젝트]

노션에서 마크다운으로 변환

우선 노션에서 어떤 식으로 API를 호출하는지 알아보기 위해 노션 공식사이트와 개발자도구를 통해 알아봤다.

공식 API 문서를 확인하니 Block 별로 데이터를 받아 변환할 수 있었다. 하지만, 이럴 경우 코드 작업이 많아질 것 같아 다른 방법을 알아봤다. Notion Export API를 찾아봤는데, 공식 문서에는 없었다. 개발자도구를 통해 확인하니, Secret API를 통해 Export Markdown을 지원했다. 시크릿 API를 사용하는 방법은 GitHub에서 확인할 수 있다.

선택한 방법

위에서 언급했듯이 노션에서 마크다운으로 변환하는 방법은 두 가지가 있다.

  1. Secret API를 이용하여 노션에서 제공하는 Export Markdown 방식을 사용하거나
  2. 공개된 API를 통해 페이지의 데이터를 읽고 이것을 노션에서 마크다운 형식으로 직접 바꾸는 방식이다.

나는 여기서 두 번째 방법을 사용한다. 배경편에서 언급했던 프로젝트를 시작하게된 문제점이 그대로 있다. 노션의 Export 기능은 마크다운으로 완벽하게 변환하지 못한다. 노션이 편리 상으로 제공하는 기능들로 인해 마크다운 문법이 깨지는 오류가 주로 발생한다.

예를 들어 - ABC 의 경우 마크다운으로 변환하면 아래의 사진처럼 깨진다. 그렇기에 직접 변환하는 방식을 선택했으며, 해당 방식은 커스터마이징이 가능하다는 추가적인 장점이 있다.

Untitled.png

변환 방식

노션의 페이지는 여러 개의 Block들로 구성된다. 노션은 마크다운을 문법을 기반으로 하기에, 이 Block들은 마크다운 문법과 유사하다. 그래서 Notion API 문서에 나와 있는 노션의 Key 값들과 Key에 알맞은 마크다운 문법을 직접 맵핑하여 변환할 수 있다.

한번 예시를 통해 알아보자. 아래는 Block Object의 JSON 파일이다. 다음은 “Lacinato kale”이라는 heading2 문법을 나타낸다. 우리는 여기서 type을 읽어 “heading2”를 “##”으로 변환하고 뒤에 텍스트를 붙여넣어주면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"type": "heading_2",
	"heading_2": {
		"rich_text": [
			{
				"type": "text",
				"text": {
					"content": "Lacinato kale",
					"link": null
				},
				"annotations": {
					"bold": false,
					"italic": false,
					"strikethrough": false,
					"underline": false,
					"code": false,
					"color": "green"
				},
				"plain_text": "Lacinato kale",
				"href": null
			}
		],
		"color": "default",
    "is_toggleable": false
	}

직접 코드를 작성하다가, 나와 유사한 필요성을 느낀 사람이 있을 것 같았다. GitHub에서 찾아보니 오픈소스 프로젝트를 발견했다. 해당 프로젝트를 이용했다.

이미지 처리

문제상황

오픈소스 프로젝트를 이용하면, 대부분 변환이 가능하나 큰 문제가 되는 부분이 있었다. API로 이미지를 가져오기에, 이미지와 같은 미디어는 아래와 같이 링크를 통해서 가져왔다. 하지만, 이 링크는 S3 Presigned URL로 유효기간이 지나면 이미지를 참조할 수 없다.

1
2
3
4
5
6
"image": {
    "caption": [],
    "type": "file",
    "file": {
        "url": "https://prod-files-secure.s3.us-west-2.amazonaws.com/3b953ad7-a4bc-4b8b-877c-db94279d5db4/438974be-0026-455f-a4ea-eeebc12e1a37/maxresdefault.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential...",
    ...

블로그에 포스팅하기 위해서는 미디어를 다운받아야 했으며, 마크다운 문서에서 이미지 경로를 추후 업로드될 블로그 경로로 변경해야 했다.

해결 방법

Lambda에서 미디어는 별도로 추가 작업을 하며 처리했다.

  1. Block을 순회하며 미디어일 경우 API를 통해 별도로 다운로드를 진행한다.
  2. 마크다운 문서를 확인하여 파일경로를 S3 Presigned URL이 아닌 추후 업로드할 블로그의 미디어 경로로 변경한다.
  3. 블로그에 포스팅할 때, 위에서 지정한 경로에 맞게 미디어를 업로드한다.

포스팅

현재 블로그는 GitHub Pages를 통해 구성되어 있다. Jekyll에서 Chirpy테마를 이용하고 있다. 포스트는 /posts/{post_title} 경로에 업로드하고, 이미지는 /assets/img/{post_title} 경로에 업로드한다.

기존 포스팅 업데이트가 아닌 새로운 포스팅은 다음과 같은 방식으로 이뤄진다.

  1. 마크다운 문서와 이미지를 업로드한다.
  2. .sync/mapping.json 파일에 새로운 “page_id”, “update_date”, “post_title”을 추가한다.
  3. GitHub Actions이 자동으로 수행되며, 포스팅된다.

2번에서 진행한 mapping 파일을 통해 기존 포스팅 업데이트를 구분하며, 단순한 내용 업데이트일 경우 불필요한 작업을 최소화한다.

mapping 파일에서 3개의 데이터 중에 업데이트를 확인하는 데이터는 Page_ID이다. 노션의 Page ID는 페이지가 다른 곳으로 이동해도 변하지 않는다. 그렇기에 구분하는 요소를 Page ID로 설정했다. 나머지는 충분히 바뀔 수 있다.

인덱싱

인덱싱과 관련된 코드는 Google Search Console 인덱싱 자동화3, SQS 도입에서 확인할 수 있다.

SAM Template

위의 모든 코드는 Lambda 코드이다. Lambda를 콘솔에서 직접 업로드하여 배포할 수 있지만, AWS SAM을 이용하는 것도 가능하다. AWS SAM은 오픈소스 프레임워크로, Lambda 작업하는 것에 도움을 준다.

AWS SAM을 통해 Lambda로 배포하기 전 로컬에서 Docker 기반 테스트가 가능하며, 배포도 편하게 할 수 있다.

Untitled.png

정리

Lambda는 하나의 언어만 사용할 수 있는데, Open Source 프로젝트가 TypeScript이다 보니 나머지 코드도 자바스크립트로 작성했다. 자바스크립트 숙련도가 낮아, 코드 작업에 생각보다 시간이 오래 걸렸다. 또, 위의 AWS 서비스도 숙련도가 낮았다. 처음에 사용하면서 여러 문제가 발생했다. 특히 AWS SAM이 없었다면 작업시간이 더 길어졌을 것 같다. AWS SAM 덕분에 편하게 작업했다.

💡 자바스크립트를 숙련도가 낮습니다!! 코드를 보면서 고칠 부분이 있다면 댓글로 남겨주세요!

This post is licensed under CC BY 4.0 by the author.