1- # backend
2- “숨 여행, 틈” 프로젝트의 백엔드 리포지토리입니다.
1+ # SoomTeum (숨틈)
2+ ** <<2026 관광데이터 활용 공모전 장려상 수상작>>**
3+ > ** 숨 여행, 틈** - 한적한 여행지를 발견하고, 나만의 여행을 계획하세요.
4+
5+ SoomTeum은 여행지 추천 및 관리 플랫폼의 Spring Boot 기반 REST API 백엔드입니다.
6+
7+ 관광 데이터 API(https://www.data.go.kr/index.do)를 활용하여 혼잡도 정보/실시간 주차 정보를 제공합니다.
38
49---
510
6- ## 🛠️ 개발 환경
11+ ## 기술 스택
712
8- - ** Language** : Java 17
9- - ** Framework** : Spring Boot 3.5.3
10- - ** Build Tool** : Gradle
11- - ** Database** : MySQL
12- - ** ORM** : Spring Data JPA
13- - ** Infra** : AWS EC2, RDS
14- - ** API 문서화** : Swagger (springdoc-openapi)
13+ | 분류 | 기술 |
14+ | ------| --------------------------------------------------------|
15+ | ** Framework** | Spring Boot 3.5.3, Spring WebFlux, Spring Security 6.x |
16+ | ** Language** | Java 17 |
17+ | ** Database** | MySQL 8.0, Spring Data JPA |
18+ | ** Authentication** | JWT (JJWT 0.11.5), Kakao OAuth 2.0 |
19+ | ** Cache** | Caffeine 3.1.8 |
20+ | ** Documentation** | Springdoc OpenAPI (Swagger UI) |
21+ | ** External API** | 공공데이터포털 (한국관광공사 API), Google Gemini AI |
22+ | ** Infrastructure** | Docker, AWS (EC2, RDS) |
23+ | ** Testing** | JUnit 5, k6 (부하 테스트) |
1524
1625---
1726
18- ## 📁 폴더 구조 (도메인형 DDD 기반)
27+ ## 주요 기능
28+
29+ ### 인증 및 사용자 관리
30+ - Kakao OAuth 2.0 소셜 로그인
31+ - JWT 기반 인증 (Access Token 14일, Refresh Token 7일)
32+ - 프로필 조회/수정, 회원 탈퇴
33+
34+ ### 여행지 탐색
35+ - ** 위치 기반 추천** : 좌표 및 반경으로 주변 여행지 검색
36+ - ** 지역/테마 기반 필터링** : 지역과 테마별 여행지 조회
37+ - ** 혼잡도 정보** : 실시간 혼잡도 수준 제공
38+ - ** AI 리뷰 요약** : Google Gemini를 활용한 리뷰 요약
1939
40+ ### 사용자 상호작용
41+ - 여행지 좋아요 (Like)
42+ - 여행지 저장 (Bookmark)
43+ - 저장한 여행지 검색 및 페이지네이션
44+
45+ ### 주차 정보
46+ - 지역별 공영주차장 조회
47+ - 좌표 기반 근처 주차장 검색 (Haversine 거리 계산)
48+ - 실시간 주차 가용 현황 업데이트
49+
50+ ---
51+
52+ ## 프로젝트 구조
53+
54+ ```
55+ src/main/java/com/comma/soomteum/
56+ ├── config/ # 전역 설정 (Security, Swagger, Cache 등)
57+ ├── domain/ # 도메인 모듈 (DDD 기반)
58+ │ ├── ai/ # AI 리뷰 요약 서비스
59+ │ ├── auth/ # Kakao OAuth, JWT 인증
60+ │ ├── external/tourapi/ # 공공 관광 API 연동
61+ │ ├── parking/ # 공영주차장 정보
62+ │ ├── place/ # 여행지 관리
63+ │ ├── region/ # 지역 정보
64+ │ ├── theme/ # 여행 테마 분류
65+ │ ├── token/ # 토큰 관리
66+ │ ├── user/ # 사용자 관리
67+ │ ├── userPlace/ # 좋아요/저장 기능
68+ │ └── recommendation/ # 여행지 추천 서비스
69+ └── global/ # 전역 유틸리티
70+ ├── exception/ # 예외 처리
71+ └── response/ # API 응답 래퍼
2072```
21- backend
22- domain/
23- ├── user/
24- │ ├── controller/
25- │ ├── service/
26- │ ├── repository/
27- │ ├── dto/
28- │ └── entity/
29- ├── place/
30- │ ├── controller/
31- │ ├── service/
32- │ ├── repository/
33- │ ├── dto/
34- │ └── entity/
35- ├── region/
36- ├── theme/
37- ├── userattraction/
38- │ ├── controller/
39- │ ├── service/
40- │ ├── repository/
41- │ ├── dto/
42- │ └── entity/
43- └── BaseEntity.java
44- ㄴ global
45- ㄴ exception
4673
74+ ---
75+
76+ ## API 문서
77+
78+ 애플리케이션 실행 후 Swagger UI에서 API 문서를 확인할 수 있습니다:
79+
80+ ```
81+ http://localhost:8080/swagger-ui.html
4782```
4883
84+ ### 주요 API 엔드포인트
85+
86+ | Method | Endpoint | 설명 |
87+ | --------| ----------| ------|
88+ | ` POST ` | ` /api/auth/login/kakao ` | Kakao 로그인 |
89+ | ` POST ` | ` /api/auth/reissue ` | 토큰 재발급 |
90+ | ` GET ` | ` /api/my/profile ` | 프로필 조회 |
91+ | ` GET ` | ` /api/places/integrated/{contentId} ` | 여행지 통합 상세 정보 |
92+ | ` GET ` | ` /api/places ` | 지역/테마 기반 여행지 목록 |
93+ | ` GET ` | ` /api/places/ai ` | 위치 기반 여행지 추천 |
94+ | ` POST ` | ` /api/places/like ` | 여행지 좋아요 |
95+ | ` PUT ` | ` /api/my/places/save ` | 여행지 저장 |
96+ | ` GET ` | ` /api/my/places ` | 저장한 여행지 목록 |
97+ | ` GET ` | ` /api/parking/nearby ` | 근처 주차장 조회 |
98+ | ` POST ` | ` /api/ai/summary ` | AI 리뷰 요약 |
99+
100+ ---
101+
102+ ## 성능 최적화
103+
104+ ### Caffeine 캐시 아키텍처
105+
106+ 5단계 캐시 전략을 적용하여 외부 API 호출을 최소화했습니다:
107+
108+ | 캐시 | TTL | 최대 항목 | 대상 |
109+ | ------| -----| -----------| ------|
110+ | tourApiCache | 1시간 | 500 | 외부 관광 API |
111+ | cnctrRateCache | 30분 | 1,000 | 혼잡도 데이터 |
112+ | themeCache | 24시간 | 100 | 테마 메타데이터 |
113+ | regionCache | 24시간 | 300 | 지역 메타데이터 |
114+ | placeLikeCache | 10분 | 500 | 좋아요 수 |
115+
116+ ** 성능 개선** : p95 응답 시간 2,400ms → 15.29ms (99.4% 개선)
49117
50118---
51119
52- ## 🔖 브랜치 전략 (GitHub Flow 기반)
120+ ## 브랜치 전략 (GitHub Flow 기반)
53121
54122- ` main ` : 제품 출시 브랜치 (배포 대상)
55123- ` dev ` : 통합 개발 브랜치 (optional)
@@ -58,23 +126,23 @@ backend
58126
59127---
60128
61- ## 💬 PR 규칙
129+ ## PR 규칙
62130
63131- 제목 형식: ` feat: 로그인 API 구현 `
64132- 템플릿 기반 작성 (유형 / 작업 내용 / 리뷰 포인트 등)
65133
66134| 태그 | 설명 |
67135| --- | --- |
68- | ✨ [ Feat] | 새로운 기능 추가 |
69- | 🐛 [ Fix] | 버그 수정 |
70- | 🎨 [ Design] | API 응답 포맷/UI 관련 수정 |
71- | 📝 [ Docs] | 문서 수정 (README 등) |
72- | 🔧 [ Chore] | 설정 변경, 의존성 관리 등 |
73- | 🚀 [ Hotfix] | 배포 중 긴급 수정 |
136+ | [ Feat] | 새로운 기능 추가 |
137+ | [ Fix] | 버그 수정 |
138+ | [ Design] | API 응답 포맷/UI 관련 수정 |
139+ | [ Docs] | 문서 수정 (README 등) |
140+ | [ Chore] | 설정 변경, 의존성 관리 등 |
141+ | [ Hotfix] | 배포 중 긴급 수정 |
74142
75143---
76144
77- ## ✅ 커밋 컨벤션
145+ ## 커밋 컨벤션
78146
79147``` bash
80148< 태그> : < 제목>
@@ -83,18 +151,16 @@ backend
83151- 작업 내용 상세2
84152
85153# 이슈번호 (optional)
86-
87154```
88155
89156### 예시
90157
91158- ` feat: 회원가입 API 구현 `
92159- ` fix: 회원가입 시 닉네임 중복 오류 수정 `
93160
94-
95161---
96162
97- ## 🧾 Database 규칙
163+ ## Database 규칙
98164
99165- ** 테이블 명** : ` lower_snake_case `
100166- ** PK 컬럼명** : ` id `
@@ -104,4 +170,75 @@ backend
104170
105171---
106172
173+ ## 라이선스
174+
175+ 이 프로젝트는 MIT 라이선스를 따릅니다.
176+
177+ ---
178+
179+ ## 시작하기
180+
181+ ### 사전 요구사항
182+
183+ - Java 17
184+ - MySQL 8.0+
185+ - Gradle 8.4+
186+
187+ ### 환경 변수 설정
188+
189+ ` application.properties ` 또는 환경 변수로 설정:
190+
191+ ``` properties
192+ # Database
193+ spring.datasource.url =jdbc:mysql://localhost:3306/soomteum?serverTimezone =Asia/Seoul
194+ spring.datasource.username =your_username
195+ spring.datasource.password =your_password
196+
197+ # JWT
198+ jwt.secret =your_base64_encoded_secret
199+
200+ # Kakao OAuth
201+ spring.security.oauth2.client.registration.kakao.client-id =your_kakao_client_id
202+ spring.security.oauth2.client.registration.kakao.redirect-uri =http://localhost:8080/api/auth/kakao/callback
203+
204+ # 공공데이터 API
205+ tourapi.clients.korService2.service-key =your_tour_api_key
206+ parking.api.key =your_parking_api_key
207+
208+ # Google Gemini AI
209+ gemini.api.key =your_gemini_api_key
210+ ```
107211
212+ ### 데이터베이스 생성
213+
214+ ``` sql
215+ CREATE DATABASE soomteum CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
216+ ```
217+
218+ ### 빌드 및 실행
219+
220+ ``` bash
221+ # 프로젝트 빌드
222+ ./gradlew clean build
223+
224+ # 애플리케이션 실행
225+ ./gradlew bootRun
226+
227+ # 또는 JAR 직접 실행
228+ java -jar build/libs/soomteum-0.0.1-SNAPSHOT.jar
229+ ```
230+
231+ ### Docker 실행
232+
233+ ``` bash
234+ # 이미지 빌드
235+ docker build -t soomteum:latest .
236+
237+ # 컨테이너 실행
238+ docker run -d \
239+ -p 8080:8080 \
240+ -e SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3306/soomteum \
241+ -e SPRING_DATASOURCE_USERNAME=root \
242+ -e SPRING_DATASOURCE_PASSWORD=root \
243+ soomteum:latest
244+ ```
0 commit comments