Codex와 함께 만든 실시간 칸반 보드: DESIGN.md부터 Supabase, Vercel 배포까지

이 글을 읽으면 얻을 수 있는 것

  • 디자인을 잘 모르는 개발자가 DESIGN.md로 AI 생성 UI의 기준을 잡은 과정
  • Supabase Auth·Realtime·RLS를 MVP에 연결하며 확인한 실무 포인트
  • Codex와 함께 구현부터 Vercel 배포까지 마무리한 경험

최근 AI 코딩 도구를 활용해 스터디와 소규모 프로젝트에서 사용할 수 있는 칸반 보드 웹 애플리케이션을 만들어 보았다. 프로젝트 이름은 Orbit Board다.

이번 프로젝트에서는 특별한 개발 하네스나 복잡한 자동화 환경을 별도로 구성하지 않았다. 대신 shadcn.io의 Linear 디자인 페이지에서 제공하는 마크다운을 복사한 뒤, Next.js 프로젝트 최상위에 DESIGN.md 파일을 만들어 그대로 붙여 넣었다. 그리고 Codex가 개발을 시작하기 전에 이 문서를 읽어 전체 화면에 일관되게 적용하도록 했다.

기술 스택으로는 Next.js, TypeScript, Tailwind CSS, shadcn/ui 스타일의 컴포넌트와 함께 Supabase를 사용했다. Supabase는 주변에서 많이 사용하는 서비스라 한 번 제대로 경험해 보고 싶었다. 처음에는 단순히 PostgreSQL 데이터베이스를 편하게 사용할 수 있는 서비스 정도로 생각했지만, 실제로 사용해 보니 인증, Realtime, 서버 함수, 보안 정책까지 애플리케이션의 백엔드 전반을 담당할 수 있었다.

특히 Row Level Security, 즉 RLS를 적용하면서 “로그인했는가?”만 확인하는 것과 “이 사용자가 이 데이터에 접근할 권한이 있는가?”를 데이터베이스 단계에서 보장하는 것은 완전히 다른 문제라는 사실을 배웠다.

개발이 끝난 뒤에는 Vercel 배포도 직접 대시보드에서 하나씩 처리하지 않았다. Codex가 Vercel 프로젝트 설정과 환경변수 연결, 프로덕션 배포 및 동작 확인까지 진행했다. 코드를 작성하는 단계를 넘어 실제 서비스로 공개하는 과정까지 AI와 함께 진행해 본 셈이다.

결론 요약DESIGN.md는 AI가 만드는 화면의 일관성을 높였고, Supabase는 빠른 백엔드 구축에 유용했다. 다만 인증·권한·RLS는 자동으로 안전해지는 영역이 아니므로 개발자가 직접 구조를 이해하고 검증해야 했다.

시작 프롬프트

프로젝트는 다음과 같은 요구사항으로 시작했다.

Next.js, TypeScript, Tailwind CSS, shadcn/ui, Supabase를 사용해 스터디와 소규모 프로젝트를 위한 칸반 보드 웹 앱을 만들어줘.

Vercel 배포를 전제로 하고, 작업을 시작하기 전에 프로젝트 루트의 DESIGN.md를 읽어 전체 UI에 적용해줘.

Linear에서 영감을 받은 세련되고 프리미엄한 생산성 앱 분위기를 원하지만, Linear 자체를 그대로 복제하지는 않았으면 좋겠어.

필수 기능은 다음과 같아.

  • Supabase Auth를 이용한 회원가입과 로그인
  • 워크스페이스 생성과 멤버 관리
  • 4단계 칸반 보드와 카드 CRUD
  • 드래그 앤 드롭 카드 이동 및 순서 저장
  • 담당자, 우선순위, 마감일, 라벨
  • 체크리스트와 댓글, 오늘 대시보드
  • Supabase Realtime과 역할 기반 RLS
  • 반응형 디자인과 loading·empty·error 상태

우선 핵심 기능이 실제로 동작하는 단순한 MVP를 완성해줘. 저장소를 먼저 확인한 다음 적절한 구조를 판단하고, 완료 후에는 실행 방법과 Supabase·Vercel 설정 방법도 정리해줘.

