전체 프로젝트
Team Project · Lead

Roomfit

12가지 라이프스타일 항목을 온보딩으로 수집해 15가지 유형으로 분류하고, Gemini API로 우선순위를 반영해 룸메이트를 추천하는 매칭 서비스입니다.

기간
2026.03 – 2026.07
팀 구성
7명 (BE 3 · FE 4)
역할
팀장 · 백엔드 개발 · 디자인
완성 여부
완성 ✓
JavaSpring BootMySQLAWS EC2 JPAJWTGemini APIDocker GitHub ActionsReact 19ViteTailwind CSS
01

기획 의도

외대 기숙사·자취 룸메이트를 구할 때 에브리타임 게시글이 사실상 유일한 방법이지만, 생활 패턴을 제대로 확인하기 어려워 입주 후 갈등이 자주 발생한다는 문제에서 시작했습니다.

수면 시간, 청소 빈도, 흡연 여부 등 12가지 라이프스타일 항목을 3단계 온보딩으로 수집해 취침 시간(3) × 성향(5) = 15가지 유형으로 자동 분류하고, Gemini AI가 우선순위 가중치를 반영해 추천하는 매칭 서비스를 만들었습니다.

핵심 가치 — 데이터 기반 라이프스타일 매칭 + AI 추천으로 갈등 사전 예방
02

시연 영상

03

시스템 구조

DomainUser, Lifestyle, Like, Match, Notification, Type, UserPriorityTrait, UserSleepHabit, UserSleepSensitivity
Enum15개 (CleaningFrequency, Gender, MatchStatus, Personality, SleepTime, TraitKey 등)
ControllerAuth, Like, Main, Matching, Mypage, Notification, Onboarding, Search, UserProfile
DTO30개 이상
ConfigDataInitializer, GeminiProperties, SecurityConfig
04

담당 역할 · 주요 구현

1

인증 · 인프라

JWT 기반 이메일 로그인을 구현하며 @hufs.ac.kr 도메인 검증, BCrypt 암호화, 이메일·닉네임 중복 확인 로직을 만들었습니다. Docker + GitHub Actions로 자동 배포 파이프라인을 구축했고, SecurityConfig와 SwaggerConfig로 HTTPS 서버 설정을 관리했습니다.

2

3단계 온보딩 API

Step1(선호 층수·성격·온도), Step2(샤워시간·청소빈도·수면시간·수면민감도·수면습관), Step3(방 내 식사·흡연·통화·귀가 빈도)까지 총 12가지 항목을 수집해 Lifestyle 엔티티에 저장하는 API를 만들었습니다.

3

15가지 룸메이트 유형 분류 알고리즘

취침 시간(EARLY / LATE / MIDNIGHT) × 성향(NEAT / SOCIAL / QUIET / FREE / HERMIT) 조합으로 15가지 유형 분류 로직을 직접 설계하고 구현했습니다. DataInitializer에서 서버 기동 시 15개 타입을 자동 초기화하고 S3 URL로 이미지를 매핑하도록 했습니다.

4

Gemini AI 룸메이트 추천

라이프스타일과 우선순위 항목(TraitKey)을 프롬프트로 구성하고, 우선순위 항목에는 3배 가중치를 적용했습니다. Gemini 응답을 매칭 점수 JSON으로 파싱해 RankedCandidate로 캐싱하고 AI 추천 리스트로 응답하도록 했으며, 매칭 요청에 카카오 오픈채팅 URL을 포함하는 기능도 추가했습니다.

5

매칭 플로우 · 검색 · 마이페이지

좋아요 → 매칭 요청 → 수락 / 거절 / 완료까지 전 단계를 구현했고, 매칭 완료 시 양측 UserStatus 변경과 Notification 자동 생성을 처리했습니다. 성별·라이프스타일 전체 필터 기반 유저 검색을 전면 재설계했고, 마이페이지에서 프로필·라이프스타일 수정 시 유형이 자동 재계산되도록 만들었습니다.

6

서비스 디자인

백엔드 개발과 함께 서비스 화면 디자인을 맡아, 온보딩부터 추천·매칭까지 이어지는 사용자 흐름을 화면으로 설계했습니다.

05

