[STOOV] 버스킹 공연 장소 탐색 플랫폼

과정
노출 페이지
대표 이미지
대표이미지
서비스 한 줄 소개
회차
5 more properties

1. 배경(Problem)

서울시 내 버스킹 공연은 매년 꾸준히 운영되고 있지만, 공연자가 어디서 공연이 가능한지, 허가가 필요한지, 어디서 신청해야 하는지를 한눈에 파악하기 어렵다.

1.1 문제 원인

공연 허가·운영 기관이 여러 곳으로 분산됨(자치구·문화재단·공공기관 등)
때문에 공식 예약/허가 안내가 각 기관 홈페이지에 흩어져 있음
기존 서비스는 사용자 제보 기반이거나 업데이트가 늦어서 정보 정확도·최신성 유지가 어려움

1.2 사용자(버스커)의 pain point

지역·기관별로 상이한 예약 방식 → 장소별 허가 여부·신청 조건 확인의 어려움 → 공연 환경(분위기, 후기, 시설 정보 등) 사전 파악 어려움 → 장소를 예약하고 공연을 실행하는데 있어서 초보 버스커에게 높은 진입 장벽 유발
핵심 문제: ‘공연 장소 탐색→조건 이해→예약’의 흐름이 단절되어 실제 공연 실행까지 이어지기 어렵다.

2. 서비스 소개(Solution)

공식 허가 기반 버스킹 공연 장소를 지도에서 한눈에 확인하고, 각 장소의 예약/신청 링크까지 바로 연결하는 지도형 정보 플랫폼

2.1 핵심 제공 가치

서울 내 공식 버스킹 장소(공공기관·지자체)만 모아 표준화된 형태로 제공
장소별 운영 시간, 허가 조건, 예약 링크를 통합 제공
후기 및 북마크 기능을 통해 공연 실행 장벽 완화

2.2 핵심 유저

2.3 핵심 기능페인포인트 대응 전략

기능명
기능 상세 정의
목적
해결 페인포인트
지도 기반 공연 장소 탐색
서울시·자치구·산하기관 공식 장소 지도 시각화, 검색/필터를 제공한다.
분산된 정보 통합, 탐색 비용을 최소화한다.
반복 사이트 방문 필요 → 탐색 피로, 조건 비교 어려움, 공연 가능성 불확실하다
장소 상세 정보 구조화
운영 시간, 허가 조건, 제한 사항, 담당자·문의처, 예약 링크 등 통합
공연 가능 여부 확신 제공
공지 상이 → 이해 어려움, 규정 누락으로 오해를 일으켜 신뢰도가 하락한다.
공식 예약 연동
장소 상세 화면에서 공식 예약 페이지 링크를 제공한다.
탐색→예약 단절 없는 흐름
불확실성 제거, 재검색 과정을 최소화한다.
공연자 후기 작성 및 조회
현장 정보 작성·조회, 신고 기능을 제공한다.
의사결정 정확도가 향상한다.
현장 정보 부족, 신규 공연자 불안감
관심 장소(북마크)
로그인 사용자 대상 장소 저장/관리한다.
공연 준비 효율화
반복 탐색·후보지 비교가 어렵다.
사용자 인증 및 최소 계정
소셜 로그인 기반, 후기 신뢰도 관리, 개인화 기능을 제공한다.
정보 신뢰성 유지, 개인화 경험을 제공한다.
익명 후기 신뢰도 저하, 스팸·중복 문제

2.4 핵심 기능

핵심 기능(솔루션) 요약

 장소 목록 조회

 장소 검색

 장소 상세 보기

2.5 시연 영상

3. 아키텍처 및 핵심 기능

3.1 시스템 아키텍처

Onset 프로젝트는 거리 공연 장소에 대한 정보를 제공하고, 사용자가 장소를 검색, 리뷰, 북마크할 수 있는 위치 기반 서비스입니다.

1. Auth Service