시작할 당시 저장소에는 사실상 DESIGN.md만 있었다. 기존 프로젝트를 수정하는 방식이 아니라, Codex가 요구사항과 디자인 문서를 바탕으로 애플리케이션 구조부터 새로 만드는 방식으로 진행됐다.

DESIGN.md로 UI의 기준 만들기

AI에게 단순히 “세련되게 만들어줘”라고 요청하면 결과물의 기준이 모호해진다. 화면마다 색상과 간격이 달라지거나, 불필요한 그라데이션과 그림자가 많이 사용될 수도 있다.

이번에는 디자인 기준을 처음부터 직접 작성하지 않았다. shadcn.io/design에서 Linear를 검색했고, Linear 디자인 시스템 페이지의 Copy markdown 기능으로 내용을 복사했다. 그다음 Next.js 프로젝트 최상위 경로에 DESIGN.md 파일을 만들고 복사한 내용을 붙여 넣었다.

이렇게 준비한 DESIGN.md에는 다음과 같은 기준이 담겨 있었다.

  • 거의 검은색에 가까운 배경과 단계별로 구분된 surface
  • 얇은 1px 테두리와 보라색 계열의 primary accent
  • 절제된 radius와 그림자
  • 장식보다 정보 밀도를 우선하는 구성
  • 데스크톱 사이드바와 모바일 하단 내비게이션
  • Linear에서 영감을 받되 그대로 복제하지 않는 방향

Codex는 이 문서를 바탕으로 로그인, 회원가입, 오늘 대시보드, 칸반 보드, 카드 상세, 멤버 관리 화면의 시각적 기준을 통일했다.

LEARNED디자인 문서는 사람끼리 협업할 때만 필요한 것이 아니었다. AI와 개발할 때도 색상, 간격, 분위기, 피해야 할 표현을 명시하면 훨씬 일관된 결과를 얻을 수 있었다.

Orbit Board 로그인 화면
Orbit Board 로그인 화면

프로젝트 기반 구성

프로젝트는 Next.js App Router를 중심으로 구성했다. 초기 구현 후 안정화 과정에서 최종적으로 Next.js 16.3.1과 React 19.2.8까지 업데이트했다.

Next.js란? React로 만든 화면에 라우팅과 서버 기능, 빌드 기능을 더해 웹 서비스를 구성하기 쉽게 만든 프레임워크다.

Next.js App Router
React & TypeScript
Tailwind CSS
Supabase
dnd-kit
Vitest & Playwright

Codex는 페이지 구조뿐만 아니라 Supabase 브라우저·서버 클라이언트, 인증 세션 처리, 전역 로딩 및 오류 화면, 환경변수 예시와 실행 문서까지 함께 구성했다.

Supabase Auth로 인증 구현하기

첫 번째 핵심 기능은 사용자 인증이었다. 이메일 회원가입과 이메일·비밀번호 로그인을 구현하고, 인증되지 않은 사용자가 제품 화면에 접근하면 로그인 페이지로 이동하도록 했다. 이메일 확인 링크를 처리하기 위한 Auth callback도 별도의 Route Handler로 구성했다.

클라이언트에서 로그인 여부만 확인하는 것이 아니라 서버에서도 세션을 확인하도록 구성해, 보호된 페이지가 인증 상태에 따라 올바르게 동작하도록 만들었다.

Supabase Auth를 사용하면서 회원가입 기능은 단순히 사용자 정보를 테이블에 저장하는 작업이 아니라는 점을 확인할 수 있었다. 인증 사용자는 Supabase의 auth.users에서 관리되고, 애플리케이션에서 사용할 이름과 아바타 등의 정보는 별도의 profiles 테이블로 관리해야 했다.

이를 연결하기 위해 신규 사용자가 생성되면 자동으로 profile을 생성하는 데이터베이스 트리거도 추가했다.

워크스페이스와 멤버 역할 설계