트러블슈팅

AI 추천 후 이미지·유형 null 표시

문제

추천 목록에서 프로필 이미지와 유형(type)이 null로 표시됐습니다.

원인

RankedCandidate에 User 엔티티를 통째로 캐시해, 트랜잭션 종료 후 detached 상태에서 user.getType()에 접근하는 게 실패했습니다.

해결

트랜잭션 안에서 imageUrl과 typeCode를 원시값으로 미리 계산해 캐시에 저장해, detached 상태에서도 정상 반환되도록 했습니다.

좋아요 추가 시 400 에러 (필드명 불일치)

문제

좋아요 API 호출 시 400 에러가 발생하고 receiverId가 null로 들어왔습니다.

원인

응답 DTO는 snake_case(user_id)로 내려주는데 요청 DTO는 camelCase(receiverId)를 기대해, 프론트에서 user_id로 보내면 바인딩에 실패했습니다.

해결

@JsonAlias({"user_id", "userId", "targetUserId"})로 다중 필드명을 매핑했습니다.

검색 · 좋아요 · 추천 이미지 미표시

문제

검색, 좋아요, AI 추천 화면에서 이미지가 표시되지 않았습니다.

원인

open-in-view=false 환경에서 LAZY 연관관계(Like → likedUser → type) 체인이 null로 끊겼습니다.

해결

LikeRepository에 LEFT JOIN FETCH u.type 쿼리를 추가해 로딩 체인 전체를 즉시 로딩으로 전환했습니다.

마이페이지 수정값 미반영

문제

PUT /mypage/profile/modify 호출 후 GET /users/{id}에서 수정값이 반영되지 않았습니다.

원인

DTO에 @Setter가 누락돼 Jackson 역직렬화가 실패해 모든 필드가 null 처리됐고, JPA dirty checking에 의존해 repository.save() 호출도 빠져 있었습니다.

해결

@Setter를 추가하고 repository.save()를 명시적으로 호출하도록 수정했습니다.

좋아요 · 매칭 로직 혼재

문제

좋아요 목록 API가 likes 테이블이 아닌 matches 테이블을 조회하고 있었습니다.

해결

Like 테이블을 분리하고 LikeRepository에 findAllByUserId를 추가해, MainController에서 getLikeList를 호출하도록 교체했습니다.

06

진행 타임라인

3 – 4월
프로젝트 기획 단계 — 기능명세서, 와이어프레임, API 명세서, ERD 설계
5/5 – 5/12
프로젝트 초기 세팅(BE/FE), 회원가입·로그인·이메일/닉네임 중복확인 API, 로그인·회원가입 UI
5/13 – 5/18
온보딩 1~3단계 API, Gemini AI 추천 시스템 연동, 좋아요/매칭요청/수락/거절/취소 API, 매칭페이지 UI 및 연동
5/19 – 5/31
마이페이지, 나의 타입 검사, 검색 필터 전면 개편, 카카오 오픈채팅 연동, 메인·마이페이지 UI 및 API 연동
6/1
좋아요·추천 응답 구조 버그 다수 수정, 자동 로그인 처리, 각종 디테일 수정
6/2 – 7/4
공백기 (방학 초반 휴식 또는 다른 일정과 겹친 기간)
7/5 – 7/17
유학생/동갑 선호, 인원수 옵션(2인실·4인실 룸타입), 이메일 인증 기능, 배포 파이프라인 구축(BE/FE), 알림 기능, 모바일 전면 개편
7/20 – 7/26
4인 매칭 로직, 알림 클릭 시 페이지 이동, Google Analytics 연동, 매칭페이지 최종 버그 수정 → 배포 마무리
07

성과 · 운영 지표

2026-08-15 기준, EC2 서버에서 실측한 값입니다.

172 / 211
백엔드 커밋 (약 82%)
92명
총 가입자 수
62건
매칭 요청 전체 (성사 7 · 대기 32 · 취소 22 · 거절 1)
12명
매칭 성사에 관여한 고유 유저 수
7.5G / 29G
서버 디스크 사용량 (약 27%)
2등
멋쟁이사자처럼 동아리 내 미니프로젝트
← 이전 프로젝트SciFit-Sync