서론
방학이 시작되고 Leets 4기에서 프로젝트를 시작하게 되었고, 내가 참여하여 시작한 프로젝트의 주제는
" 교내 학생들의 택시 이용시, 요금과 시간의 부담을 줄여줄 수 있는 택시 매칭 서비스 " 였다.
해당 자세한 내용은 아래의 게시글을 참고해주면 더욱 좋을거같다
가치택시(무중단 배포)
서론2025년이 되었다. Leets 에서 가치택시라는 새로운 프로젝트를 진행중이다프로젝트의 구상은 가천대학교 학생들 대상으로 AI 공학관 또는 기숙사까지 택시를 공유해서 탑승할 수 있는 서비스
huncozyboy.tistory.com
설문조사
프로젝트 페르소나, 서비스의 대상을 가천대학교 교내 학생을 시작으로 특정했기때문에
가천대학교의 학생들의 의견이 중요하겠다고 판단이 되어, Google Forms를 제작하여 학생들을 대상으로 설문을 받아보았다

그 결과 41명의 학생들의 표본이 형성 되었고, 해당 설문조사 내용을 바탕으로 기획회의를 진행하여 필수 기능에 대한 MVP를 설정하였다
역할분담
MVP 설정 후에 BE 회의가 진행되었고, 해당 회의에서 전체적인 유저 플로우와 ERD 를 최종적으로 완성하게 되었다
유저플로우가 완성된 뒤에 드디어 역할 분담 회의를 하게 되었는데, 파트 분배는 도메인 별로 나누자는 주영이의 의견이 있었고, 그에 따라서 아래 내용처럼 파트가 크게 나눠지게 되었다.

파트 분배를 할때에 팀원들의 의견중에서, 안해본 파트를 구현 해보고싶다는 우석이형과 강혁이의 의견이 있었다
난 유저 파트를 전에 당근마켓 클론코딩을 진행했을때, JWT 기반 인증(ACCESS, REFRESH TOKEN) + 로그인, 회원가입 + 유저 프로필 이미지 관리(S3 프로필 이미지 생성, 수정, 삭제 기능) 등의 기능을 구현을 해봤었다.
또한 채팅 파트는 P-프로젝트(중고거래 서비스)를 구현했을때, 가볍게나마 몽고 DB+ Redis를 이용하여 구현을 해봤던 경험이 있었기에 해당 파트들의 우선권을 팀원들에게 양보하게 되었고, 자연스럽게 남은 기능은 매칭 기능이 되었다.
결론적으로 아래의 내용처럼 역할 분담이 확정 되었다.
유저 | 우석이형 |
채팅 | 강혁 |
매칭 | 지훈, 주영 |
본론
개발 전 고려사항
개발서버의 라즈베리파이 초기 세팅(깃헙 액션, mysql 컨테이너 관련 설정)과 CICD 개발을 끝낸 뒤였고,
내가 맡은 부분은 매칭 알고리즘 부분이 다였기때문에 작업의 볼륨 부분에서의 부담은 없었지만, 나와 주영이가 채팅 도메인이라는 동일한 API를 2명이서 나눠서 작업을 해야했기에 맨 처음에 우려했던 부분은 컨플릭트였다.
컨플릭트란 ?
GitHub와 같은 버전 관리 시스템에서 동일 파일의 동일 부분을 두 명 이상이 서로 다르게 수정했을 때 발생하는 충돌 현상을 말한다
컨플릭트가 발생하면 이를 수동으로 해결해줘야 하기때문에 시간과 노력이 더 소모 된다. 병합과정이 복잡해질수록 이 과정은 더 어려워질 수 있고, 작업 흐름이 끊겨서 작업 속도랑 효율성을 저하시킬 수 있다고 생각했다.
또한 장기적으로 봐도 깃허브에 불필요한 수정 이력이 발생하게 되어, 병합 이력이 복잡해지기때문에 유지 보수에 악영향을 미칠 수 있다고 판단하였다.
1. 명확한 역할 분담
첫번째 해결책으로 아래의 내용으로 주영이와 둘이 매칭 구현 관련 회의를 진행해서 명확하게 역할을 분담해주었다
주영:
• Kafka 세팅 및 연동, 이벤트 발행 구조 설계
• 매칭 알고리즘 인터페이스에 의존하여 작업 진행
• 매칭 성공 및 실패 시 처리 로직을 임시 구현체로 개발
지훈 :
• 매칭 알고리즘 구현
• 필터링 로직(태그별, 시간, 블랙리스트) 개발
• 매칭 성공 여부, 매칭 방 정보, 방장 여부 반환 로직 작성
2. GitHub Flow 전략 선택
두번째 방법으로는 브랜치 전략인데,
dev 브랜치를 따로 생성한 뒤에 각자의 이슈별로 브랜치를 분리하여 작업하는 방식을 사용한 GitHub Flow 브랜치 전략으로 진행하여
모든 개발자가 자신의 기능별 브랜치에서 독립적으로 작업할 수 있도록 하였고, 작업을 동시에 병렬적으로 진행할 수 있도록 해주었다
따라서 해당 방식을 통해 우리는 PR을 통해 병합하기 전에 코드 리뷰를 통한 피드백을 진행하여 병합 시 발생할 수 있는 충돌을 사전에 방지하고 관리할 수 있었다.
3. 작업 순서 및 데드라인 설정
또한 아래의 사진처럼 병합시에 생길 수 있는 충돌을 방지하기 위해서,
작업을 단계별로 세분화해서 나누고, 각 단계에서 담당자와 마감 기한을 구체적으로 정하여 효율적인 협업을 진행할 수 있도록 하였다.

