화면보다 보이지 않는 곳이 더 중요했다
Santiago Brain을 만들면서 처음에는 화면에 보이는 기능에 관심이 많았다.
오늘 할 일 화면,
목표 화면,
프로젝트 화면,
브레인 대화 화면.
그런데 앱이 조금씩 커지면서 알게 됐다.
화면보다 더 중요한 것은 그 뒤에서 데이터를 어떻게 저장하고 연결하느냐는 것이었다.
Santiago Brain에서는 이 역할을 Supabase가 맡고 있다.
처음에는 Supabase를 그냥 “데이터를 저장하는 곳” 정도로 생각했다.
하지만 실제로 사용해보니 데이터베이스는 단순한 창고가 아니었다.
무엇과 무엇이 연결되어 있는지,
어떤 상태인지,
삭제했을 때 어디까지 영향을 주는지,
같은 일이 두 번 저장되지 않는지까지 관리해야 했다.
목표 하나에도 여러 관계가 생긴다
예를 들어 목표 하나를 만든다고 해보자.
그 목표 아래 프로젝트가 여러 개 있을 수 있다.
각 프로젝트에는 마일스톤이 있을 수 있다.
마일스톤 아래에는 할 일이 있다.
또 어떤 할 일은 프로젝트 없이 목표에 직접 연결될 수도 있다.
이렇게 되면 단순히 데이터를 따로 저장하는 것만으로는 부족하다.
서로 어떤 관계인지 연결정보를 저장해야 한다.
그래서 Santiago Brain은 점점 이런 구조를 가지게 됐다.
목표
→ 프로젝트
→ 마일스톤
→ 할 일
하지만 실제 사용에서는 항상 이렇게만 흘러가지 않았다.
할 일
→ 목표 직접 연결
아이디어
→ 프로젝트 전환
결정
→ 프로젝트 참고
이런 관계도 필요했다.
중복 저장 문제는 생각보다 자주 생겼다
AI와 함께 개발하다 보면 같은 저장 요청이 두 번 들어갈 가능성도 있다.
사용자가 버튼을 두 번 누를 수도 있고,
서버가 응답을 기다리다가 재시도할 수도 있다.
네트워크가 느릴 때 같은 요청이 다시 들어갈 수도 있다.
처음에는 이것을 크게 생각하지 않았다.
그런데 실제로는 같은 프로젝트나 같은 할 일이 두 번 생기는 문제가 발생할 수 있었다.
예를 들어,
“유튜브 1강 원고 작성”
이라는 할 일이 두 번 저장되면,
진행률도 틀어지고,
오늘 화면에도 두 번 보이고,
나중에는 어느 것이 진짜인지 구분하기 어려워진다.
그래서 저장 기능에는 중복 방지가 필요했다.
프로젝트를 저장하다가 중간에 실패하는 문제
더 어려운 문제도 있었다.
프로젝트를 만들 때 프로젝트 하나만 저장하는 것이 아니었다.
완료조건,
마일스톤,
필수 할 일,
일반 할 일
같은 것도 함께 만들어질 수 있다.
그런데 저장 도중에 문제가 생기면 어떻게 될까.
프로젝트는 만들어졌는데 마일스톤은 저장되지 않고,
할 일은 일부만 생길 수도 있다.
이런 상태가 가장 곤란하다.
겉으로는 프로젝트가 있는 것처럼 보이지만,
안쪽 데이터는 절반만 만들어져 있기 때문이다.
그래서 나중에는 프로젝트 생성 과정을 가능한 한 하나의 작업처럼 처리하는 방향으로 바꿨다.
중간에 실패하면 일부만 남지 않도록 하는 것이다.
삭제는 더 조심해야 했다
데이터베이스에서 가장 무서운 기능 중 하나가 삭제였다.
처음에는 프로젝트를 삭제하면 그냥 그 프로젝트 데이터만 지우면 된다고 생각했다.
하지만 연결된 할 일이 있으면 문제가 생긴다.
예를 들어 프로젝트를 삭제했다고,
그 아래 연결된 할 일까지 모두 같이 삭제해버리면 안 될 수도 있다.
그 할 일이 다른 목표에도 연결되어 있을 수 있기 때문이다.
그래서 삭제 정책을 따로 정했다.
삭제한다고 해서 관련 데이터를 무조건 같이 지우지 않는다.
필요하면 보관하고,
복원할 수 있게 하고,
연결관계도 최대한 유지한다.
즉 삭제보다 관계 보존이 우선이었다.
보관과 삭제는 다른 개념으로 만들었다
실제로 쓰다 보면 완전히 없애고 싶은 것보다,
지금은 안 보이게 하고 싶은 것이 더 많다.
그래서 보관과 삭제를 구분했다.
보관은 숨기는 것이다.
나중에 다시 꺼낼 수 있다.
삭제는 정말 필요 없을 때 사용한다.
이 차이를 두니 훨씬 안전해졌다.
그리고 실수로 지웠을 때를 대비해 휴지통과 복원도 고려하게 됐다.
데이터베이스 구조를 바꾸는 일은 더 어려웠다
앱을 처음 만들 때와 나중에는 구조가 달라진다.
처음에는 없던 기능이 생긴다.
예를 들어 처음에는 마일스톤이 없었다가 나중에 추가될 수 있다.
프로젝트와 목표 연결 방식도 달라질 수 있다.
이럴 때는 데이터베이스 구조도 바꿔야 한다.
그런데 새 구조만 생각하면 안 된다.
이미 저장되어 있는 기존 데이터가 있기 때문이다.
새 칼럼을 추가하고,
새 관계를 만들고,
기존 데이터를 새로운 구조에 맞춰야 할 수 있다.
이런 변경 작업을 migration이라고 한다.
처음에는 이 단어 자체도 낯설었다.
하지만 개발을 하면서 매우 중요한 개념이라는 것을 알게 됐다.
migration이 코드와 맞지 않는 문제
개발하다 보면 코드에서는 새 구조를 기대하고 있는데,
실제 데이터베이스에는 그 변경이 아직 반영되지 않은 경우가 있다.
반대로 데이터베이스는 바뀌었는데,
테스트나 코드 일부가 예전 구조를 보고 있을 수도 있다.
그러면 화면에서는 이상한 오류가 난다.
이런 문제는 단순히 버튼 위치를 수정하는 것보다 훨씬 까다롭다.
잘못 건드리면 기존 데이터까지 영향을 받을 수 있기 때문이다.
그래서 데이터베이스 관련 문제는 항상 더 조심하게 됐다.
테스트가 중요한 이유를 여기서 많이 배웠다
화면 하나를 수정했을 때는 눈으로 확인하면 되는 경우가 많다.
하지만 데이터베이스는 눈으로만 보기 어렵다.
예를 들어 프로젝트를 옮겼을 때,
원래 프로젝트의 진행률이 내려가는지,
새 프로젝트의 진행률이 올라가는지,
같은 할 일이 두 번 계산되지 않는지,
삭제 후 복원했을 때 관계가 그대로 남는지
확인해야 한다.
그래서 자동 테스트가 중요해졌다.
처음에는 테스트를 귀찮은 과정으로 생각할 수도 있다.
하지만 기능이 많아질수록 테스트가 없으면 한 곳을 고쳤다가 다른 곳이 망가질 수 있다.
‘진행률’도 결국 데이터 문제였다
화면에 보이는 진행률은 단순한 숫자처럼 보인다.
하지만 그 숫자를 만들기 위해서는 데이터베이스 관계가 정확해야 한다.
예를 들어 프로젝트 진행률은
그 프로젝트에 속한 필수 할 일 중
몇 개를 완료했는지를 계산해야 한다.
그런데 같은 할 일이 여러 경로로 연결되어 있으면 한 번만 세야 한다.
할 일이 다른 프로젝트로 이동하면 양쪽 진행률이 같이 바뀌어야 한다.
필수 할 일이 하나도 없으면 0/0 같은 이상한 표시가 나오면 안 된다.
그래서 진행률은 화면 기능처럼 보이지만,
사실은 데이터 설계와 관계 계산의 문제였다.
아이디어를 프로젝트로 바꾸는 것도 단순하지 않았다
아이디어를 저장해두었다가 나중에 프로젝트로 전환하는 기능도 만들었다.
처음에는 단순히 아이디어 제목을 프로젝트 제목으로 복사하면 될 것 같았다.
하지만 실제로는 더 많은 것이 필요했다.
기존 아이디어가 무엇이었는지 남겨야 했다.
이미 프로젝트로 전환한 아이디어를 다시 전환하면 안 됐다.
프로젝트 저장이 실패하면 아이디어 상태가 잘못 바뀌면 안 됐다.
전환이 끝나면 두 데이터가 서로 연결되어야 했다.
이런 작은 기능 하나에도 데이터 관계가 여러 개 생겼다.
데이터베이스는 ‘기억’의 신뢰성을 만드는 곳이었다
Santiago Brain이라는 이름처럼,
이 앱은 나의 목표, 결정, 프로젝트, 할 일, 기록을 기억해야 한다.
그런데 기억을 제대로 하려면 단순히 많이 저장하는 것으로는 부족하다.
잘못 저장되지 않아야 한다.
중복되지 않아야 한다.
관계가 끊어지지 않아야 한다.
삭제해도 필요한 것은 복원할 수 있어야 한다.
이전 결정과 현재 상태를 연결할 수 있어야 한다.
결국 데이터베이스의 역할은
많이 기억하는 것이 아니라, 정확하게 기억하는 것이었다.
화면보다 데이터 수정이 더 무서웠다
개발을 하다 보면 화면 수정은 비교적 마음이 편하다.
버튼 색이 잘못되거나,
문구가 이상하면 다시 고치면 된다.
하지만 데이터베이스는 다르다.
잘못 수정하면 기존 기록이 바뀌거나 없어질 수도 있다.
그래서 점점 이런 습관이 생겼다.
먼저 원인을 확인한다.
데이터를 바로 수정하지 않는다.
가능하면 읽기 전용으로 점검한다.
테스트 데이터로 확인한다.
기존 데이터가 영향을 받지 않는지 본다.
그다음에 수정한다.
이런 과정이 느려 보여도 결국 더 안전했다.
비용 문제도 데이터베이스와 연결됐다
Supabase도 사용량이 커지면 비용이 생길 수 있다.
그래서 처음부터 너무 복잡한 구조를 만드는 것도 부담이었다.
필요한 데이터만 저장하고,
같은 내용을 반복 저장하지 않고,
외부 서비스에 이미 있는 데이터는 꼭 필요한 경우에만 가져오는 방향을 생각했다.
예를 들어 Google Tasks 데이터를 전부 복사해서 Brain에 저장하기보다,
원본은 Google에 두고 필요한 상태만 Brain에서 관리하는 방식도 선택했다.
이런 결정은 개발비뿐 아니라 장기 운영비를 줄이는 데도 중요했다.
만들면서 알게 된 데이터베이스의 진짜 의미
처음에는 데이터베이스가 단순히 자료를 넣어두는 서랍이라고 생각했다.
지금은 조금 다르게 생각한다.
Santiago Brain에서 데이터베이스는
목표와 행동을 연결하는 지도이고,
과거와 현재를 이어주는 기억이며,
앱이 일관되게 판단하게 만드는 기준이다.
화면은 바뀔 수 있다.
메뉴 이름도 바뀔 수 있다.
하지만 데이터 구조가 엉키면 앱 전체가 흔들린다.
그래서 지금은 새로운 기능을 만들 때
“화면을 어떻게 만들까?”보다 먼저
“이 데이터는 어디에 저장되고 무엇과 연결되는가?”
를 생각하게 됐다.
다음 글 예고
9편 — Santiago Brain을 만들며 가장 많이 겪은 오류들
다음 글에서는 실제 개발하면서 반복해서 겪었던 문제들을 정리해보려고 한다.
버튼을 눌러도 반응이 없는 문제,
영어 상태값이 화면에 그대로 보이는 문제,
Preview에서는 고쳐졌는데 실제 사이트에는 옛 화면이 나오는 문제,
Google 일정은 있는데 Brain에서는 없다고 하는 문제,
같은 할 일이 중복되는 문제,
문자는 오는데 일정 내용이 틀리는 문제까지.
그리고 이런 오류를 만날 때마다 화면 캡처 하나를 들고 AI와 어떻게 원인을 찾아갔는지 실제 사례 중심으로 이야기해보겠다.
