들어가며
기술 블로그란?
보통 블로그란 맛집리뷰 혹은 내돈내산을 떠올리게 하지만, 개발자들에게 블로그는 기술 블로그로 통용됩니다.
그럼 기술 블로그는 왜 중요한 걸까요? 요즘 핫한 고물로봇 ChatGPT에게 물어봤습니다.
나: 기술 블로그가 개발자에게 중요한 이유가 뭐야?
ChatGPT: 기술 블로그가 개발자에게 중요한 이유는 여러 가지가 있습니다:
지식 공유와 커뮤니케이션: 기술 블로그는 개발자들 간에 지식을 공유하고 의견을 교환하는 훌륭한 수단입니다. 다른 개발자들이 새로운 기술이나 도구, 문제 해결 방법 등을 학습하고 활용할 수 있도록 정보를 제공하고 공유할 수 있습니다.
자기 브랜딩 및 포트폴리오: 기술 블로그는 개발자의 기술적인 능력과 지식을 나타내는 한 가지 방법입니다. 새로운 기술 스택을 사용하거나 프로젝트를 구현한 경험 등을 기술하여 자신의 역량을 노출시키고, 이는 구인자나 프로젝트 협력 기회에 대한 포트폴리오로 활용될 수 있습니다.
문제 해결 능력 강화: 블로그를 통해 자신이 마주한 문제와 그 해결 과정을 기록하고 설명함으로써, 문제 해결 능력이 향상될 수 있습니다. 또한, 다른 개발자들의 피드백을 받아 개선할 수 있는 기회가 생깁니다.
요약하자면, 블로그는 정보 공유의 창구, 퍼스널 브랜딩, 문제 해결 능력 향상을 시켜주는 도구입니다.
어떻게 만들까?
자 이제 좋은 거는 알았는데, 어떻게 시작해야 할까요? 방법과 장점은 아래와 같습니다.
- 직접 만들기
- 내맘대로 편하게 커스텀 가능
- 평소에 접하지 못했던 기술들에 도전
- 플랫폼 이용하기
- 기본 설정(SEO, 에디터 지원 등)을 갖춤
- 플랫폼 내 다른 사용자들과의 더 많은 커뮤니케이션에 용이
저는 SEO를 직접 보완해보고, 타 사용자들과의 소통은 서드파티 플러그인(giscus 등)을 최대한 활용해보기로 하고 직접 만들기를 택했습니다.
제작 과정
직접 만들기라고 거창하게 적었지만 밑바닥부터 만든 건 아닙니다. 이런저런 글을 읽다가 우연히 관심이 가는 프로젝트를 발견했는데, Next.js라는 프레임워크를 만든 Vercel의 VP(부사장)으로 있는 leerob이라는 개발자가 감사하게도 본인의 포트폴리오 저장소(Star가 6.8k!)를 오픈소스로 공개하고 있습니다.
전체 코드와 운영 중인 사이트를 확인해본 결과, 심플한 디자인으로 커스텀하기 쉬울 거 같았고, 여러 낯선 기술 스택(App Router, Tailwind 등)들이 흥미로워 바로 제작을 시작했습니다.
'제작 과정' 하위 파트는 개발 경험이 어느 정도 있다는 것을 가정으로 설명하며, 이미 선택되어 있는 기술 스택을 위주로 진행했고 leerob이 가이드한 내용에 더불어 제가 직접 경험하고 정리한 부분을 추가했습니다.
초기 세팅
먼저 저장소를 포크하고, 배포에 이용할 Vercel 대시보드에 들어가 포크한 프로젝트를 연동하여 배포합니다. 여기까지만 해도 기본 템플릿 페이지를 확인할 수 있습니다.
배포된 URL의 루트("/") 경로에 갔을 때 This is your new portfolio. 가 보이면 성공입니다!
지금부터는 README 및 기술 문서를 참고하여 진짜 내 포트폴리오(블로그)로 바꿔봅시다.
Bun
시작부터 새로운 친구가 등장하는데, JavaScript와 TypeScript all-in-one toolkit으로 소개되는 Bun입니다. Deno나 Node.js보다 빠르다고 강조하며(저는 드라마틱한 속도 체감은 하지 못했습니다 😂), npm이나 yarn과 같이 package manager 역할도 한꺼번에 수행할 수 있기 때문에 편리했습니다.
Environment Variables(환경 변수)
로컬 개발 환경으로 돌아와서 README를 따라 bun run setup
까지 입력했다면, 이제는 .env.local
을 만들어 로컬에서의 환경 변수 세팅을 해줍니다. 저는 동작에 이상없는 정도로 수정을 해서 간단하게 바꿔봤습니다.
POSTGRES_DATABASE=
POSTGRES_HOST=
POSTGRES_PASSWORD=
POSTGRES_URL=
POSTGRES_URL_NON_POOLING=
POSTGRES_USER=
AUTH_SECRET=
AUTH_GITHUB_ID=
AUTH_GITHUB_SECRET=
크게 POSTGRES
와 AUTH
라는 prefix를 가진 변수로 나누어 살펴보겠습니다.
-
POSTGRES 관련 변수는 Vercel Postgres 문서를 참고했습니다.
- 게시물 조회수, 방명록을 이용하기 위해 데이터베이스가 필요합니다. 대시보드에 미리 만들어둔 프로젝트에 들어가 데이터베이스까지 만들어주면, 프로덕션용 환경 변수를 알아서 세팅해주고, 로컬에는 Vercel CLI를 이용하여 간편하게 가져올 수 있습니다.
- 처음 고른 region은 바꿀 수 없습니다. Vercel Postgres는 Neon과의 합작품인데, 아쉽게도 region으로 한국이 아직 없습니다. 문서에도 적혀있듯이 데이터베이스와 Function Region만 일치시켜줍니다(저는 워싱턴(
iad1
)을 이용했습니다). - 테이블은 미리 제공된 쿼리를 통해 프로젝트 Storage 탭 > Data > Query에서 생성했습니다.
-
AUTH 관련 변수는 Auth.js 문서를 참고했습니다.
-
Auth.js는 NextAuth.js v5로 아직 beta 버전이지만, 환경 변수 자동 추론과 더 간단한 API(
auth()
)를 제공합니다. v4에서 v5로의 자세한 업데이트 사항은 Upgrade Guide (v5)를 읽어보시면 됩니다. -
조금 귀찮지만 로컬 개발용 환경 변수와 프로덕션용 환경 변수를 각각 만듭니다(참고).
-
배포
AWS, GCP와 같은 클라우드 서비스 플랫폼을 직접 다룰 줄 몰라도 Vercel을 이용하면 아주아주 쉽게 거저먹을 수 있습니다(뒷광고 X). Vercel은 AWS의 서비스들(Amazon S3, AWS Lambda 등)을 아름답게 말아서 배포의 용이성을 크게 증가시켰습니다(관련 링크, 관련 영상). 다음은 대시보드에 프로젝트를 연결해놓기만 하면 받을 수 있는 대표적인 기능입니다.
- remote branch의 변화를 감지하여 재배포
- 보기 좋게 정리된 배포 과정 및 여러 탭(Logs, Analytics, ...)
여기까지 마쳤다면 프로덕션용 환경 변수를 가지고 새로 배포도 해보고, 다음 커스텀 파트로 넘어갑니다.
프로젝트 커스텀
세팅을 마쳤다면 이젠 진짜 내가 쓸 프로젝트로 바꿔보겠습니다. 빠른 팁은 'leerob'으로 되어있는 부분을 각자 본인에 맞춰 수정하고, 사용하지 않는 코드를 제거하면 됩니다!
ESLint
저는 개인적으로 ESLint를 정말 좋아합니다. 미리 경고나 에러를 띄워 전반적인 코드 퀄리티 보장 및 버그 방지를 해주고, 때로는 Format On Save를 통해 자동으로 코드를 수정해주기도 하는 친구입니다.
Next.js ESLint와 Legacy ESLint Setup에 맞춰 설치했습니다.
타입 안정성을 보장하며 더 간단한
flat
config format이 있긴 하지만, 규칙 자체가 달라지는 것은 아니기 때문에 익숙한 legacy 포맷을 사용했고 후에 ESLint v9가 나오면 마이그레이션 해볼 예정입니다!
추가적으로 no-useless-escape와 @typescript-eslint/no-unused-vars과 관련된 동작에 이상이 없는 것을 확인한 후, warn
으로 처리하여 당장 눈을 아프게 하는 빨간 줄들을 임시 처리 해두었습니다.
Metadata
App Router에선 static(객체 형태) 혹은 dynamic(함수 형태) metadata를 export 하여 meta
, link
태그를 만들 수 있습니다. 저는 기존 템플릿에서 수정하고 싶은 부분만 골라서 수정했습니다.
속성 중 verification
은 Google Search Console에서 발급받아 넣어줍니다.
각 속성에 대한 설명은 Metadata 문서에 있습니다.
Open Graph(W/ Route Handler, Edge Runtime)
카카오톡, 디스코드 등에서 링크를 공유하면 이미지 하나와 여러 설명들이 나오는 걸 보신 적이 있으신가요? Open Graph(이하 OG)는 이와 같이 링크를 공유했을 때 시각적인 추가 정보를 제공해주는 프로토콜입니다. 아래는 leerob 블로그 글 중 하나에 대한 디스코드에서의 OG입니다.
App Router의 파일 컨벤션 중 opengraph-image
는 모든 페이지에 보여질 기본 OG 이미지를 정할 수 있습니다. 저는 웹으로 바로 사용할 수 있는 무료 에디터를 이용하여 이미지를 생성해줬고, 게시물(post)마다 동적인 OG를 따로 생성하게끔 했습니다.
여기서 잠깐 동적인 OG를 생성하는 코드의 일부를 한 번 살펴보겠습니다.
const ogImage = image
? `https://chogyejin-io.vercel.app${image}`
: `https://chogyejin-io.vercel.app/og?title=${title}`;
image
라는 값이 falsy할 때 /og로 끝나는 경로에 접근하게 되는데, 이는 프로젝트 내에서 app/og/route.tsx로 향하는 요청이고, 이렇게 route라는 파일 컨벤션을 활용하는 것을 Route Handlers라고 합니다(Pages Router의 API Routes와 같은 기능입니다).
눈치채셨을 수도 있지만, auth.js에서 이미 route 컨벤션을 이용했습니다!
이제 og route 안의 ImageResponse
인스턴스에 세팅되어 있던 폰트인 kaisei-tokumin-bold
를 날려버리고 아름다운 한글이 지원되는 폰트를 가져와서 commit, push를 했는데 어라? 빌드가 실패합니다.
이유는 Edge Runtime의 크기 제한 때문입니다.
export const runtime = 'edge';
Edge Runtime은 작고 간단한 함수를 통해 짧은 지연 시간으로 정보를 제공해주지만, 크기 제한이 있고 일부 npm 패키지를 사용하지 못합니다(여기서 크기는 번들링된 후의 함수와 종속성의 압축된 크기입니다). Hobby 플랜에서는 제한이 1 MB인데, 웬만한 한글 폰트들은 크기가 크기 때문에 저 정도 크기는 우습게 넘깁니다. 또한 현재로썬 로컬 개발 환경에서 크기를 미리 파악해볼 뾰족한 수가 없는 것 같습니다(관련 레딧글 및 디스커션).
사투 끝에 저는 NotoSansKR-Hestia를 이용하여 1 MB에 간신히 맞춰 한국인의 긍지를 보여주었습니다.
Edge Runtime과 함께 언급되는 Nodejs Runtime은 사용해보지 않았습니다. 이유는 opengraph-image 공식 문서에서 Route segment 옵션으로
'edge'
를 사용하기도 했고, Hobby 플랜 내애서 최대한 알차게 여러 기능을 사용해보고 싶었기 때문입니다. Nodejs Runtime이 궁금하신 분들은 비교글을 읽은 후 직접 적용해보고 가능하다면 속도 차이가 얼마나 나는지도 체크해보시면 좋을 것 같습니다!
아래는 만든 OG가 잘 적용되었는지 확인하는 방법입니다(때에 따라서는 카카오톡과 같이 직접 OG의 캐시를 초기화해야하는 경우도 있었습니다).
- 직접 링크 공유하기
- Vercel Deployments 탭 > Current 배포 > Open Grpah 탭
- Checker 이용하기(opengraph.xyz, opengraph.dev 등)
마치며
이렇게 Next.js App Router를 기반으로 블로그를 만들어봤습니다. 블로그들을 둘러보다 보면 Next.js가 아닌 Gatsby를 이용하신 분도 많이 보이는데, 똑같이 새로운 기술을 다루는 것이라면 Gatsby만의 설정이나 플러그인을 맛보는 것보단 비교적 실무에 가깝고 많이 쓰이는 Next.js를 사용해보는 게 의미도 있고 재밌었습니다. 또한 추가적으로 댓글 기능, 테마 변경, 게시글 레이아웃 변경 등 개선 사항도 많기 때문에 계속해서 점진적으로 수정해나갈 예정입니다.
이 글에서 직접적으로 언급하지 못한 검색 수집 및 색인 관련 내용(Google Search Console, Naver Search Advisor)과 타이트한 TypeScript 적용 등은 다른 포스팅으로 다뤄보도록 하겠습니다. 긴 글 읽어주셔서 감사합니다! 😎