Kafka 사용
Kafka 란 ?
데이터를 이벤트(Event) 형태로 관리하여 이벤트 브로커를 통해 여러 서비스의 백엔드 모듈 간에 이벤트를 전달하기 위한 플랫폼입니다.
PUB이 특정 데이터를 토픽(Topic)에 전송하면, 이를 구독(subscribe)하여 데이터를 소비하는 방식으로 동작합니다.
먼저 주영이가 카프카의 장점들을 알려줘서 해당 플랫폼을 처음알게 되었고, 카프카와 관련한 내용들을 공부하기 시작하였다.
물론 카프카에 대한 초기세팅 + 전체적인 이벤트 관련 로직은 주영이가 작성해주었지만, 나도 같은 매칭 부분을 맡고 있었기에 자세하게 공부가 필요했다 (Kafka 구현을 너무 잘해준 주영이에게 무한한 감사...🙏)
아래의 예시를 참고하면 이해가 더 빠를 것이다.
예: “방장 취소 이벤트” → “매칭 취소 로직 실행” → “취소 알림 이벤트” → “알림 서비스” 통해 SSE로 사용자에게 실시간 전송
결론적으로 해당 플랫폼을 사용해서 우리는 매칭 로직을 구현하기로 결정하였다.
매칭 알고리즘
먼저 매칭 알고리즘을 구현하기 전, 아래 사진들을 보면 알 수 있듯이 관련하여 수많은 고민들을 진행하였다.

이전에 Weeth 프로젝트(맨 처음 맡은 프로젝트)를 진행했을시에 내가 맡은 출석 파트를 완벽하게 구현해내지 못했던 적이 있었는데,
해당 경험에서 무작정 코드를 짜보기보다는 관련된 플로우에 대해서 고민을 진행하고, 어떤 로직을 사용할건지, 어떤 시스템으로 구현을 할건지 등등 에 대한 기능 설계가 훨씬 중요하다는 사실을 알게되어, 해당 부분을 고민하고 또 고민하였다
알고리즘 설계와 관련하여 중점적으로 고민했던 부분들을 일부 적어보겠다
1. 매칭시 계좌번호와 관련한 결제 관련 내용을 처리해줄 방장은 어떻게 지정해줄건지 ?
-> 현재 WAITING 상태이며, keywords가 동일하고, start_location/end_location이 같은 방 중에서 자리가 있는 방(current_members < max_capacity)을 찾아준다,
방이 존재하지 않을시에 : 새 방을 생성하고 해당 사용자를 방장(host)으로 설정.
방이 존재할 시에 : 해당 방에 참가(방장 외 +@), 만약에 방장이 없으면(취소/탈주 등으로 방장이 null)이 된 상태라면, 처음 들어온 사용자를 방장으로 지정하거나, 랜덤/시간순 지정 로직 적용.
2. 매칭시 블랙리스트(이전에 만났던 특정 사용자 벤 기능) 관련 내용은 어떻게 처리해줄 것인지 ?
-> 매칭 참가 시, 블랙리스트 관계가 있는 사용자와는 같은 방에 들어갈 수 없도록 해주는 로직이므로, 방에 멤버가 추가될 때마다 그 멤버와 현재 방에 있는 모든 멤버가 블랙리스트 관계인지 검사, 만약 블랙리스트 관계라면 참가 거부 처리해준 뒤 기존 구현되어있는 “MATCH_JOIN_DENIED” 이벤트를 발행해줌
3. 매칭시 기존 등록된 친구를 포함해서 매칭은 어떤식으로 구현해줄 것인지 ?
-> 자동매칭 시작 전에 친구 초대를 통해서 2명(초대한 사람 + 수락한 친구)가 동일한 이벤트의 매칭을 발행하도록(초대한 사람이 “INVITE_FRIEND” API를 호출해주는 구조), 만약에 수락 시 백엔드에서 둘을 함께 매칭 로직에 넣어서 새 방 생성(또는 기존 방 참가).
카프카에서 “FRIEND_INVITED” / “FRIEND_ACCEPTED” 이벤트를 발행해줌
구현사항
매칭 필터링과 관련하여 구현한 MatchingAlgorithmServiceImpl의 내용은 아래와 같았다.

