포트폴리오 웹사이트 구축기

최근 나는 한가지 생각이 들었다.

나를 처음 보는 사람에게 나는 어떤 이미지로 보일까?

그냥 이력서 한 장으로만 나를 보여주기엔 뭔가 아쉬웠다. 나는 메카트로닉스 공학도이고, 실물 기기와 소프트웨어 사이의 연결 고리에 관심이 많다.

그렇다면 내 포트폴리오도 단순히 “저 이런 거 해봤어요” 하고 나열하는 페이지가 아니라, 내가 어떤 방식으로 생각하고, 어떤 디테일을 중요하게 보는 사람인지 보여주는 하나의 결과물이 되어야 하지 않을까? 그래서 나는 포트폴리오 웹사이트를 직접 만들어보기로 했다.

처음에는 가볍게 생각했다.

그냥 깔끔한 페이지 하나 만들고, 프로젝트 몇 개 올리면 되는 거 아닌가?

…라고 생각했는데, 역시 세상 일이 그렇게 만만할 리가 없었다.

기왕 만드는 김에 최신 기술을 써보고 싶었다. 그래서 Next.js 15와 Tailwind CSS v4를 선택했다.

사실 처음부터 엄청난 이유가 있었던 건 아니다. 그냥 가장 최신이고, 가장 트렌디해 보였고, “이걸로 만들면 뭔가 있어 보이지 않을까?” 하는 마음도 조금 있었다. ㅋㅋ

그런데 막상 만들기 시작하니까 생각보다 재밌었다.

단순히 화면을 예쁘게 꾸미는 게 아니라, 사이트 전체의 구조를 어떻게 잡을지부터 고민해야 했다.

처음에는 영문 사이트로만 만들었는데, 곰곰이 생각해보니 내가 한국 사람인데 기본 언어가 영어인 것도 좀 이상했다.

그래서 한국어를 기본값으로 하는 다국어 구조로 갈아엎었다.

그냥 텍스트만 번역하는 수준이 아니라, 아예 구조 자체를 바꿨다.

[lang] 파라미터를 사용해서 언어별 라우팅이 가능하게 만들고, 사용자가 그냥 사이트에 접속하면 자동으로 /ko로 이동하도록 미들웨어도 만들었다.

그리고 번역 데이터는 JSON으로 분리했다.

서버 컴포넌트에서 번역 데이터를 바로 불러오는 방식으로 구성해서, 클라이언트 쪽 부담을 최대한 줄였다.

이쯤 되니까 단순한 포트폴리오가 아니라 점점 하나의 작은 서비스처럼 변해가고 있었다.

그런데 내가 진짜 신경 쓴 부분은 따로 있었다.

바로 인터랙션이었다.

나는 사용자가 사이트에 들어왔을 때 “오… 뭔가 느낌 있는데?” 라는 생각이 들었으면 했다.

그래서 커서를 직접 만들기 시작했다.

처음에는 단순한 커스텀 커서 정도였는데, 하다 보니 욕심이 생겼다.

마우스를 빠르게 움직이면 커서가 이동 방향으로 쫀득하게 늘어나고, 버튼이나 소셜 아이콘 근처에 가면 자석처럼 “착” 달라붙는 느낌을 넣고 싶었다.

이걸 구현하려고 마우스 속도를 실시간으로 추적하고, 그 속도에 따라 커서의 형태가 변하도록 만들었다.

처음 구현했을 때는 꽤 신기했다.

커서 하나 바뀌었을 뿐인데 사이트의 인상이 확 달라졌다.

물론 처음부터 지금처럼 깔끔했던 건 아니다. 처음에는 링도 있고 효과도 많았는데, 막상 보다 보니 조금 과하다는 느낌이 들었다.

그래서 복잡한 요소를 줄이고, 최종적으로는 단일 닷 커서 형태로 정리했다.

확실히 덜어내니까 더 세련돼 보였다.

역시 디자인은 무조건 많이 넣는다고 좋은 게 아니었다.

그리고 개발하면서 당연히 문제도 터졌다.

가장 먼저 만난 건 Clipboard API 에러였다.

이메일을 클릭하면 자동으로 복사되는 기능을 만들었는데, 일부 환경에서 navigator.clipboard를 읽지 못하면서 TypeError가 발생했다.

처음에는 “아니 왜 내 컴퓨터에서는 되는데?” 싶었다.

