Vercel이 말아주는 이미지 CDN 사용해보기 Thumbnail

이미지 업로드 with Vercel Blobs

9 min read

Vercel이 말아주는 이미지 CDN 사용해보기

Vercel LogoVercel Logo

티스토리나 벨로그 같은 블로그 서비스는 이미지를 복사하고 에디터에 붙여넣기를 할 경우에 이미지가 자체 cdn에 업로드되는 것을 볼 수 있다. 이 기능은 글을 작성할 때 사용자가 원하는 이미지를 바로 붙여넣을 수 있기 때문에 블로그에게는 필수기능이라고 생각이 든다.

ex) https://velog.velcdn.com/images/shipfriend/post/e2c95daa-397b-4484-a800-31327932598b/image.gif

이전까지 내 블로그는 이미지의 링크를 붙여넣는 것만 가능했다. 사실 내부적으로는 vercel의 blobs라는 cdn을 사용하고 있었다. 하지만 순수 노가다로 이미지를 업로드하고 링크를 붙여넣었기 때문에 실질적인 업로드 기능이 없었다.

cdn으로는 firebase 정도만 써봤었는데 찾아보니 vercel에서 storage -> blobs라는 이미지 저장소 기능을 지원하는 것을 알게 되었다. (vercel은 참 좋다.)


CDN이란?

CDN은 Content Delivery Network의 약자로, 데이터 사용량이 높은 여러 컨텐츠들을 빠르게 업로드하고 빠르게 전송 받을 수 있게 해주는 고마운 녀석이다.

CDN이미지CDN이미지

CDN과 일반 DB의 차이?

CDN과 일반 DB의 차이는 아래와 같다.

  • 목적
  • 데이터 특성
  • 분산 방식

가장 큰 차이점은 위치와 개수인 분산 방식에 있다. 일반 DB는 특정 위치에 고정적으로 몇 군데만 존재할 수 있지만 CDN은 전세계에 걸쳐 분산된 서버들을 사용한다는 점이 가장 큰 차이점이다.

분산된 서버를 사용하기 때문에 사용자가 있는 위치와 가장 가까운 서버를 사용한다는 특징이 있다. CDN의 성능을 올리기 위해 지역별로 캐싱을 하는 등의 성능 최적화를 한다고 한다.

그리고 정적인 자산을 저장하는데에 CDN이 사용된다. 정적인 자산은 사진이나 영상과 같이 한 번 저장되면 잘 변경되지 않는 자산을 의미한다. 일반적인 DB에는 자주 변경되고, 자주 추가되는 데이터들이 저장된다.

DB에 이미지를 저장하지 않는 이유

처음에는 DB에 이미지를 저장하고 꺼내서 쓰면 되지 않나라고 생각했었다. 그러나 배포를 몇 번해보고 나서 깨달은 점은 이미지나 폰트 파일의 정적 서빙이 은근 대역폭 비용을 많이 차지한다는 점이었다.

만약 서비스의 DB에 이미지를 저장하고 서빙한다면, 매번 DB 요청과 함께 무거운 이미지 파일을 전송하게 되는데, 이렇게 되면 비용이 많이 나갈 수 밖에 없다. 이런 비용을 외부 CDN을 사용함으로써 절감할 수 있는 것이다. 단점이라면 CDN 서비스에 의존적이라는 점이지만..


Vercel Blobs

vercel blobs는 vercel에서 지원하는 미디어를 저장하는 서버이다. 사실 CDN이라고는 했지만 Vercel Blobs는 CDN의 특성을 일부 가지고 있을 뿐 CDN은 아니다. AWS의 S3 인스턴스와 비슷한 역할을 한다고 한다.

무료 플랜의 경우 250MB를 무료로 지원한다. 적은 용량이지만 한번 사용해보는 목적으로는 적절하다고 생각했다.

사용하기 위해서는 vercel 배포 대시보드에서 Storage → Create Database 버튼 클릭 후 Blob을 선택하고 계속하면 된다.

Capture-2025-01-13-190325.pngCapture-2025-01-13-190325.png

Blob 데이터베이스를 만들고 나면 BLOB_READ_WRITE_TOKEN 을 주는데 이건 env 파일에 적고 유출되지 않도록 하자. firebase 같은 경우에는 이런 Token을 process.env.TOKEN 이런 식으로 코드 내에서 사용해야하는데, blobs는 nextjs에 최적화되어있다보니 간단하게 라이브러리 깔아서 써도 내부적으로 env파일을 참조한다.

내 블로그에서의 활용

내 블로그에서는 글을 작성할 때 이미지를 업로드할 수 있게 했다. 지금은 업로드 버튼을 눌러야만 업로드가 가능하지만, 추후에 그냥 글 중간에 붙여넣기해도 업로드 될 수 있게 해보려고 한다.

문서화가 잘되어있는 nextjs 덕분에 vercel blobs 업로드도 쉽게 해볼 수 있었다.

Vercel Blobs 문서

이 문서에서 잘 나와있다. 클라이언트 사이드 업로드와 서버 사이드 업로드로 나뉘는데, 클라이언트 측에서 업로드하는 방식을 선택했다.

클라이언트 사이드에서 업로드를 할 경우 file type의 input의 onChange 이벤트로 발생하는 event의 file를 업로드 시도하는 이벤트 핸들러를 만들어주고, next server route로는 클라이언트에서 업로드된 파일을 vercel blobs에 저장하는 api route를 만들어주는 방식이다.

// image upload change 이벤트 핸들러
const uploadToBlob = async (event: ChangeEvent) => {
  try {
    event.preventDefault();
    const target = event.target as HTMLInputElement;
    if (!target.files) {
      throw new Error('이미지가 선택되지 않았습니다.');
    }

    const file = target.files[0];
    const timestamp = new Date().getTime();
    const pathname = `/images/${timestamp}-${file.name}`;
    
    // pathname 저장되는 경로와 파일이름, 중복 방지를 위해 timestamp를 추가했다. 
    const newBlob = await upload(pathname, file, {
      access: 'public',
      handleUploadUrl: '/api/upload',
    });

    setUploadedImages([...uploadedImages, newBlob.url]);
    return;
  } catch (error) {
    console.error('업로드 실패:', error);
    throw error;
  }
};

이미지를 업로드하면 이렇게 업로드된 이미지를 볼 수 있고 이미지를 클릭해서 링크를 복사할 수 있도록 했다.

업로드 화면업로드 화면

남아있는 문제들

글을 쓰다가 나가면, 이미지 링크를 가져올 방법이 없다는 점이다. 이건 사실 다른 블로그도 똑같지만, 용량이 적으니까 아껴쓰던지 아니면 임시저장 기능을 만들어야할 것 같다.

아니면 글에서 사용되지 않는 사진의 경우 가비지 컬렉팅하는 기능을 만들어봐도 좋을 것 같다.

같은 사진을 한번 더 업로드할 경우에 대한 대비도 생각해봐야할 것 같다.

📌 Table of Contents

0
추천 글