FE
[SvelteKit] 완벽한 ‘공유 기능’을 향한 여정: 서버, 서버리스, 그리고 방향 전환의 교훈
| 서론 — “내 회고, 어떻게 ‘잘’ 공유할 수 있을까?”
안녕하세요 팡일입니다!
Re-Log 프로젝트를 만들면서 가장 먼저 떠올린 기능 중 하나가 바로 공유였습니다. “내 회고를 다른 사람에게 링크로 건네줄 수 있다면 얼마나 편할까?” 처음엔 단순해 보였지만, 막상 만들다 보니 욕심이 생기기 시작했습니다.
어차피 만드는 김에 ‘그냥 되는 공유’가 아니라 ‘잘 만든 공유’를 만들어보고 싶다는 마음이 생겼고, 그 마음이 이번 여정을 조금 더 길고 복잡하게 만들었습니다.
| 본론 1. 공유 기능을 기획하며 했던 고민들
1) 공유 페이지는 어디에 둬야 할까?
Re-Log는 SvelteKit의 그룹 라우팅을 활용해 (private)과 (public)으로 페이지 접근을 분리하는 구조입니다. 그러다 보니 공유 페이지의 위치 역시 자연스럽게 고민이 되었습니다.
로그인 없이 누구나 접근할 수 있어야 하고
Firestore 보안 규칙을 복잡하게 만들지 않아야 하며
사용자의 민감한 정보는 절대 노출되면 안 되는 구조여야 한다
이 기준을 바탕으로, 공유 페이지는 (public) 그룹 아래 /share/[id] 라우트로 만들기로 결정했습니다.
2) Firestore 데이터는 어떻게 공개할까?
여기서 본격적인 고민이 시작됐습니다.
Firestore 문서를 클라이언트에 그대로 공개해도 될까?
공유 전용 필드만 모아두는 publicShare 컬렉션이 필요할까?
혹시 서버에서 한 번 가공한 데이터만 내려주는 구조가 더 안전할까?
여러 가능성을 검토한 끝에, ‘최소한의 데이터만 노출하는 방식’으로 방향을 잡았습니다.
문서 id를 기반으로 공유에 필요한 필드만 읽어 오고, 민감한 정보는 모두 제외하는 형태로 설계를 정리했습니다.
| 본론 2. 서버리스(Function)로 만들려다 실패했던 이유
여기서 제 욕심이 다시 고개를 들었습니다. “이 기능을 아예 서버리스로 만들어보면 어떨까? Firebase Functions로 SSR처럼 구현해보면 더 안전하고 멋지지 않을까?”
하지만 결론부터 말하자면, 이 선택은 Re-Log의 현재 구조에서는 ‘과한 설계(Over-engineering)’였습니다.
당시 제가 서버리스 구현을 시도했던 이유는 단순했습니다.
“데이터를 서버에 한 번 통과시켜서 가공해 내려주면 더 안전하지 않을까?”
하지만 실제로 부딪히며 느낀 문제들은 명확했습니다.
1) 유지보수 비용이 너무 컸다
Functions는
배포 시간이 길고
로컬 테스트 환경도 까다롭고
작은 변경에도 전체 로직을 다시 배포해야 하는 부담이 있었죠.
단순한 공유 페이지 하나를 위해 감당하기에는 과했습니다.
2) 공유 기능에는 사실상 서버가 필요하지 않았다
공유 페이지는 SEO가 필요한 것도 아니고, 서버에서 처리해야 할 복잡한 연산도 없었습니다. 그저 Firestore에서 필요한 필드만 안전하게 읽어 오면 충분했기 때문에 SSR을 구현해야 할 이유 자체가 약했습니다.
3) 오히려 전체 구조가 복잡해졌다
Functions를 끼워 넣자 'Firestore → Functions → 클라이언트' 이렇게 흐름이 길어졌고, Firestore 보안 규칙과 Functions 권한 관리를 둘 다 신경 써야 하는 이중 부담이 생겼습니다. Cold Start로 인해 발생하는 지연도 잠재적인 문제였습니다.
결국 “안전하게 만들고 싶다”는 선한 의도에서 출발했지만, 현실적으로는 이 기능에 맞지 않는 선택이라는 결론에 도달했습니다.
그래서 Functions를 과감히 걷어내고, 다시 SvelteKit의 기본 구조로 돌아왔습니다.
| 본론 3. 방향 전환 후 얻은 ‘명확하고 실용적인 공유 기능’
서버리스를 제거하고 나니 오히려 전체 흐름이 훨씬 명확해졌습니다.
1) SvelteKit 라우트 + CSR로 심플하게 구성
src/routes/(public)/share/[id]/+page.svelte 파일 하나로 공개 라우트를 만들고, 페이지 로드시 Firestore에서 데이터를 읽는 구조로 바꿨습니다. 복잡하지 않아서 개발 속도도 빨라졌고, 유지보수도 쉬워졌습니다.
2) Firestore 보안 규칙의 역할이 더욱 선명해졌다
서버라는 중간 계층이 사라지니, 보안의 책임이 오직 Firestore Security Rules에 집중되었습니다.
예를 들어 다음과 같은 규칙으로,
isPublic == true인 문서만
필요한 필드만 읽기 허용
목록 조회(list)는 금지
작성자 본인만 전체 읽기/쓰기 허용
이런 형태로 불필요한 노출 없이 안전하게 공유 기능을 제공할 수 있었습니다.
3) 인증 상태에 따른 UI 분리는 클라이언트에서 해결
SvelteKit의 $page.data.isAuthenticated 값을 활용해 로그인한 사용자에게만 수정/삭제 버튼을 노출하는 구조를 만들었습니다.
별도의 서버 인증 로직 없이도 “읽기 전용 공유 페이지”라는 목적을 깔끔하게 달성할 수 있었습니다.
| 결론 — 중요한 건 ‘멋진 기술’이 아니라 ‘맞는 기술’
이번 공유 기능을 구현하며 느낀 점은 정말 단순했습니다.
“기술이 멋지다고 해서, 그게 지금 나에게 맞는 기술은 아니다.”
서버리스를 적용해보고 싶은 개발자로서의 욕심은 자연스러운 것이고, 저 역시 그 마음으로 Firebase Functions를 시도했습니다. 하지만 한 바퀴 돌아와 보니, 실제로 해결해야 했던 문제는 훨씬 단순했습니다. SvelteKit의 기본 기능과 Firestore 규칙만으로도 충분히 안전하고 완성도 높은 공유 기능을 만들 수 있었습니다.
앞으로도 새로운 기술에 대한 도전은 계속하겠지만, 그보다 더 중요한 건 문제의 본질을 정확히 이해하고 그에 맞는 적정한 기술을 선택하는 일이라는 걸 다시 깨달은 경험이었습니다.