사용자가 입력한 출발지, 도착지, 태그 조건에 맞는 활성 상태의 매칭 방을 검색하는 로직(findRoom 메서드)인데,
아래의 플로우에서 사용되는 내용으로 이해해주면 될거같다
- 멤버 아이디로 사용자 조회 및, 해당 특정 사용자가 방에 이미 방에 존재하는지 조회
- ST_Distance_Sphere를 활용하여 출발지(300m 이내) 도착지(300m 이내)의 매칭 방을 필터링
- 검색된 매칭 방 리스트에서 ACTIVE 상태인 방만 검색되도록 필터링
- 태그 조건(criteria)이 주어진 경우, 태그 조건을 만족하는 방만 추가로 필터링
- 위 조건에 맞는 방이 있으면 해당 방에 참가할 수 있도록 방의 정보를 조회
- 조건에 맞는 방이 없다면 해당 방을 생성
거리 조건은 300m 이내로 설정했고, 태그가 비어있는 경우에도 처리할 수 있도록 아래 사진처럼 태그 조건이 있는 경우를 별도로 설정하여 처리해주었다

느낀점
물론, 현재 클라이언트 측에서 앱으로의 마이그레이션이라던지, 백엔드의 친구 추가, 블랙리스트 관리 등 후순위 작업들이 아직 완료되지 않은 상태에서 작성한 회고이기 때문에, 이와 관련된 API 연결조차 진행되지 않은 상태라는 점을 감안해야한다
따라서, 프로젝트가 아직 완전히 끝난 것은 아니라는 점은 참고해줬으면 좋겠다.
SMS 서비스 금전적 문제
아직 해당 프로젝트에 대한 최종발표가 끝난 것이 아닌 상태지만, 해당 프로젝트에 개인적으로 남은 아쉬움은 내가 구현하는 파트가 사업자 관련한 이슈로 너무 적어진 것이 아닐까 싶다.
우리의 프로젝트는 보안성과 신뢰성이 생명인 서비스라 판단했었기에, 사용자가 인증번호를 받아 직접 휴대폰 번호를 인증을 받는 시스템을 내가 구현을 하려했었다.

우리가 사용하려던 네이버 클라우드의 SMS 서비스는 사업자 계정으로만 사용할 수 있었기 때문에
이를 대신할 방안으로 CoolSms라는 문자발송대행 서비스 이용해서 구현하려했지만, SMS를 발송할 경우 건당 수수료 문제가 발생하여 해당 기능은 우선순위에서 제외하게 되었고, 팀원들과 상의 끝에 후순위로 미룰 수밖에 없는 결정을 내리게 되었다 🥺
결제 시스템 도입의 어려움
또한 초기 역할 분담에서도 나와 있듯이, 원래 우리가 개발하려던 서비스는 택시 호출 전 결제 시스템 도입까지 포함하고 있었다. 이는 사용자 경험 측면에서도 당연히 좋고, 안전한 결제 프로세스를 보장하기 위한 핵심 기능으로 계획되었으나 사업자 등록이 되지 않으면 토스(Toss)의 결제 API를 활용할 수 없는 제약이 있었다. 원래는 주영이와 매칭 관련 역할 분담 시 상대적으로 작업 볼륨이 적었던 내가,
해당 결제 기능까지 추가적으로 구현하여 프로젝트에 기여하고 싶었던 마음이 있었지만, 현실적인 한계로 인해 이 기능 역시 제외가 되어 너무 아쉬웠다....
결론
이처럼 여러 가지 외부적인 제약과 아쉬움이 있었지만,
그래도 현재는 남은 기능이라도 집중해서 끝까지 프로젝트를 마치고 싶다는 생각뿐이다.
앞으로의 프로젝트에서는 해당 경험을 바탕으로 더 철저한 기획과 현실적인 계획 수립을 통해, 부족했던 부분을 보완하고 한 단계 더 성장한 개발자가 되고 싶다.
https://junuuu.tistory.com/795
'Spring > 매칭 로직' 카테고리의 다른 글
가치택시(수동 매칭, Spring) (0) | 2025.02.05 |
---|