Uket

공연 사전 티켓팅 플랫폼

기존의 수기 명단 관리, 계좌 송금, 현장 혼잡 등 공연 운영 과정의 비효율을 개선하기 위해 시간대별 티켓팅, QR 기반 입장, 카카오 송금 연동, 알림톡 발송 기능을 지원한다. 사용성과 운영 실효성을 함께 고려해 직관적인 인터페이스와 가벼운 사용자 흐름을 구현했다. UKET은 2025년 1월, 약 100명이 참여한 서울 소재 대학 동아리 공연에서 처음 운영되었으며, 티켓 구매부터 QR 입장까지 전 과정을 안정적으로 처리하며 서비스의 실사용 가능성을 검증했다.

Period

2024.04 - 2025.08

Type

Team

Role

Frontend Engineer (100%)

Tech Stack

Next.js 15 (app router), TypeScript

preview images
preview images
preview images
preview images
preview images
preview images

Contributions

OpenGraph 메타데이터 적용을 통한 SNS 공유 미리보기 품질 개선

문제 배경
공연 서비스는 특성상 SNS를 통한 공연 정보 공유가 활발해, 링크 미리보기 품질이 유입과 전환에 직접적인 영향을 준다고 판단했다. 그러나 기존 Vite 기반 SPA 구조에서는 초기 HTML에 공연별 OpenGraph 메타데이터가 포함되지 않아, SNS 크롤러가 공연 제목, 설명, 이미지 정보를 읽지 못했다. 그 결과 공유 미리보기에 공연 정보가 정상적으로 노출되지 않았다.

접근 방식 #1
먼저 react-helmet-async를 적용해 클라이언트에서 메타 태그를 동적으로 변경하는 방식을 시도했다. 하지만 이 방식은 브라우저 렌더링 이후에 메타데이터가 반영되기 때문에, 초기 HTML만 읽는 SNS 크롤러 환경에서는 공연별 메타데이터를 안정적으로 제공할 수 없었다.

접근 방식 #2
다음으로 Puppeteer와 prerender 방식을 도입해 공연 상세 페이지를 사전 렌더링하고, 페이지별 HTML을 생성하는 방식을 적용했다. 이를 통해 동적 메타데이터를 포함한 HTML 생성에는 성공했지만, 배포 환경에서 Chromium 실행 이슈가 반복적으로 발생해 운영 환경에 안정적으로 적용하기 어려웠다.

접근 방식 #3
최종적으로 기존 Vite 기반 SPA 구조를 Next.js로 마이그레이션했다. 서버 사이드 렌더링 환경으로 전환한 뒤, Next.js의 Metadata API를 활용해 공연 상세 페이지별 메타데이터를 서버 응답 시점에 포함하도록 구현했다. 이를 통해 SNS 크롤러가 초기 HTML에서 공연 정보를 직접 읽을 수 있는 구조를 만들었다.

성과
배포 환경에서도 공연 상세 페이지의 SNS 공유 미리보기가 안정적으로 노출되도록 개선했다. 또한 Next.js 도입과 함께 렌더링 구조를 최적화해 초기 JS 번들을 675KB → 140KB로 줄였고, FCP를 4.1s → 1.1s로 개선했으며, Lighthouse Performance 점수도 약 20% 향상시켰다.

에러 처리 및 데이터 관리 구조 중앙화로 유지보수성 개선

문제 배경
React Query의 쿼리 키를 문자열로 직접 관리하면서 오타나 네이밍 불일치가 발생하기 쉬웠고, 갱신·무효화 로직의 일관성도 보장하기 어려웠다. 또한, 토스트와 에러 바운더리로 나뉜 에러 처리 로직이 컴포넌트마다 분산되어 있어, 정책 변경 시 여러 파일을 수정해야 하는 번거로움이 있었다.

접근 방식
에러 처리와 데이터 관리 책임을 공통 계층으로 모았다. Axios 인터셉터와 커스텀 에러 객체로 네트워크 에러를 표준화해 컴포넌트가 정리된 상태만 소비하도록 바꿨고, Query Key Factory를 도입해 도메인별 쿼리 키를 함수 형태로 관리하며 갱신·무효화 로직이 동일한 키 집합을 참조하도록 정리했다. (포스팅)

성과
에러 정책 변경 시 수정 범위를 1~2개 파일 수준으로 줄였고, 쿼리 관련 파일 수를 약 40% 감소시켰다. 그 결과 에러 처리와 캐시 관리의 일관성을 높이고 유지보수성을 개선했다.

RSC 기반 prefetch를 활용해 초기 렌더링 및 요청 워터폴 개선

문제 상황
기존 클라이언트 중심 useQuery 패턴은 페이지 진입 이후 브라우저에서 데이터를 요청하는 구조라 초기 화면에서 로딩 상태를 먼저 노출해야 했고, 컴포넌트별 loading/error 분기가 반복되기 쉬웠다. 또한 화면 구성에 필요한 데이터 요청이 클라이언트 마운트 이후 시작되면서, 초기 렌더링 구간에서 요청 워터폴이 발생하기 쉬워 서버 렌더링 이점을 충분히 활용하지 못했다.

접근 방식
RSC를 활용하여 페이지 단에서 데이터를 선조회하고, HydrationBoundary로 쿼리 캐시를 클라이언트에 전달한 뒤 RCC에서는 useSuspenseQuery로 hydrate된 데이터를 바로 읽는 구조로 전환했다. 이를 통해 데이터 패칭 흐름을 RSC prefetch -> hydration -> suspense query로 재구성했다.

