LIKELION HGU 14th · Space On Backend
서비스 바로가기 · Frontend Repository
Space On은 비어 있는 공간(공실)과 그 공간이 필요한 대학생을 이어 주는 서비스입니다.
- 사용자는 원하는 분위기와 용도를 자연어로 입력합니다. 예: "조용하고 깔끔한 스터디 공간" LLM(Gemini)이 이 문장을 미리 정의된 칩(chip) 으로 바꾸고, 칩이 일치하는 공실을 추천합니다.
- 공실 소유자(호스트) 는 공간 정보와 사진, 대여 가능한 날짜·시간대를 등록하고 예약 현황을 확인합니다.
- 여러 명이 함께 쓸 공간이라면, 각자의 위치를 입력해 중간 지점 근처의 공실을 찾을 수 있습니다.
|
AI 공실 추천 자연어 → 칩 정규화 → 칩 매칭 Gemini가 입력 문장을 26개의 칩 중 해당하는 것으로 바꿉니다. 동의어·오탈자는 보정하고, 부정 표현("빼고", "제외")은 걸러냅니다. 칩이 하나 이상 겹치는 공실만 추천합니다. |
위치 기반 탐색 중간 지점 · 반경 3km · 가격 범위 여러 출발지의 위·경도 평균으로 중간 지점을 구합니다. MySQL에서 Haversine 공식으로 반경 3km 안에 있고 예산 범위에 맞는 공실만 조회한 뒤, 거리순으로 정렬합니다. |
|
슬롯 단위 예약 월별 가능 날짜 · 일별 남은 슬롯 호스트가 연 시간 슬롯에서 이미 예약된 슬롯을 빼고 보여 줍니다. 여러 날짜와 슬롯을 한 번에 예약할 수 있습니다. |
호스트 등록 · 내역 조회 multipart 업로드 · 전화번호 조회 공실 정보, 옵션, 칩, 사진(S3), 날짜별 대여 시간을 한 번에 등록합니다. 회원가입 없이 전화번호로 예약·등록 내역을 조회합니다. |
flowchart LR
A["요청<br/>출발지 목록 · 프롬프트 · 가격 범위"] --> B["중간 지점 계산<br/>위·경도 평균"]
B --> C["MySQL 조회<br/>반경 3km · 가격 범위"]
A -. 프롬프트 .-> D["Gemini<br/>자연어 → 칩 JSON"]
C --> E["칩 매칭<br/>1개 이상 일치"]
D --> E
E --> F["거리순 정렬"]
F --> G["추천 공실 목록"]
- Gemini 응답 스키마는
{"chips":[{"chip":"모던한"}]}입니다. 일치하는 칩이 없으면{"chips":[]}를 돌려줍니다. - Gemini 호출이나 파싱에 실패하면 반경·가격 조건으로 찾은 공실을 그대로 돌려줍니다. AI가 실패해도 결과가 비지 않게 하기 위한 처리입니다.
칩 목록 — 26개 (canonical 표기)
| 분류 | 칩 |
|---|---|
| 분위기 | 활기찬 따뜻한 포근한 여유로운 레트로 영감을_주는 모던한 로맨틱 세련된 컬러풀한 깔끔한 심플 감성적인 조용한 럭셔리 유니크 창의적인 빈티지 |
| 용도 | 회의 스터디 촬영 상담 연습 시험 이벤트 |
| 공간 | 넓은 |
enum 표기는
영감을_주는처럼 언더스코어를 포함한 형태로 통일합니다.
flowchart LR
U["사용자 / 호스트"] --> FE["Frontend<br/>React · Vite (Vercel)"]
FE -->|HTTPS| NG["Nginx<br/>Reverse Proxy · Certbot"]
subgraph EC2["AWS EC2"]
NG --> BE["Spring Boot 3.5<br/>Java 17"]
end
BE --> DB[("MySQL 8")]
BE --> S3[("AWS S3<br/>공실 사진")]
BE --> AI["Google Gemini API<br/>gemini-1.5-flash"]
| Method | Endpoint | 설명 |
|---|---|---|
POST |
/main |
현재 위치 기준 반경 3km 안의 공실 카드 (가까운 순 최대 3개) |
POST |
/search/middle |
여러 출발지의 중간 지점 계산 |
POST |
/recommend |
출발지 · 자연어 프롬프트 · 가격 범위로 AI 추천 |
GET |
/recommend/detail/{roomId} |
공실 상세 정보 |
POST |
/reservation/{roomId} |
예약 페이지용 공실 정보 |
POST |
/reservation/available/days/{roomId} |
해당 월의 예약 가능 날짜 |
POST |
/reservation/available/timeslots/{roomId} |
해당 날짜의 남은 시간 슬롯 |
POST |
/reservation/done/{roomId} |
예약 확정 (여러 날짜 · 슬롯 일괄) |
POST |
/enrollment/done |
공실 등록 (multipart/form-data, 사진 → S3) |
POST |
/enrollment/confirmation |
호스트 전화번호로 등록 공실의 예약 현황 조회 |
POST |
/reservation/confirmation |
예약자 전화번호로 예약 내역 조회 (날짜별 병합) |
POST |
/gemini/query |
칩 추출 테스트용 |
erDiagram
ROOM ||--|| ADDRESS : "위치"
ROOM ||--o{ SCHEDULE : "대여 가능 시간"
ROOM ||--o{ RESERVATION : "예약"
ROOM {
Long id
String enName "호스트 이름"
String enPhoneNumber "호스트 연락처"
String account
int maxPeople
int price
String memo
List optionList
List chipList
List photoList "S3 URL"
}
ADDRESS {
Long id
String roadName
double latitude
double longitude
}
SCHEDULE {
Long id
LocalDate date
Set slotIndex "대여 가능 슬롯"
}
RESERVATION {
Long id
String name
String phoneNumber
LocalDate date
Set slotIndex "예약한 슬롯"
}
src/main/java/com/likelionhgu/nvidia
├── ai/ # Gemini 클라이언트, 프롬프트, 칩 JSON 매핑
├── config/ # CORS(WebConfig), S3 설정 · 업로드 서비스
├── controller/ # REST 컨트롤러, request/response 객체
├── converter/ # Set<Integer> ↔ DB 컬럼 변환
├── domain/ # Room · Address · Schedule · Reservation · Chip
├── dto/ # 서비스 계층 DTO
├── repository/ # Spring Data JPA (Haversine 반경 쿼리 포함)
└── service/ # 추천 · 예약 · 등록 비즈니스 로직
src/main/resources
└── import.sql # 개발용 더미 데이터
요구 사항: JDK 17, MySQL 8, AWS S3 버킷, Gemini API 키
-
src/main/resources/application.yaml을 만듭니다. 이 파일은.gitignore에 포함되어 있습니다. 키 값은 환경 변수로 주입하는 것을 권장합니다.spring: datasource: url: jdbc:mysql://localhost:3306/space_on?serverTimezone=Asia/Seoul username: ${DB_USERNAME} password: ${DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: create # import.sql 더미 데이터를 함께 적재 defer-datasource-initialization: true sql: init: mode: always cloud: aws: region: static: ap-northeast-2 credentials: accessKey: ${AWS_ACCESS_KEY} secretKey: ${AWS_SECRET_KEY} s3: bucket: ${S3_BUCKET} gemini: api: key: ${GEMINI_API_KEY}
-
서버를 실행합니다.
./gradlew bootRun
![]() JuanHubb Backend |
![]() sion1212 Backend |
![]() Gyuho-Han Frontend |
![]() dkrehd0519 Frontend |