Google OAuth2 기반 인증 및 사용자 정보를 관리합니다.
sequenceDiagram
    participant Client
    participant UserController
    participant GoogleOAuthService
    participant Google OAuth
    participant UserRepository
    participant HttpSession

    Client->>+UserController: POST /api/users/google (credential)
    UserController->>+GoogleOAuthService: login(credential)
    GoogleOAuthService->>+Google OAuth: ID 토큰 검증 요청
    Google OAuth-->>-GoogleOAuthService: 토큰 정보 (sub, email 등)
    GoogleOAuthService->>UserRepository: findBySub(sub)
    alt 기존 사용자인 경우
        UserRepository-->>GoogleOAuthService: User 정보 반환
    else 신규 사용자인 경우
        GoogleOAuthService->>UserRepository: save(newUser)
        UserRepository-->>GoogleOAuthService: 생성된 User 정보 반환
    end
    GoogleOAuthService-->>-UserController: LoginResponse (userId 포함)
    UserController->>+HttpSession: setAttribute("USER_ID", userId)
    HttpSession-->>-UserController: 세션 저장 완료
    UserController-->>-Client: 200 OK (LoginResponse)
Mermaid
복사
사용자 인증 흐름 (User Authentication Flow) - Google 소셜 로그인을 통한 세션 기반 인증을 사용
주요 기능
Google OAuth 로그인
신규 사용자 자동 가입
세션 기반 인증
사용자 정보 조회
기술 요소
Spring Security
Google OAuth2
HttpSession
PostgreSQL, Redis(세션 캐싱)

2. Place Service

공식 공연 장소 탐색의 핵심 기능을 제공하는 도메인입니다.
sequenceDiagram
    participant Client
    participant PlaceController
    participant PlaceService
    participant PlaceRepository
    participant ReviewRepository
    participant BookmarkRepository

    Client->>+PlaceController: GET /api/places/search?keyword=공원
    PlaceController->>+PlaceService: searchPlaces("공원", userId, pageable)
    Note over PlaceService: 1. 장소 기본 정보 조회 (1번의 쿼리)
    PlaceService->>+PlaceRepository: searchByNameOrDistrict("%공원%", pageable)
    PlaceRepository-->>-PlaceService: Page<Place> (장소 목록)
    Note over PlaceService: 2. 리뷰 개수 일괄 조회 (1번의 쿼리)
    PlaceService->>+ReviewRepository: countByPlaces(placeList)
    ReviewRepository-->>-PlaceService: List<Object[]> (장소별 리뷰 개수)
    Note over PlaceService: 3. 북마크 정보 일괄 조회 (1번의 쿼리)
    PlaceService->>+BookmarkRepository: findByUserAndPlaceIn(user, placeList)
    BookmarkRepository-->>-PlaceService: List<Bookmark> (사용자의 북마크 목록)
    Note over PlaceService: 4. 조회된 데이터를 메모리에서 조합하여 최종 응답 생성
    PlaceService-->>-PlaceController: Page<PlaceSearchResponse>
    PlaceController-->>-Client: 200 OK (JSON Response)
Mermaid
복사
장소 검색 및 목록 조회 기술 흐름 - 장소 목록/검색 시 발생하는 N+1 문제를 해결하기 위해 'Batch Fetch' (IN절 사용) 방식을 사용함
주요 기능
공연 장소 목록 조회
키워드 기반 검색
장소 상세 정보(허가 조건, 운영 시간, 예약 링크 등)
리뷰/북마크 정보와 병합된 응답 제공
기술 요소
Spring Boot
Spring Data JPA
PostgreSQL
Batch Fetch 기반 성능 최적화 (N+1 문제 해결)

3. Review Service

공연자 간 정보 공유를 위한 후기 기능을 관리합니다.
주요 기능
후기 생성 / 수정 / 삭제
장소별 후기 조회
후기 신고 처리
기술 요소
Spring Boot
Spring Data JPA
PostgreSQL

4. Bookmark Service

사용자가 관심 장소를 저장하고 관리할 수 있도록 돕는 서비스입니다.
주요 기능
북마크 생성 / 삭제
사용자 별 북마크 목록 조회
장소 목록 조회 시 북마크 여부 함께 반환
기술 요소
Spring Boot
Spring Data JPA
PostgreSQL

3.2 ERD