Orbit Board에서는 사용자가 워크스페이스를 만들고 다른 사용자를 멤버로 추가할 수 있다. 역할은 owner, admin, member로 구분했다.

워크스페이스가 생성될 때 생성자는 자동으로 owner가 되고 기본 라벨도 함께 만들어진다. 이미 가입한 사용자는 이메일을 이용해 멤버로 추가할 수 있다.

워크스페이스와 owner 멤버십이 따로 생성되다가 일부만 저장되는 상황을 피하기 위해 관련 작업은 PostgreSQL 함수인 RPC로 처리했다. 여러 데이터 변경을 하나의 서버 측 작업으로 묶은 것이다.

멤버 관리 기능에는 역할 변경과 멤버 제거도 포함했다. owner는 관리자나 일반 멤버와 다르게 보호되어야 하므로, 관리자가 owner를 제거하거나 다른 사용자에게 임의로 owner 역할을 부여할 수 없도록 정책을 구성했다.

칸반 보드 구현

메인 화면은 할 일, 진행 중, 검토, 완료의 네 상태로 구성된 칸반 보드다. 사용자는 카드를 생성하고 제목과 설명을 수정하거나 삭제할 수 있다.

각 카드에는 담당자, 우선순위, 마감일, 라벨, 체크리스트, 댓글을 설정할 수 있다. 카드 이동에는 dnd-kit을 사용했다. 같은 컬럼 안에서 재정렬하거나 다른 상태로 이동하면 변경된 상태와 순서가 데이터베이스에 저장되며, 새로고침한 뒤에도 배치가 유지된다.

작은 화면에서는 네 개의 컬럼을 억지로 축소하지 않고 가로 스크롤로 탐색하도록 했다. 데스크톱에서는 사이드바를, 모바일에서는 하단 내비게이션을 사용한다. 보드 상단에는 담당자와 우선순위 필터도 추가했다.

Orbit Board 칸반 보드
Orbit Board 칸반 보드

오늘 대시보드 만들기

칸반 보드만 있으면 전체 작업 상태를 보기에는 좋지만, 사용자가 지금 해야 할 일을 찾으려면 여러 컬럼을 계속 살펴봐야 한다.

이를 보완하기 위해 별도의 “오늘” 화면을 만들었다. 현재 로그인한 사용자에게 할당된 작업, 마감일이 가까운 작업, 아직 완료되지 않은 작업을 한곳에 모아 보여준다.

PRODUCT INSIGHT단순한 CRUD 애플리케이션과 실제 생산성 도구의 차이는 데이터를 저장하는 데만 있지 않았다. 사용자에게 필요한 정보를 어떤 기준으로 다시 보여주느냐가 중요했다.

Supabase는 단순한 DB가 아니었다

Supabase란? PostgreSQL 데이터베이스를 중심으로 인증, 실시간 동기화, 서버 기능을 한곳에서 제공하는 백엔드 서비스다.

이번 프로젝트에서 가장 많은 것을 배운 부분은 Supabase였다. 처음에는 데이터베이스를 빠르게 연결하기 위한 도구로 선택했지만, 실제 프로젝트에서는 다음 기능을 함께 사용했다.

  • PostgreSQL 데이터베이스
  • 이메일 기반 사용자 인증과 세션 관리
  • 데이터베이스 함수와 트리거
  • Realtime publication 및 구독
  • Row Level Security
  • 역할 기반 접근 제어

하나의 서비스를 사용했지만 내부적으로는 인증, 데이터 모델링, 실시간 이벤트, 권한 설계를 모두 생각해야 했다. Supabase가 많은 기능을 제공한다고 해서 보안과 데이터 구조까지 자동으로 해결되는 것은 아니었다. 오히려 사용자, 프로필, 워크스페이스, 멤버십, 작업 간의 관계를 더 명확하게 설계해야 했다.

RLS로 데이터 접근 권한 보호하기

RLS란? 건물 입구만 지키는 것이 아니라 각 방의 문마다 출입 권한을 검사하듯, 데이터베이스의 행 단위로 접근 권한을 확인하는 보안 기능이다.