하지만 웹은 내 환경에서만 돌아가는 게 아니니까…

결국 isSecureContext를 체크하도록 만들고, Clipboard API를 사용할 수 없는 환경에서는 임시 textarea를 만들어 복사하는 fallback 로직을 추가했다.

이렇게 해두니까 훨씬 안정적으로 동작했다.

또 하나 거슬렸던 건 레이아웃 시프트였다.

이메일 복사가 성공하면 “복사되었습니다!”라는 메시지가 나타나는데, 그 순간 카드 높이가 변하면서 화면이 뚝 끊겨 보였다.

기능적으로는 문제가 없지만, 뭔가 완성도가 떨어져 보였다.

그래서 Framer Motion의 layout 속성을 사용했다.

레이아웃 변화가 생기면 그걸 자동으로 감지해서, spring 물리 엔진으로 부드럽게 확장되도록 바꿨다.

이 작은 차이가 생각보다 컸다.

그냥 메시지가 뜨는 것과, 카드가 자연스럽게 늘어나면서 메시지가 뜨는 건 느낌이 완전히 달랐다.

그리고 또 하나.

한국어 줄바꿈이 생각보다 신경 쓰였다.

특히 “포트폴리오 웹사이트입니다” 같은 문장이 화면 너비에 따라 어색하게 잘리는 문제가 있었다.

진짜 별거 아닌 것처럼 보이는데, 한 번 눈에 들어오니까 계속 거슬렸다.

결국 텍스트 영역의 최대 너비를 max-w-4xl로 조정하고, 특정 단어 사이에는 줄바꿈 방지 공백을 넣었다.

또 JSON 데이터 안에서 의도한 줄바꿈이 제대로 보이도록 whitespace-pre-line도 적용했다.

이때 느꼈다.

사용자는 이런 걸 하나하나 말하지는 않지만, 분명히 느낀다.

커서가 0.1초 늦게 따라오는 느낌, 문장이 이상한 곳에서 끊기는 느낌, 버튼을 눌렀는데 피드백이 애매한 느낌.

이런 작은 것들이 쌓여서 사이트의 인상을 만든다.

그리고 프로젝트 데이터 관리는 Notion을 사용했다.

노션을 Headless CMS처럼 활용해서, 노션 데이터베이스에 프로젝트를 등록하면 포트폴리오 사이트에도 반영되도록 만들었다.

이 부분도 꽤 마음에 들었다.

코드에 직접 프로젝트를 하나하나 박아 넣는 게 아니라, 노션에서 내용을 관리하고 사이트는 그 데이터를 가져와 보여주는 구조가 되니까 훨씬 관리하기 편했다.

홈 화면에는 전체 프로젝트를 다 보여주기보다는 상위 3개의 주요 프로젝트만 미리보기로 보여주도록 했다.

정보를 많이 보여주는 것도 중요하지만, 처음 들어온 사람에게는 적당히 덜어내는 것도 중요하다고 느꼈다.

결국 이 포트폴리오 사이트는 단순한 웹페이지가 아니었다.

Next.js 15, Tailwind CSS v4, Framer Motion, Notion API, 다국어 라우팅, 미들웨어, 서버 컴포넌트…

이런 기술들을 하나씩 붙여가며 내가 어떤 엔지니어가 되고 싶은지 고민한 결과물에 가까웠다.

처음에는 그냥 포트폴리오 하나 만들어보자는 생각으로 시작했는데, 만들다 보니 점점 더 욕심이 생겼다.

더 부드럽게. 더 깔끔하게. 더 안정적으로. 더 나답게.

결국 내가 이 프로젝트를 하면서 가장 크게 느낀 건 하나였다.

완성도는 거창한 기능 하나에서 나오는 게 아니라, 사용자가 굳이 말하지 않는 작은 불편함을 얼마나 줄였는지에서 나온다는 것.

이제 이 사이트 위에 내가 배우고 있는 TypeScript, React, 시스템 아키텍처, 그리고 여러 프로젝트들을 하나씩 기록해보려 한다.

어쩌면 이 포트폴리오는 완성된 결과물이라기보다는, 앞으로 내가 어떤 엔지니어로 성장할지 보여주는 출발점에 더 가까운 것 같다.


사용한 기술들

  • Next.js 15
  • Tailwind CSS v4
  • Framer Motion
  • Notion API
  • Custom Dictionary Pattern
  • Middleware Redirect
  • Vercel Deployment
  • Git Automation