현 ERD는 소셜 로그인 기반 사용자(Users) 를 중심으로 공연 장소(Place), 후기(Review), 찜(Bookmark) 이 세 가지 핵심 엔티티가 서로 1:N / N:1 관계로 연결되는 구조이다.

3.3 중요 구현 포인트

Backend
키워드 기반 장소 검색 조건 구현
사용자가 입력한 keyword를 기준으로 이름(name)·지역구(district) 컬럼에서 LIKE 검색을 수행하는 검색 기능을 구현
PlaceRepository에 전용 JPQL 쿼리를 정의해 Pageable 페이지네이션과 함께 검색결과를 효율적으로 반환하도록 구성
실제 검색은 다음 흐름으로 처리됨:
유저 입력 → Controller → Service → Repository → PageResponse로 변환 → FE 전달
Google ID Token 기반 로그인/회원가입 구현
프론트에서 받은 Google ID Token(credential)을 서버로 전달해 로그인/회원가입을 처리하는 소셜 로그인 기능을 구현
GoogleCredentialVerifier에서 JWT 서명, Issuer(iss), Audience(aud), 만료시간(exp)를 검증해 토큰 위변조, 만료 여부를 확인
검증된 토큰에서 sub(고유 식별자), email, picture를 추출해 사용자 식별 및 프로필 정보로 활용
기존 유저면 단순 로그인 처리, 신규 유저면 회원가입 후 로그인 처리
Frontend
리뷰 작성·수정·삭제 흐름 + React Query 상태 관리
useMutationinvalidateQueries를 활용해 후기 CRUD 이후 필요한 데이터만 선택적으로 갱신
createdAt / updatedAt 혼합 정렬 규칙을 적용해 리스트 일관성을 유지하고, 백엔드 응답 구조와 동기화되도록 정렬 로직을 설계
장소 상세 페이지 구조 + 바텀시트/페이지 연동 설계
동일한 상세 정보 데이터를 바텀시트 버전과 풀페이지 버전 양쪽에서 재사용할 수 있도록 공통 컴포넌트 기반으로 UI 구조를 계층화
스크롤 위치, topButton, Header/Bottombar 노출 여부 등 레이아웃 요소와 충돌하지 않도록 설계
구글 로그인
구글에서 공식적으로 제공하는 react-oauth/google를 이용하여 사용자들이 편하게 이용할 수 있도록 원탭 로그인 구현
윈도우 너비 감지를 통하여 반응형으로 동적 너비 길이 업데이트
useMutation를 활용하여 버튼 클릭 전에 로그인이 되지 않도록 방지함과 동시에, 신규 유저 여부를 구분하여 약관 페이지와 메인 페이지로 이동

4. 활용 라이브러리 및 개발 환경

4.1 주요 사용 기술 스택 요약

Backend
Spring Boot, RESTful API
DB: PostgreSQL(운영), H2(테스트), Spring Data JPA
Infra: Docker, Docker compose, AWS EC2, Route 53, ALB, IAM, S3, RDS, GitHub Actions
Logging/Monitoring: Spring Boot Actuator, Prometheus, Grafana
Test: JUnit 5
기타 도구: IntelliJ IDEA, Checkstyle, Postman, Git / GitHub, Swagger / OpenAPI
선택 이유 요약:
검증된 구조로 빠른 개발 가능
확장성·안정성 확보
대규모 장소 조회 시 Batch Fetch 전략으로 성능 최적화
Frontend
React(Vite), JS(ES6+), React Router DOM, Zustand, React Query, TailwindCSS, Axios, react-hook-form, react-hot-toast, react-oauth/google
API: Kakao Maps API
선택 이유 요약:
지도 기반·리스트 기반 UI에 최적화
빠른 MVP 구축을 위한 단순하고 안정적인 상태 관리 구조
서버 상태 캐싱으로 API 요청 최소화
디자인 및 프로토타입 도구
Figma, Adobe Photoshop, Adobe illustrator
커뮤니케이션 및 협업 도구
Notion, Discord, Google Drive, GitHub, Zapier

4.2 주요 기술 스택 선정 이유

