01
서버 비밀 키를 노출하지 않는 포스터 업로드
- 문제
- 브라우저에서 Supabase Storage에 직접 접근하면 높은 권한의 서버 키가 노출될 수 있고, 이미지를 Next.js 서버를 거쳐 전달하면 서버리스 환경에서 불필요한 트래픽과 메모리 사용이 발생할 수 있었습니다.
- 해결
- 관리자 세션과 파일 정보를 서버에서 검증한 요청에만 서명된 업로드 URL을 발급했습니다. 파일 형식과 크기를 클라이언트와 서버에서 모두 검사하고, 업로드 경로도 editor/{uuid}.{확장자} 형식으로 제한했습니다.
- 결과
- 서버 비밀 키를 브라우저에 노출하지 않으면서도 클라이언트가 Storage에 직접 포스터를 업로드하는 효율적인 구조를 구현했습니다.
02
서버리스 환경에서 관리자 세션 유지
- 문제
- Cloudflare Workers는 요청마다 실행되는 서버리스 환경이므로 서버 메모리에 로그인 상태를 저장할 수 없었고, 화면에서 관리 기능을 숨기는 것만으로는 API 접근을 보호할 수 없었습니다.
- 해결
- 만료 시각을 포함한 세션 데이터를 HMAC-SHA256으로 서명해 HttpOnly 쿠키에 저장했습니다. 등록·수정·삭제와 업로드 URL 발급 요청마다 Web Crypto API로 쿠키의 서명과 만료 시간을 다시 검증했습니다.
- 결과
- 별도의 세션 저장소 없이 7일간 유지되는 관리자 인증을 구현하고, 모든 데이터 변경 API를 서버에서 일관되게 보호했습니다.
03
데이터베이스와 이미지 Storage의 상태 동기화
- 문제
- 대회 정보만 수정하거나 삭제하면 이전 포스터가 Storage에 남고, 새 포스터 업로드 뒤 데이터베이스 작업이 실패하면 사용되지 않는 이미지가 누적될 수 있었습니다.
- 해결
- 포스터 교체 시 새 이미지 업로드와 데이터베이스 수정이 모두 성공한 뒤 기존 이미지를 제거했습니다. 데이터베이스 작업이 실패하면 새 파일을 삭제하고, 대회 삭제 시에는 연결된 포스터도 함께 정리했습니다.
- 결과
- 실패 상황에서도 이전 상태를 유지하도록 보상 처리를 구성해 데이터베이스와 Storage 사이의 불일치 및 불필요한 파일 누적을 줄였습니다.
04
검색·카테고리·추천 필터의 상태 동기화
- 문제
- 검색어와 카테고리, 추천 여부를 따로 처리하면 조건이 조합될 때 목록과 카테고리별 개수가 서로 다르게 표시되고, 관리 작업마다 전체 목록을 다시 요청하면 UI 반응성이 떨어질 수 있었습니다.
- 해결
- 원본 대회 목록을 하나의 상태로 관리하고 useMemo로 검색 결과와 카테고리별 개수를 계산했습니다. 관리 작업 후에는 API 응답을 사용해 변경된 항목만 불변 방식으로 갱신했습니다.
- 결과
- 여러 필터가 동시에 적용돼도 일관된 결과를 제공하고, 추가 요청 없이 관리 작업의 결과를 즉시 화면에 반영할 수 있게 되었습니다.