성과
초기 데이터 요청 시점을 클라이언트 마운트 이후가 아니라 서버 렌더링 단계로 앞당겨 첫 화면 로딩 깜빡임을 줄였고, 페이지 진입 시 필요한 데이터의 요청 워터폴을 완화해 더 빠르게 콘텐츠가 표시되도록 개선했다. 또한,loading/error 분기와 중복 로직을 줄였고, 서버 중심 데이터 패칭 패턴을 공통 구조를 정착시켰다.

공연 정보 등록을 위한 리치 텍스트 에디터 도입

문제 정의
공연 등록 화면에서는 운영자가 정보를 빠르게 입력할 수 있어야 했다. 하지만 기존 textarea 방식은 입력은 단순했지만, 실제 사용자 화면에서는 내용이 줄글처럼 노출돼 주의사항이나 상세 안내의 구조가 잘 드러나지 않았다. 운영자의 입력 편의성은 있었지만, 최종적으로 사용자에게 전달되는 정보의 가독성과 전달력에는 한계가 있었다.

접근 방식
처음에는 textarea에 bullet 자동 삽입, Enter/Backspace 처리, 붙여넣기 변환, 들여쓰기 유지 같은 로직을 직접 구현해 문제를 해결하려 했다. 하지만 입력 패턴이 다양해질수록 예외 처리가 늘어나며 결과가 일관되지 않았고, 유지보수 비용도 빠르게 커졌다. 그래서 단순 입력 컴포넌트 위에 규칙을 계속 얹는 대신, 목록과 서식을 안정적으로 다룰 수 있는 리치 텍스트 에디터로 전환했다.

결과
리치 텍스트 에디터 전환 이후 운영자는 메뉴바와 slash command를 통해 굵게, 밑줄, 리스트 등 서식을 더 직관적으로 작성할 수 있게 됐다. 그 결과 공연 상세 정보와 주의사항을 더 구조적으로 전달할 수 있었고, 입력 로직의 복잡도와 오류 가능성도 함께 줄일 수 있었다.

가설 기반의 사용성 개선

문제 정의
서비스 출시 전 단계에서는 실제 사용자 피드백이 없었기 때문에, 사용자 관점에서 직접 서비스를 반복적으로 사용하며 불편이 발생할 수 있는 지점을 찾고 가설로 정의하면서 문제를 찾아나갔다.

문제 해결 #1 - 어드민 대시보드 개선
어드민 대시보드는 많은 데이터를 여러 관리자가 함께 운영하는 화면이기 때문에, 문제가 발생했을 때 현재 화면 상태를 빠르게 공유하고 동일한 화면을 재현할 수 있어야 한다고 판단했다. 또한 등록·수정·삭제 결과가 즉시 반영되지 않으면 운영 흐름이 끊길 수 있다는 가설을 세웠다.

기존에는 페이지네이션과 필터 상태가 메모리에만 저장되어 새로고침 시 유실됐고, URL만으로 현재 화면을 복원할 수 없었다. 이를 개선하기 위해 테이블 상태를 쿼리 스트링과 동기화해 페이지, 필터, 정렬 조건이 URL로 유지되도록 재설계했다. 또한 등록·수정·삭제 액션에는 optimistic update를 적용해 서버 응답 이전에 UI가 먼저 반영되고, 실패 시에는 이전 캐시 기준으로 롤백되도록 처리했다.

그 결과 새로고침 이후에도 화면 상태를 유지할 수 있게 되었고, 운영 이슈 발생 시 동일한 화면을 빠르게 공유할 수 있게 했다. 동시에 사용자 액션이 즉시 반영되도록 개선해 어드민 대시보드의 사용 흐름도 향상시켰다.

문제 해결 #2 - 회원가입 플로우 개선
회원가입은 서비스의 첫 진입 경험이기 때문에, 직접 플로우를 반복 점검하고 타 서비스 사례를 참고한 결과 한 화면에서 많은 정보를 한 번에 요구할수록 사용자가 복잡하게 느껴 이탈할 가능성이 높다고 판단했다.

이를 개선하기 위해 회원가입 구조를 퍼널 기반으로 재설계해, 입력 단계를 여러 화면으로 나눠 각 단계에서 처리해야 할 정보량을 줄였다. 또한 이메일 인증 코드 재전송 기능과 명확한 피드백 메시지를 추가해 인증 과정에서의 혼란도 줄였다.

그 결과 회원가입 플로우의 복잡도를 낮추고, 사용자가 더 가볍게 진입할 수 있는 가입 경험을 만들었다.

문제 해결 #3- 공연 정보 탐색 경험 개선
공연 정보는 예매 판단과 직접 연결되기 때문에, 사용자가 필요한 내용을 빠르게 찾고 핵심 정보를 쉽게 이해할 수 있어야 한다고 판단했다. 직접 서비스를 사용해보며 많은 정보를 한 화면에 나열할수록 사용자가 피로감을 느끼고, 정작 중요한 정보는 놓칠 수 있다는 가설을 세웠다.

이를 개선하기 위해 공연 상세 정보를 공연 정보, 위치, 환불 규정으로 나눠 성격에 따라 탭으로 분리하고, 핵심 정보만 우선 노출한 뒤 부가 정보는 모달로 확인할 수 있도록 구조를 재설계했다.

그 결과 정보 탐색 속도를 높이고 불필요한 피로도를 줄여, 공연 상세 페이지의 탐색 경험을 더 직관적으로 개선했다.