notion을 CMS로 이용하는 방법

(작성자: 정경호)

WP 테크 글을 발행할 수 있게 만들었는데,

동료의 요구 사항은 글을 더 쉽게 쓸 수 있도록 해달라는 것. Jekyll에 글을 쓰기 위해선 VS code를 열고 글을 작성하고 빌드하는 과정이 어렵다고 피드백을 해줬다.

또한 이미지를 붙여넣기가 너무 힘들다는 피드백도 있었다. 이미지는 포스트할 때 이미지 쉽게 업로드하기 글에서 설명한 것 처럼 raycast 와 extension을 이용하면 쉽게 가능한데. (이는 나한테만 쉬운거였음 ㅋㅋㅋ..) 나는 vim에 익숙하고 raycast에 익숙해서 쉽게 조합해서 사용하지만 이 도구에 익숙하지 않으면 다 장애물이 된다는 것을 알게 됐다.

그래서 notion을 CMS로 이용하기로 했다

처음부터 notion을 염두한건 아니었다. 다양한 후보군들이 존재하고 jekyll-admin 같은 전용 CMS도 존재한다. 하지만 notion 만큼 완성도를 가진건 아니었고 또 새로운 도구를 도입하는 것에 대한 내 부담도 있었다.

다행히도 우리 회사는 Notion을 많이 사용하고 구성원들도 익숙하므로 Notion을 CMS로 사용하면 다양한 이점을 가질 수 있을것 같았다.

그리고 jekyll-notion 프로젝트를 발견했다.

아래 이미지에서 보이듯 다양한 방식으로 notion 문서를 jekyll에 배포할 수 있으며 심지어 video도 임베딩 할 수 있는 방법을 제공한다.

사용방법을 여기서 자세히 말하진 않겠지만

  1. Notion connections를 만들고
  2. jekyll 프로젝트에 환경 설정을 하면

jekyll 을 빌드할때 notion 페이지를 가져와서 글을 렌더링할 수 있다.

사실 이 글은 Notion에서 쓰고 발행하는 첫 글이다

아래 이미지는 발행할 글을 갖고있는 테이블인데. 이 테이블에 글을 추가하고 Published = true로 설정하면 새 글 발행이 가능하다.

노션을 쓰니 vim에 비해 느껴지는 장단점이 있는데. 노션이 이미지를 붙여넣기가 너무 쉽다는 것을 빼면 나머지 장점은 잘 모르겠다. vim은 아무래도 커스텀이 가능하니까 나에게 맞춰서 정말 편하게 할 수 있는데 Notion은 그게 안되니까.


아무튼 이렇게 notion - jekyll 연동은 잘 되었고 조금 부족하지만(더 필요한 부분은 jekyll을 확장하면 되니) 만족스러운 결과물이다.


💡 여기에서 글을 작성할 수 있다. 👉 https://www.notion.so/fnf-digital/3134312cba1f4feb95ca2593a515aeb0?v=a7935f8070a2403584339a791366a941

🚨 글 작성 후 배포를 해야하는데, README.md 를 참고하면된다.


이미지가 안뜬다

며칠이 지나고 다시 글을 읽어보니 이미지가 안뜬다는 사실을 발견했다. Notion의 AWS SignedUrl API가 관련있을거란 생각이 들었다. 첫날에는 잘 보였는데, 다음날 쯤 보니 이미지가 안보이기 시작했기 때문이다.

AWS SignedUrl

https://prod-files-secure.s3.us-west-2.amazonaws.com/d1e171ff-e12d-422d-b387-ee69736aa2cc/422a090d-8410-402f-82b6-7a193e481a85/image.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45HZZMZUHI%2F20240828%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20240828T065908Z&X-Amz-Expires=3600&X-Amz-Signature=2741632ffd686499e46ce91588f40b69bd90664a80b5a36df907c847ae1feaa8&X-Amz-SignedHeaders=host&x-id=GetObject

GetObject   있는 시간이 지정되있는 쿼리
X-Amz-Date=20240828T065908Z&X-Amz-Expires=3600

image url을 뽑아보니 위와같이 생겼고 시간에 대한 query param이 포함된걸 확인할 수 있었다.


이미지 다운로드, 교체 코드가 필요함

  1. 이미지가 안뜨는 문제를 해결하기 위해 아래와 같이 Notion의 s3 파일을 다운로드 받는 코드를 작성했다.
#!/bin/bash

# 1. _site 디렉토리에서 prod-files-secure.s3 내용을 포함하는 모든 파일 목록 만들기
echo "Searching for files containing 'https://prod-files-secure.s3.us-west-2.amazonaws.com/'..."
file_list=$(grep -rl 'https://prod-files-secure.s3.us-west-2.amazonaws.com/' ./_site --include=\*.html)


# 2. 위 파일 목록에서 https://prod-files-secure.s3/ 파일을 읽어와 asset/images 에 다운로드
echo "Downloading images to asset/images..."
mkdir -p ./assets/images

IFS=$'\n'

for file in $file_list; 
do
  # Extract URLs from the file
  urls=$(grep -o 'https://prod-files-secure.s3.us-west-2.amazonaws.com/[^"]*\.\(png\|jpg\|jpeg\|gif\)[^"]*' "$file")

  echo "Processing file: $file"

  for url in $urls;
  do
    # 쿼리 파라미터 제거
    clean_url=$(echo "$url" | sed 's/[?&].*//')

    # URL에서 파일 경로 추출 (호스트 부분 이후)
    filename=$(echo "$clean_url" | sed 's|https://prod-files-secure.s3.us-west-2.amazonaws.com/||')
    
    # 파일이 이미 존재하는지 확인
    if [ -f "./assets/images/$filename" ]; then
      echo "File already exists, skipping: ./assets/images/$filename"
    else
      # 디렉토리가 존재하지 않으면 생성
      mkdir -p "./assets/images/$(dirname "$filename")"
    
      # amp; 삭제
      removed_amp_url=$(echo "$url" | sed 's/amp;//g')
    
      # 파일 다운로드
      echo "Downloading: $url to ./assets/images/$filename"
      curl -s "$removed_amp_url" -o "./assets/images/$filename"
    fi

  done
done


  1. 페이지가 로드 될 때, Notion s3 파일을 다운로드 받은 파일을 가르키도록 javascript 코드를 post.html 추가했다.
<script>
  document.addEventListener("DOMContentLoaded", function() {
    // 모든 img 태그와 배경 이미지 스타일을 검색
    const images = document.querySelectorAll("img, [style*='background-image']");

    images.forEach(image => {
        let src = image.src || image.style.backgroundImage;

        if (src.includes("https://prod-files-secure.s3.us-west-2.amazonaws.com/")) {
            // 쿼리 파라미터를 제거하고, URL을 상대 경로로 변경
            const cleanUrl = src.replace(/^https:\/\/prod-files-secure\.s3\.us-west-2\.amazonaws\.com\//, "/").split("?")[0];
            const replacedUrl = `/assets/images/${cleanUrl}`;

            if (image.src) {
                // img 태그인 경우 src 속성 수정
                image.src = replacedUrl;
            } else if (image.style.backgroundImage) {
                // background-image 스타일인 경우 수정
                image.style.backgroundImage = `url('${replacedUrl}')`;
            }
        }
    });
  });
</script>


이미지가 잘 뜬다.