3차 프로젝트도 잘 마무리 했다! 2차 프로젝트보다 기간이 짧게 느껴졌는데 실제로도 더 짧은 기간이었다. 그래서 우리 팀은 프로젝트 볼륨을 줄이는 대신 서비스의 퀄리티에 집중해 보자라는 목표를 세우고 기획하게 되었다. 그리고 그 목표를 나름대로 잘 달성한 것 같다는 생각이 든다.
# 프로젝트 개요
우리 과정에서 강사님은 Slido라는 익명 게시판을 통해 자유롭게 소통하곤 했다. 익명으로 소통할 때면 수강생들은 기명으로 소통할 때 보다 더욱 적극적이고 재밌어했다. 하지만 Slido의 단순한 텍스트 기반의 소통 방식이 다소 아쉽다는 생각이 들었고 여기에 더 재미있는 기능들을 추가한다면 어떨까 하는 아이디어가 떠올랐다. 그래서 우리만의 개선된 버전의 Slido를 만들어 수업 시간에 강사님께서 실제로 사용하는 것을 목표로 프로젝트를 기획하게 되었다. •프로젝트명 : Anonimo (스페인어로 익명)
•개발 기간 : 3주 ( 2025.08.18 ~ 2025.09.08 )
•팀 구성 : 4명
•기술 스택 : React, Supabase, Vite, Husky
•사용 라이브러리 : Zustand, Tanstack/react-virtual, Konva, GSAP
# 기획과 설계 단계
수강생들의 프로젝트 열정으로 2차때 대부분 팀들의 프로젝트 볼륨이 컸던 것 같다. 이전 팀에서 작업했던 프로젝트 Seediary 역시 기능 구현에만 치중했고 정작 중요한 서비스 퀄리티와 코드 퀄리티는 가져가지 못했던 것 같아 아쉬움이 많았다. 이번 3차 프로젝트를 같이 할 팀원들도 비슷한 생각을 했다고 했다. 그래서 우리는 기획 단계부터 서비스 성능 최적화와 코드 퀄리티에 신경 쓸 수 있도록 프로젝트 볼륨을 줄이고 단기 프로젝트 성공 목표를 세울 수 있는 아이디어를 기획해보자는 방향으로 목표를 가지게 되었다. 또한 서비스 퀄리티에 대한 명확한 목표를 세우기 위해 Lighthouse 지표 95점 이상이라는 목표도 세우게 되었다. 단기 프로젝트 성공 목표는 “강사님이 Slido 대신 우리의 서비스를 사용할 수 있을 정도의 퀄리티를 만들어보자” 였다.
최종 기획 방향
텍스트만으로 소통하는 Slido에 이미지 첨부, Canvas API를 활용한 그림 그리기, 슬랙의 이모지 기능 그리고 각 피드의 댓글 기능을 추가한 확장형 익명 소통 서비스를 기획하게 되었다. 사용자의 쉽고 빠른 경험을 위해 로그인이 필요 없이 사용할 수 있도록 기획했고 어느정도 사용자 구분이 필요하기에 브라우저 핑거프린트를 구현해 익명 사용자도 구분할 수 있게 했다. 주요 기능 설계
•스레드 방 개설 (로그인 필요)
•스레드 링크 및 qrcode 공유
•실시간 피드 소통 (익명 채팅)
•실시간 피드 이모지, 댓글
•스레드 관리 (비밀번호 수정, 삭제)
기술적 설계
•프론트엔드 : React
•백엔드 : Supabase
•라이브러리 : Zustand, tanstak/react-virtual, Konva, gsap
# 개발 과정
내가 맡은 파트는 피드 실시간 업데이트 및 최적화 (가상화), 이모지 실시간 업데이트 및 낙관적 업데이트, 공통 모달 레이아웃, 공통 Input 컴포넌트, 이스터에그 설계 및 구현, 프로젝트 셋업이였다.
프로젝트를 진행하면서 마주한 트러블 슈팅을 정리해 보았다.
1. 피드 실시간 업데이트
이 서비스는 채팅에 가깝기 때문에 대부분의 기능에서 실시간 업데이트가 필요했다. 피드 등록과 피드 이모지 그리고 댓글까지 모든 데이터를 실시간으로 감지하고 업데이트하기 위해 Supabase Real-time을 사용하여 모든 피드를 감지하게 했다.
문제 상황
서비스 특성상 무한스크롤 페이지네이션을 구현해야 했는데 만약 사용자가 스크롤을 내리며 모든 피드를 마운트한다고 가정했을 때 피드가 100개 이상이 되었을 경우 성능 부하를 일으킬 것을 우려하게 되었다.
해결 방안
이 상황을 개선하기 위해 tanstack/react-virtual을 도입했다. 가상화(Virtualization)를 통해 전체 피드 목록 중 화면 보이는 피드만 DOM에 렌더링하여 필요한 요소에 선택적 구독을 할 수 있게 되었다.
화면에 보이는 요소들만 마운트되고 보이지 않는 요소들은 언마운트되면서 효율적인 구독 관리가 가능해졌다. 결과적으로 리스트 렌더링 최적화와 실시간 구독 관리 최적화를 동시에 챙길 수 있어 성능과 효율을 크게 향상시킬 수 있는 좋은 선택이었다.
2. 이모지 낙관적 업데이트
Slido와 다르게 각 피드 마다 사용자들이 반응을 실시간으로 업데이트하여 좀 더 인터렉티브한 서비스를 만들었다. 슬랙의 이모지 기능을 그대로 가져와 다양한 이모지를 등록할 수 있도록 frimousse 이모지 라이브러리를 사용했다.
문제 상황
이모지 등록을 시도하면 클릭 → 서버 통신 → 성공/실패 여부 → UI 업데이트 과정을 거치기 때문에 즉각적으로 반영되지 않고 약간의 지연이 생겨 지루하게 느껴지고 모바일이나 느린 네트워크 환경에서 지연이 두드러졌다. 또한 이모지를 연속으로 클릭하면 끊김이 발생하여 즉각적인 피드백이 제공되지 않았다. 이는 사용자 경험과 참여도를 저하시키는 원인이 되었다.
해결 방안
이모지 업데이트 기능에 낙관적 업데이트와 Debounce를 적용했다. 이모지 기능은 간단한 액션으로 실패할 확률이 낮고 설령 실패하더라도 서비스에 큰 영향을 주지 않는 특성을 가지고 있다. 이러한 특성을 활용해 낙관적 업데이트를 도입함으로써 사용자가 이모지를 클릭하는 즉시 UI에 반영되어 즉각적인 피드백을 제공할 수 있게 되었다.
채팅이나 SNS에서 이모지는 즉각적인 반응을 표현하는 수단이다. 통신 결과를 기다리지 않고 바로 UI가 업데이트되면서 자연스럽고 반응성 좋은 사용자 경험을 만들어낼 수 있었다. 또한 답답함을 느낀 사용자가 이모지를 연속으로 클릭하여 불필요한 네트워크 요청이 발생하거나 UI가 불안정해지는 것을 방지하기 위해 Debounce을 적용했다. 이를 통해 안정적인 네트워크 통신과 일관된 사용자 경험을 보장할 수 있도록 설계했다.
Throttle을 적용했으나, 이후 학습을 통해 사용자의 최종 선택만 반영하는 Debounce가 더 적합하다는 것을 깨닫고 변경했다.
3. 이미지 라사이징
그림 그리기와 이미지 업로드 기능 구현 완료 후 Lighthouse로 성능을 측정한 결과, Performance 점수가 55점이라는 아쉬운 결과를 받았다.
문제 상황
그림 그리기와 사진 업로드 기능을 통해 용량이 큰 이미지들이 다수 업로드되면서 이미지 다운로드 시간이 길어져 LCP(Largest Contentful Paint) 점수가 크게 저하되었다. 피드에서 이미지가 가장 큰 콘텐츠 요소인데 용량이 큰 원본 이미지를 그대로 렌더링하다 보니 페이지 로딩 성능이 현저히 떨어지게 되었다. 실시간 피드백이 핵심인 우리 서비스에는 이러한 성능 저하가 사용자 경험에 치명적인 영향을 미칠 수 있어 반드시 해결해야 할 문제였다.
해결 방안
이 문제를 해결하기 위해 이미지 리사이징을 도입하기로 결정했다. 당초 백엔드에서 처리하려 했으나 Supabase Edge Function에서는 필요한 라이브러리 사용에 제약이 있어 클라이언트 사이드에서 구현하는 방향으로 전환했다.
사용자가 그림을 그리거나 이미지를 업로드할 때 클라이언트에서 이미지를 압축하고 리사이징한 후 원본과 압축된 이미지를 모두 Storage에 저장하도록 구현했다. 피드 목록에서는 압축된 이미지를 사용해 빠른 로딩을 보장하고 사용자가 이미지를 저장할 때는 고화질의 원본을 다운로드할 수 있도록 설계했다.
그 결과 Lighthouse Performance 점수가 55점에서 98점으로 크게 향상되어 사용자에게 훨씬 더 쾌적한 서비스 경험을 제공할 수 있게 되었다.
4. 이스터에그
사용자들에게 재미있는 경험을 제공하기 위해 숨겨진 이스터에그 기능을 구현했다. 이 과정에서 확장 가능한 설계에 대한 고민과 코드 개선을 경험할 수 있었다. 이스터에그를 설계 및 구현하면서 마주한 문제점과 해결 과정 그리고 확장성을 고려한 리팩토링에 대한 자세한 글은 여기서 확인할 수 있다. # 결과
다른 팀에 비해 페이지와 기능이 적었기 때문에 어떻게 하면 최적화와 성능을 극대화할 수 있을까 사용자 플로우를 얼마나 자연스럽게 만들 수 있을까에 대한 고민을 정말 많이한 프로젝트였다. 특히 우리의 서비스는 사용자들이 동시에 네트워크 통신을 하며 실시간 피드백을 주고받는 특성을 가지고 있어 최적화는 선택이 아닌 필수 였다고 생각이 들었다. 이러한 서비스에서는 작은 지연이나 끊김도 사용자 경험을 크게 해칠 수 있기 때문이다.
강사님께서 기존의 Slido 대신 Anonimo를 실제 수업에서 사용해 주셨다. 그래서 프로젝트 초기에 설정했던 단기 프로젝트 성공 목표를 달성할 수 있었고 더 나아가 강사님께서 다음 기수에도 지속적으로 사용해 보겠다고 말씀해 주셨다. 앞으로도 서비스를 지속적으로 개선하고 발전시키기 위해 Github Discussion을 오픈하여 실제 사용자들과 강사님의 소중한 피드백을 수집하고 반영해 나갈 예정이다. # 배운점과 성장
이전 프로젝트들을 돌이켜보면 대부분 최적화보단 기능 구현에만 집중했던 것 같다. 기획 단계에서 다양한 기능들과 도전적인 기술 스택을 욕심내어 추가하다 보니 정작 최적화를 위한 기간이 부족했었다. 하지만 이번 프로젝트에서는 팀원들과 함께 명확한 목표를 설정하고 이를 달성해 나가면서 이전과는 다른 성취감을 느낄 수 있었다.
이 경험을 통해 깨달은 것은 앞으로는 단순히 기능 구현에만 그치지 않고 사용자에게 자연스러운 플로우을 제공하면서 서비스 전체적인 퀄리티를 높이는 것이 더 중요하다는 점이다.
프로젝트는 마무리되었지만 여전히 아쉽고 개선하고 싶은 부분들이 정말 많은데 수료하고 난 후 하나씩 차근차근 개선해 나가볼 계획이다!
# 마치며
3주동안 정말 밤 낮을 가리지 않고 열심히 해준 팀원들 덕분에 3차 프로젝트도 1등을 할 수 있었다. 다른 팀들의 프로젝트도 퀄리티도 정말 좋아 큰 기대하지 않았지만 이번에도 1등을 할 수 있어 너무 기뻤다. 이번 프로젝트를 통해 팀원들은 성능 최적화에 대한 중요성을 다시 한번 깨닫게 되었고 앞으로도 우리의 Anonimo를 꾸준히 업데이트 해 나가며 값진 경험을 이어나가볼 생각이다.
🖊️ Anonimo 체험해보기
저희 서비스 Anonimo는 여기서 직접 사용해 볼 수 있습니다.
친구들과 아니면 가까운 지인들과 익명으로 실시간 소통하며 평소 전하지 못했던 진심을 익명으로 전달해보세요!