하루 종일 앉아서 보내는 날들이 쌓이면서, 나는 어느 순간부터 조금씩 변해가고 있었다. 처음엔 단순히 몸이 무겁다는 느낌 정도였는데, 어느 날 체중계 위에 올라서는 순간 그 변화가 숫자로 보였다. 세 자리 숫자에 가까워진 몸무게. 잠깐 멍해졌다. “이건 좀 아닌데…”라는 생각이 머릿속을 스쳤고, 그날로 다이어트를 해야겠다고 마음먹었다.
가장 먼저 떠오른 건 헬스장이었다. 익숙한 선택이었고, 많은 사람들이 그렇게 하니까 나도 자연스럽게 등록을 했다. 첫날은 꽤 의욕적이었다. 러닝머신도 뛰고, 기구도 만져보고, 나름 열심히 했던 것 같다. 그런데 그 의욕은 오래가지 않았다. 이틀, 삼일… 그리고 발걸음은 자연스럽게 끊겼다. 왜 이렇게 꾸준히 못 할까 생각해봤는데, 이유는 의외로 간단했다. 재미가 없었다. 무거운 걸 들고 내리고, 같은 동작을 반복하는 시간이 나에게는 그저 버티는 시간처럼 느껴졌다. 에너지는 쓰는데, 기분은 전혀 좋아지지 않았다. 점점 더 가기 싫어졌고, 결국 또 포기했다.
그러다 어느 날, 별생각 없이 러닝머신 위에 올라갔다. 그냥 가볍게 걷다가 조금씩 속도를 올리면서 달리기 시작했다. 그때 옆에서 어떤 사람이 같이 뛰기 시작했는데, 눈에 띄는 건 그 사람의 체형이었다. 나와 비슷했다. 그런데 이상하게도, 나보다 훨씬 잘 달렸다. 숨도 고르면서 꾸준히, 안정적으로 뛰고 있었다. 순간 묘한 기분이 들었다. “어? 나랑 비슷한데 저렇게 뛸 수 있다고?” 그 장면이 머릿속에 강하게 남았다. 그리고 그날 이후로 나도 한번 해보고 싶다는 생각이 들었다.
그렇게 목표를 정했다. 하루에 5km. 거창하지는 않지만, 나에게는 충분히 도전적인 숫자였다. 처음에는 힘들었지만, 조금씩 몸이 적응해갔다. 다만 혼자 뛰는 시간이 길어지면서 또다시 지루함이 스며들기 시작했다. 그러던 중, 우연히 인스타그램에서 마라톤 메달 사진을 보게 됐다. 반짝이는 메달과 완주했다는 글. 그걸 보는 순간 이상하게 끌렸다. “이거… 나도 한번 해볼까?” 그렇게 처음으로 마라톤 대회에 신청했다. 마블런 10km.
신청 버튼을 누르고 나서야 현실감이 밀려왔다. ‘내가 10km를 뛸 수 있을까?’ 솔직히 자신은 없었다. 그래도 이미 신청은 했고, 어쩔 수 없이 준비를 시작했다. 다시 헬스장도 가고, 달리는 거리도 조금씩 늘렸다. 그렇게 시간이 지나고, 대회 당일이 됐다. 처음 출발선에 섰을 때의 긴장감은 아직도 기억난다. 사람들이 많았고, 다들 준비된 모습이었다. 나만 준비가 덜 된 것 같은 느낌이 들었지만, 이미 시작은 되었고 뒤로 물러설 수는 없었다. 그렇게 첫 마라톤이 시작됐다.
결과적으로는 완주했다. 하지만 기분은 성취감보다는 생존에 가까웠다. 숨은 턱까지 차올랐고, 머리는 어지러웠고, 당장이라도 쓰러질 것 같은 느낌이었다. ‘아… 진짜 힘들다’라는 생각밖에 안 들었다. 다음 날은 더 심했다. 온몸이 쑤셔서 제대로 움직이기도 힘들었다. 기록은 1시간 20분. 잘한 건지 못한 건지도 모르겠고, 그냥 끝냈다는 사실만 남았다.
그런데 이상하게도, 며칠이 지나니까 생각이 조금씩 바뀌기 시작했다. 그렇게 힘들었던 기억이었는데, 어느 순간 “한 번 더 해볼까?”라는 생각이 자연스럽게 떠올랐다. 이유는 모르겠지만, 다시 도전해보고 싶었다.
그래서 다음으로 선택한 건 뉴발란스 10km였다. 이 대회는 인기가 많아서 새벽부터 줄을 서야 했다. 강남에 도착했을 때 이미 많은 사람들이 모여 있었고, 그 분위기 자체가 묘하게 설렜다. 그렇게 다시 한 번 달리게 됐다. 두 번째 마라톤은 첫 번째와 달랐다. 여전히 힘들긴 했지만, 그때처럼 죽을 것 같지는 않았다. 몸이 조금은 익숙해진 느낌이었다. 기록을 확인했을 때 더 놀랐다. 1시간 5분. 무려 15분이나 단축됐다. 그때 처음으로 느꼈다. ‘아, 이게 쌓이는 거구나.’ 매일 꾸준히 달렸던 시간이 결과로 보이기 시작했다.
그 이후로 나는 거의 매일 10km를 달리기 시작했다. 힘들었지만, 이상하게 그 시간이 점점 즐거워졌다. 목표는 단순했다. 한 달 동안 꾸준히 해보자. 그렇게 한 달이 지났고, 체중은 99kg에서 89kg까지 떨어졌다. 숫자가 바뀌는 걸 보는 재미도 있었지만, 그보다 더 컸던 건 스스로에 대한 느낌이었다. ‘나도 할 수 있구나’라는 생각.
하지만 여기서 멈추면 안 된다는 걸 나는 알고 있었다. 예전에 여러 번 다이어트를 하면서 느꼈던 것처럼, 멈추는 순간 다시 돌아간다. 그래서 계속 달렸다. 그리고 어느 순간 깨달았다. 이게 더 이상 ‘해야 하는 일’이 아니라, ‘하고 싶은 일’이 되어버렸다는 걸.
그 이후로는 자연스럽게 마라톤 대회에 자주 참가하게 됐다. 한 달에 두세 번씩 대회를 나가면서 점점 더 다양한 경험을 하게 됐다. 그런데 한 가지 불편한 점이 계속 눈에 들어왔다. 마라톤 정보를 찾는 게 너무 어려웠다. 대회는 여기저기 흩어져 있고, 접수 기간은 놓치기 쉽고, 공식 사이트도 각각 따로였다. 정보를 찾는 데에 생각보다 많은 시간이 들어갔다. 그때 문득 이런 생각이 들었다. “이거… 왜 이렇게 불편하지?” 그리고 이어서 떠오른 생각. “그럼 내가 만들어볼까?” 내가 직접 겪었던 불편함을 해결해주는 사이트. 마라톤 일정을 한눈에 보고, 접수 기간을 놓치지 않고, 원하는 대회를 쉽게 찾을 수 있는 곳. 그렇게 시작하게 된 게 바로 ‘RunZoa’, 런조아다.
처음에는 단순한 생각에서 시작했지만, 지금은 조금 더 욕심이 생겼다. 나처럼 처음 달리기를 시작하는 사람들에게 도움이 되고, 이미 달리고 있는 사람들에게도 더 편한 환경을 만들어주는 서비스. 그걸 직접 만들어보고 싶어졌다. 이제는 단순히 달리는 것에서 끝나는 게 아니라, 그 경험을 바탕으로 무언가를 만들어보려 한다. 그럼… 이제 진짜 시작해볼까. 🏃♂️🔥
이번 프로젝트는 단순히 만들어보는 수준이 아니라, 내가 실제로 계속 사용할 서비스로 만들 생각이다. 그래서 가장 먼저 기준을 하나 정했다. 내가 익숙한 도구를 쓰자. 새로운 기술을 공부하면서 만드는 것도 의미는 있지만, 그 과정에서 속도가 느려지고 완성도가 떨어질 수 있다. 이번에는 빠르게 만들고, 실제로 쓰면서 계속 개선해나가는 게 더 중요하다고 생각했다.
물론 완전히 무료로만 구성할 수도 있다. 하지만 이번에는 약간의 비용이 들더라도, 안정적이고 편하게 운영할 수 있는 구조를 선택하기로 했다. 어차피 내가 계속 사용할 서비스라면, 작은 투자 정도는 충분히 가치가 있다고 판단했다.
프론트엔드는 처음에 React와 Next.js 사이에서 잠깐 고민을 했다. 둘 다 익숙한 선택이었지만, 이번 프로젝트에서는 방향이 비교적 명확했다. **검색엔진 최적화(SEO)**가 중요한 서비스이기 때문이다. 마라톤 정보는 검색을 통해 유입되는 경우가 많고, 대회명이나 일정으로 검색했을 때 노출되는 게 굉장히 중요하다. 그런 점에서 서버 사이드 렌더링과 SEO에 유리한 Next.js가 더 적합하다고 판단했다. 그래서 이번에는 Next.js로 가기로 했다.
데이터베이스는 자연스럽게 Supabase를 선택했다. 이미 많은 사람들이 사용하고 있고, 설정도 비교적 간단하면서 인증, 데이터베이스, 스토리지까지 한 번에 사용할 수 있는 점이 마음에 들었다. 무엇보다 개인 프로젝트에서 빠르게 시작하기에 이만한 선택이 없다고 생각했다. 배포는 고민할 필요도 없이 Vercel이다. Next.js와의 궁합이 워낙 좋아서 별다른 설정 없이도 바로 배포가 가능하고, 개발 흐름도 깔끔하게 이어진다. 실제로 작업하면서 가장 스트레스가 적은 부분이 배포인데, 이 조합은 그 부분을 거의 신경 쓰지 않아도 된다.
스타일링은 Tailwind CSS와 shadcn/ui를 함께 사용할 생각이다. Tailwind는 빠르게 UI를 구성하기에 정말 편하고, shadcn은 기본 컴포넌트를 깔끔하게 제공해줘서 디자인 작업 시간을 많이 줄여준다. 특히 이번 프로젝트처럼 혼자 개발할 때는 이런 생산성이 굉장히 중요하다.
LLM이 등장하기 전에는 웹사이트를 만든다는 것이 곧 “모든 것을 직접 구현한다”는 의미에 가까웠다. 작은 기능 하나를 추가하더라도 공식 문서를 찾아보고, 예제를 참고하고, 시행착오를 반복하면서 하나씩 완성해 나가는 과정이 필요했다. 그 과정 자체가 개발자의 실력이었고, 동시에 많은 시간과 집중력을 요구하는 일이기도 했다.
하지만 지금은 상황이 많이 달라졌다. 다양한 AI 도구들이 등장하면서, 단순한 기능 구현이나 반복적인 작업들은 더 이상 사람이 직접 모든 코드를 작성하지 않아도 되는 시대가 되었다. 프롬프트를 잘 작성하면 기본적인 구조나 기능은 빠르게 만들어낼 수 있고, 초기 개발 속도는 이전과 비교할 수 없을 정도로 빨라졌다. 말 그대로 “뚝딱”이라는 표현이 어울릴 만큼 빠르게 결과물을 만들어낼 수 있다.
그렇다고 해서 모든 문제가 해결된 것은 아니다. 오히려 실제로 사용할 수 있는 수준의 서비스를 만들기 시작하면, 다른 종류의 어려움이 나타난다. 기능이 하나둘 추가될수록 구조는 복잡해지고, AI가 생성한 코드들이 쌓이면서 일관성이 깨지거나 코드가 지저분해지는 경우도 많다. 처음에는 빠르게 만들어진 것처럼 보이지만, 시간이 지날수록 유지보수가 어려워지는 상황이 생기기도 한다. 그래서 이번 프로젝트에서는 하나의 기준을 정했다.
전체적인 구조와 흐름은 내가 직접 설계하고, 세부적인 구현은 AI의 도움을 받는다.
즉, 어떤 페이지가 필요하고, 데이터는 어떻게 흐르며, 기능은 어떤 순서로 동작해야 하는지와 같은 큰 틀은 스스로 이해하고 있는 상태에서 작업을 진행한다. 그 위에 반복적이거나 비교적 단순한 구현, 혹은 빠르게 테스트가 필요한 부분들은 AI를 활용해 효율적으로 처리하는 방식이다. 이렇게 하면 개발 속도를 유지하면서도 코드의 방향성과 일관성을 잃지 않을 수 있다.
이번 작업에서는 OpenAI Codex와 Claude 같은 도구들을 함께 활용할 예정이다. 다만 이 글을 보고 있는 분들이 사용하는 도구나 방식은 충분히 다를 수 있다. 어떤 AI를 사용하든, 혹은 직접 코드를 작성하든 그것 자체는 중요한 요소가 아니다. 중요한 것은 “어떤 구조로 만들 것인가”, 그리고 “어떤 흐름으로 서비스를 완성할 것인가”에 대한 이해다. 이 튜토리얼에서는 그 핵심적인 방향과 구조를 중심으로 설명하려고 한다. 즉, 뼈대와 기둥을 세우는 과정에 집중하고, 세부적인 구현이나 반복적인 코드 작성은 각자의 방식과 도구를 활용해 채워 넣는 것을 권장한다.
결국 이 과정의 목적은 단순히 하나의 사이트를 완성하는 것이 아니라, AI와 함께 효율적으로 개발하는 방법을 익히는 것에 있다. 전체적인 흐름을 이해하고 나면, 그 위에 어떤 도구를 사용하든 자신만의 방식으로 확장해 나갈 수 있을 것이다.