어떤 사용자가 워크스페이스 주소를 직접 알아냈다고 해도 해당 워크스페이스의 멤버가 아니라면 작업 데이터를 읽거나 수정할 수 없어야 한다. 이 검사를 화면이나 API 코드에만 의존하면 구현 실수로 데이터가 노출될 수 있다.

RLS를 사용하면 데이터베이스가 현재 로그인한 사용자를 기준으로 각 행에 대한 접근 가능 여부를 판단한다. Orbit Board에는 다음과 같은 정책을 적용했다.

  • 익명 사용자의 애플리케이션 데이터 접근 차단
  • 워크스페이스 멤버만 해당 워크스페이스와 카드 조회 가능
  • 멤버만 카드, 체크리스트 및 댓글 작성 가능
  • owner와 admin만 멤버 역할 변경 및 제거 가능
  • 댓글은 작성자만 삭제 가능
  • 사용자 프로필은 본인 또는 같은 워크스페이스 멤버에게만 노출
  • 멤버 검색용 함수의 실행 권한 제한
  • owner 멤버십 수정 및 제거 방지

두 개의 계정을 사용해 실제 권한도 확인했다. 계정 A가 만든 워크스페이스에 B를 추가하고, B가 카드를 작성한 뒤 다시 멤버에서 제거하는 시나리오였다. 제거된 B가 기존 URL로 접근하거나 데이터를 수정하지 못하는 것을 확인했다.

SECURITYUI에서 버튼을 숨기는 것은 보안이 아니다. 최종 접근 권한은 서버와 데이터베이스에서도 보장해야 한다.

Realtime으로 여러 사용자 화면 동기화하기

Supabase Realtime을 이용해 작업, 체크리스트, 댓글, 라벨 연결, 워크스페이스 멤버십의 변경 사항을 구독했다.

두 개의 브라우저에서 서로 다른 계정으로 같은 워크스페이스에 접속한 뒤, 한쪽에서 카드를 이동하거나 댓글과 체크리스트를 변경하면 다른 화면에도 새로고침 없이 반영되는 것을 확인했다.

멤버십 변경도 Realtime에 포함했다. 한 사용자가 워크스페이스에서 제거되면 이미 열려 있던 그 사용자의 보드에서도 멤버십을 다시 확인하고 접근 가능한 화면으로 이동한다. Realtime은 새로운 데이터를 화면에 추가하는 기능뿐 아니라, 권한이 변경된 경우 현재 접근 상태를 즉시 정리하는 데도 사용할 수 있었다.

두 브라우저의 실시간 동기화 이동 전
두 브라우저의 실시간 동기화 (이동 전)

두 브라우저의 실시간 동기화 이동 전
두 브라우저의 실시간 동기화 (이동 후)

안정화와 테스트 자동화

핵심 기능을 완성한 뒤에는 프로젝트를 실제로 사용할 수 있는 상태로 다듬었다. 데이터 저장 중에는 버튼을 비활성화해 중복 제출을 방지하고, 실패했을 때는 사용자에게 오류 메시지를 보여주도록 했다. 드래그 결과를 저장하지 못하면 화면의 카드 배치를 이전 상태로 되돌리는 처리도 추가했다.

날짜는 시간대 변환에 영향을 받지 않도록 날짜 전용 문자열로 처리했다. 모바일 내비게이션과 보드 필터를 활성화하고, 실제 기능이 없는 버튼은 노출되지 않도록 정리했다.

검증을 위해 Vitest와 Playwright도 도입했다.

  • 날짜와 카드 정렬 로직 단위 테스트
  • 로그인 화면과 보호 경로 테스트
  • 선택적인 로그인 세션 E2E 테스트
  • TypeScript, ESLint, 프로덕션 빌드 검사

최종적으로 Next.js 16.3.1로 업데이트했고, 의존성 보안 검사에서도 알려진 취약점이 없음을 확인했다.

Vercel 배포도 Codex에게 맡겨 보기

Vercel이란? 만든 웹 애플리케이션을 인터넷에 배포하고 운영할 수 있게 해주는 호스팅 플랫폼이다.