Frontend
사용 기술: React, JS(ES6+), React Router DOM, Zustand, Tanstack Query, Axios, Vercel
선정 이유:
구분
기술
선정 이유
프레임워크
React (Vite 기반)
컴포넌트 기반 SPA 구조에 최적화되어 있으며, Vite 기반으로 빠른 개발/빌드 환경을 제공해 MVP 구축 속도를 높임
언어
JavaScript (ES6+)
번들링 없이 모든 브라우저에서 동작하며, React, API 통신, 상태관리 전반에 자연스럽게 적용 가능
상태 관리
Zustand
코드량이 적고 직관적이며, 전역 UI 상태 관리에 가벼운 선택지
서버 상태 관리
React Query
API 캐싱, 동기화, 리페치 흐름을 자동화하여, 서버 데이터 중심 기능에 안정적인 구조 제공
라우팅
React Router DOM (v7)
상세 페이지, 탭 이동, Protected Route 구조 등 복잡한 네비게이션 요구를 충족
UI 프레임워크
Tailwind CSS + clsx + CVA
디자인 토큰 적용, Variant 체계, 화이트라벨 컴포넌트 개발에 효율적이며 재사용성을 높임
API 통신
Axios
인스턴스에서 공통 헤더, 에러 처리, 토큰 처리 통합 가능해 API 구조를 일관성 있게 유지할 수 있음
지도 라이브러리
Kakao Maps JavaScript SDK
국내 위치 기반 서비스에 최적화되어 있고, 마커·검색·필터 적용이 용이함
배포
Vercel / S3 + Cloud Front
GitHub 연동 자동 배포 지원 및 Preview URL 제공으로 협업, 테스트 속도 향상 백엔드와 동일한 도메인을 사용함으로써 통신에 필요한 쿠키를 쉽게 전송
Backend
사용 기술: Spring Boot 3.5.x, PostgreSQL, Spring Data JPA /Hibernate, Spring Security, Docker/Docker Compose, AWS
선정 이유
구분
기술
선정 이유
프레임워크
Java 21, Spring Boot (3.5.x)
스타터 기반으로 MVP 구현 속도가 매우 빠르고 운영까지 고려한 전체적인 생태계가 갖춰져 있어 추후 확장·관리 용이
데이터베이스
PostgreSQL
오픈소스 RDB 중에서 운영 사례가 많고, Docker에서 띄우기 편하고, 클라우드 매니지드 서비스도 풍부해서 장기 운영에 유리
데이터 접근
Spring Data JPA + Hibernate
반복적인 CRUD 코드를 크게 줄여주고, 메서드 이름 기반 쿼리 생성을 지원하여 개발 생산성을 극대화 쿼리들이 대부분 정형 데이터 기반이라, ORM이 다루기 좋고 유지보수성과 코드 가독성 증가
인증 · 보안
Spring Security (OAuth2, Session)
인증/인가 로직을 안정적으로 구현 OAuth2 Client를 통해 소셜 로그인을 손쉽게 연동하고, 세션 기반 인증으로 상태를 관리하여 사용자의 로그인 흐름을 단순하고 안전하게 처리
인프라
Docker / Docker Compose
애플리케이션과 그 의존성(DB, Redis 등)을 컨테이너화하여 개발, 테스트, 운영 환경의 일관성을 보장 가능
파일 저장소
AWS S3
이미지/정적 파일 저장에 최적화된 안정성, 확장성 제공
CI/CD
GitHub Actions + OIDC
인증키 없이 IAM Role을 이용해 자동배포
배포
AWS CodeDeploy
EC2 기반 배포를 안정적으로 자동화
로드 밸런싱
AWS ALB
HTTPS 종료, 헬스체크, 라우팅 제어를 담당하여 API 서비스의 안정성을 확보
운영/접속
AWS SSM
SSH 포트 개방 없이 접속 가능하여 보안 강화 및 운영 편의성 증

4.3 성능 개선·구조 설계·보안 고려사항

Backend
통일된 예외 처리 및 오류 응답 구조
GlobalExceptionHandler + CustomApiResponse로 모든 에러를 일관된 JSON 형식으로 반환
입력 검증 기반의 기본 보안 처리
→ DTO에서 @NotBlank, @Size 등 Jakarta Validation 사용
→ 요청 파라미터 유효성 자동 검증
Google ID Token 검증을 통한 소셜 로그인 보안 강화
→ 서명(Signature), Issuer, Audience, Exp 만료시간 모두 검증 수행
세션 기반 인증 및 보안 설정 적용
→ HttpOnly 세션 쿠키 사용
→ CORS 정책 명확히 설정(도메인 제한 + Credentials 허용)
공통 설정 분리로 구조 안정성 확보
ObjectMapperConfig, JpaAuditingConfig, SecurityConfig, AwsS3Config
→ 도메인 로직과 공통 기능의 분리
멀티 스테이지 Docker 빌드로 배포 안정성 확보
→ 빌드 이미지와 실행 이미지를 분리해 경량 컨테이너 구성
정기 배치 작업 기반 데이터 정리 구조
UserAgreementCleanupService의 스케줄러로 삭제 이력 관리 자동화
DB 무결성 관점 설계
→ users - bookmark - review 사이 FK + ON DELETE CASCADE/SET NULL 로 삭제 전파 및 데이터 정합성 보장
AWS 기반 인프라 보안 요소
→ 프라이빗 서브넷 기반의 백엔드 서버 운영(EC2/RDS 외부 노출 차단)
→ ALB → EC2, EC2 → RDS의 최소 권한 트래픽만 허용
→ ACM 기반 HTTPS 적용 및 ALB TLS 종료
Frontend
React Query 기반 데이터 캐싱 및 요청 최소화
동일 페이지 재진입 시 서버 재호출 없이 캐시 데이터 우선 사용 → 체감 속도 개선
staleTime, invalidateQueries 기준을 화면 흐름에 맞게 조정하여 불필요한 리페치를 줄임
API 실패 대응 및 사용자 피드백 구조
Axios 인스턴스에서 오류를 공통 처리
토스트 알림과 함께 사용자가 요청 실패 원인을 인지하고 재시도 할 수 있도록 UX 설계
입력 검증
후기 작성 시 최소/최대 글자 수 제한, 빈 문자열 방지 등 클라이언트 단 입력 검증 적용
프로필 이미지 업로드 시 파일 타입/사이즈 검증을 통해 비정상 파일 업로드 방지
UI 구조 설계에 따른 불필요 렌더링 최소화
공통 컴포넌트를 분리하고 하위 도메인 컴포넌트를 계층화
상위 상태 변경 시 불필요한 전체 리렌더를 줄이는 구조로 설계
코드 스플리팅
Home / PlaceDetail / Favorite / Mypage 등 페이지 단위로 라우트를 분리하여, 초기 진입 시 필요한 화면만 우선 로드
상세 지도/리뷰 탭 등은 상세 페이지 진입 시점에만 렌더링되도록 구성해 초기 번들 부담을 줄임

5. 트러블 슈팅

5.1 FE 트러블슈팅

1.
지도 렌더링 성능 문제
문제: 마커가 많아질수록 지도 렌더링 지연
해결: 마커 최소 렌더링, 조건부 렌더링, 메모이제이션 적용
2.
반응형 및 접근성
모바일 우선 레이아웃 재정비
스크린 리더 지원을 위한 aria-label 정비
3.
무한 요청 버그
Tanstack Query 옵션 미설정으로 재요청 반복
staleTime 조정으로 해결

5.2 BE 트러블슈팅

1.
N+1 문제
문제: 목록 조회 시 리뷰 개수·북마크 정보를 병렬로 불러오며 쿼리 폭증
해결: Batch Fetch(IN 절 기반), EntityGraph 적용 → 쿼리 수 70% 감소
2.
이미지 업로드 실패
S3 퍼블릭 정책 오류 → IAM 권한 재설정
3.
세션 만료 이슈
Google OAuth 로그인 후 세션 유지 문제 → Session TTL 정책 재정비

6. 팀 소개

STOOV는 공연자가 자신의 음악과 에너지를 거리로 옮기는 순간을 함께하며 누구나 공연을 시작할 수 있는 경험을 제공합니다.