개발이 완료된 뒤에는 Vercel 배포를 진행했다. 보통이라면 Vercel 대시보드에서 저장소를 연결하고 환경변수를 등록한 뒤, Supabase의 인증 URL을 수정하고 다시 배포해야 한다.

이번에는 Vercel과 Supabase의 설정도 직접 처리하지 않고 Codex에게 맡겼다. Codex는 Chrome 브라우저 제어 기능을 이용해 로그인된 대시보드에 접근하고, Vercel 환경변수 등록과 Supabase Auth callback URL 설정, 재배포 및 배포 결과 확인까지 수행했다.

단순히 배포 방법을 안내받은 것이 아니라, 로그인된 브라우저를 통해 실제 설정과 배포 작업까지 Codex가 수행했다는 점이 인상적이었다.

● Production

Orbit Board

Next.js와 Supabase로 만든 실시간 칸반 보드와 소스코드

코드 생성뿐만 아니라 외부 서비스 설정과 배포 후 검증까지 Codex가 이어서 처리하는 모습을 보면서 AI 코딩 도구의 역할이 상당히 넓어졌다는 것을 체감했다.

다만 모든 판단을 AI에 맡긴다는 의미는 아니다. 어떤 환경변수가 공개되어도 되는지, 인증 callback은 어디로 연결해야 하는지, 보안 정책은 의도대로 동작하는지 최종적으로 이해하고 확인하는 과정은 여전히 필요했다.

프로젝트를 마치며

이번 프로젝트를 통해 가장 크게 배운 점은 AI가 코드를 빠르게 작성해 주는 것과 실제로 사용할 수 있는 서비스를 완성하는 것은 다른 문제라는 것이다.

처음 화면이 만들어졌을 때는 거의 완성된 것처럼 보였다. 하지만 실제 서비스가 되기 위해서는 인증, 데이터 접근 권한, 여러 사용자 간 동기화, 실패 상태, 반응형 UI, 테스트, 환경변수, 배포 후 callback까지 모두 연결되어야 했다.

DESIGN.md를 사용한 경험도 인상적이었다. 구체적인 디자인 기준을 문서로 제공하자 여러 화면에서 색상과 간격, 정보 밀도가 비교적 일관되게 유지됐다. AI에게도 좋은 결과를 얻기 위해서는 좋은 컨텍스트와 명확한 기준이 필요하다는 것을 다시 느꼈다.

Supabase를 통해서는 Auth와 profile의 관계, RPC와 trigger, Realtime publication, 역할 기반 권한, RLS 정책까지 하나의 서비스를 만들기 위해 필요한 백엔드 요소를 폭넓게 경험할 수 있었다. 특히 화면에 보이지 않게 하는 것과 데이터에 접근할 수 없게 만드는 것은 전혀 다른 문제였다.

마지막으로 Vercel 배포까지 Codex가 직접 수행하게 하면서 AI를 단순한 코드 자동완성 도구가 아니라 개발 과정을 함께 진행하는 작업 파트너처럼 활용할 수 있었다. 나는 요구사항과 방향을 결정하고 결과를 확인했으며, Codex는 구현과 검증, 문서화, 배포를 이어서 수행했다.

무엇보다 “AI가 어디까지 만들어 줄 수 있는가?”보다 더 중요한 질문은 “내가 무엇을 명확하게 정의하고, 어떤 결과를 검증할 수 있는가?”라는 생각이 들었다. 다음 프로젝트에서는 시작 단계부터 요구사항뿐만 아니라 데이터 권한과 테스트 시나리오도 함께 문서화해 보고 싶다.


관련 글

#Codex #AI코딩 #바이브코딩 #DESIGNmd #shadcn #Supabase #칸반보드 #Vercel #프로젝트후기

댓글

이 블로그의 인기 게시물

클로드 Gmail 연동 방법: 이메일 분류·요약·답장 자동화

Claude Code 토큰 절약 가이드

Claude Code vs Codex vs Antigravity 비교: 2026년 AI 코딩 에이전트 무엇을 선택할까?