Skip to content

Sparata-Sheep/SheepEz_loan

Repository files navigation

SheepEz_loan: 개인 간 대출을 쉽고 빠르게, 안전하게 할 수 있는 P2P 대출 플랫폼

🐑 SheepEz_loan: 소개

  • 현재 존재하는 P2P 대출 플랫폼은 중개 플랫폼이 다수입니다.
  • 대출 조건을 플랫폼에서 강제하지 않고, 당X마켓과 같이 거래를 활성화시키기 위해 게시글, 채팅 기능을 추가합니다. 사용자끼리 커뮤니티를 구성하여 대출자를 구인합니다.
  • 개인이 작성한 계약서를 바탕으로 변호사에게 상담을 신청하여 계약서를 검토합니다.
  • 대출 조건을 플랫폼에서 강제하지 않음으로써 구매력이 강해집니다.

🏅 SheepEz_loan: 목표

위의 조건들을 적용하여 기존의 서비스들과의 차별화가 진행된 대출 플랫폼 서비스를 만드는 것이 목표입니다.


🐬 Docker-compose 실행 방법

  • 레디스를 로컬에서 띄웁니다.
  • Dockerfile 에서 active profile 을 local로 설정 후 아래의 과정을 수행합니다.
 $ gradlew build

 $ docker compose up --build -d

🏗️ 서비스 아키텍처 & CI/CD 파이프라인

image


💰 주요 기능

  • 변호사 기능

    • 변호사 등록: 사이트에 변호사 등록을 신청하여 승인을 받으면 변호사로 등록됩니다.
      • 등록 신청 시 변호사 소개, 자격 정보, 경력 사항들을 함께 업로드합니다.
    • 상담 신청: 변호사 정보 조회 시 변호사의 이름, 소개, 자격 정보, 경력 사항들이 제공되며 채팅방에 변호사 초대 버튼 클릭시 변호사에게 상담 신청 요청을 보냅니다.
      • 변호사 수락시 기존 대화에서 변호사와 셋이서(예비 채권자, 예비 채무자, 변호사) 대화가 가능합니다.
      • P2P 대출이 이루어질 때, 유저는 채팅방에 계약서를 업로드하여 검토받을 수 있습니다.
    • 변호사 리뷰: 계약이 체결되면 사용자는 상담을 신청했던 변호사에게 별점과 코멘트를 남겨 리뷰를 달 수 있습니다.
  • 게시글 기능

    • 게시글 등록: 사용자는 게시글을 게시 및 조회할 수 있고, 자신의 게시글만 수정, 삭제가 가능합니다.
      • 게시글에는 '대출해드립니다', '대출 받습니다' 두 개의 카테고리가 존재합니다.
      • 게시글에는 해당 대출에 적용되는 계약 상태를 게시글 상단에 노출시킵니다.
        • 모집 중(OPEN) → 대출자를 모집 중인 단계
        • 진행 중(IN_PROGRESS) → 대출이 진행중인 단계
        • 계약 완료(COMPLETED) → 계약이 체결된 단계
      • 계약이 생성되거나 해당 계약이 성사되면 게시글의 상태가 업데이트됩니다.
  • 계약 기능

    • 계약 생성: 계약은 게시글에 종속된 상태로 채권자, 채무자 간 합의에 의해 생성됩니다.
      • 한쪽의 계약 생성 요청 시 상대의 요청 허가 후 생성됩니다.
      • 계약 완료, 취소 요청도 마찬가지로 상호 합의하에 진행됩니다.
      • 계약이 생성, 완료, 취소됨에 따라 연결된 게시글의 상태가 변경됩니다.
  • 채팅방 기능

    • 채팅방 생성: 사용자는 누구든 원하는 상대와 채팅을 할 수 있습니다.
      • 계약서 파일을 채팅방에 업로드하여 공유할 수 있습니다.
      • 원하는 변호사를 초대하여 계약서 파일을 검토받을 수 있습니다.

🛠️ 적용 기술

  • Backend
    • Java 21
    • Spring Boot 3.3.4
    • JWT
    • JPA
    • QueryDSL
  • Database
    • AWS RDS(PostgreSQL)
    • AWS ElastiCache(Redis)
    • AWS S3
  • Build
    • gradle
  • CI/CD
    • Docker
    • AWS - EC2
    • Github Actions
  • Version
    • Git
    • Github

💡 기술적 의사결정

DDD, 멀티 모듈 프로젝트 구조를 적용하여 프로젝트의 유연성 및 확장성이 고려된 MSA 구조로 진행하였습니다.

image

  • 하나의 서비스를 각 레이어 별 3개의 모듈로 나누었습니다
  • 이러한 구조를 가지면 우선, 도메인 영역(Business Logic)을 특정 라이브러리에서 완전히 분리할 수 있습니다.
    • 이렇게 되면 버전 업데이트, 내부 요구사항 등으로 라이브러리 변경이 필요할 때 비즈니스 로직에 영향없이 작업이 가능합니다.
  • 또한, 레이어드 아키텍처 원칙에 따라 레이어 역류, 건너뛰기를 방지할 수 있습니다.
    • 이 구조에서 API 모듈은 스토리지 모듈을 런타임에만 의존하게 되고 스토리지 모듈은 도메인 모듈의 명세를 따라 구현체의 역할만 수행하게 됩니다.
    • 이렇게 되면 API 모듈은 도메인 모듈만 알고 그 구현체가 어떻게 되어있는지 모르게 되어 참조가 불가능해 집니다.
  • 이렇게 함으로써, 격리된 환경에서 비즈니스를 확장할 수 있고, Layered Architecture가 익숙하지 않은 팀원이 참여해도 규칙에 따라 쉽게 개발할 수 있어 해당 구조를 채택했습니다.

변호사 평점 조회 Redis 도입

  • 기존 변호사의 평점을 조회하기 위해서는 해당 변호사의 리뷰 전체를 조회해 평균을 냈습니다.
  • 평점을 위해 매번 DB를 조회하는 것은 대규모 시스템에서 성능 상 큰 문제가 있습니다.
  • 때문에 Redis 도입을 고려했습니다.
  • Redis는 인메모리 디비로 기존 RDB 보다 빠른 데이터 읽기와 수정이 가능합니다.
  • Redis에 변호사의 총 리뷰 개수, 현재 평점을 저장하고 리뷰가 추가 될 때 이를 갱신하는 방식으로 구현했습니다.

채팅 기능 구현에는 어떤 기술이 적합할까?

1. 고려된 기술들

  • WebSocket
    • 클라이언트와 서버 간 양방향 실시간 통신이 가능 합니다.
    • 연결 후 상시 유지되어 실시간 데이터 주고받기 적합합니다.
    • 실시간성이 중요한 경우에 적합합니다.
  • Spring WebFlux
    • 비동기/논블로킹 방식으로 높은 성능 제공 합니다.
    • Reactive Streams 기반의 고성능/확장성
    • REST API, WebSocket, Server-Sent Events(SSE) 등 다양한 비동기 통신을 지원 합니다.
    • 적은 스레드로 많은 동시 요청 처리에 유리 합니다.

2. 최종 선택: WebFlux

  • WebFlux 선택 이유
    • WebSocket, SSE 등 다양한 실시간 데이터 스트리밍 방식을 지원 하기 때문에 선택 했습니다.
    • 비동기 처리로 자원 효율적 사용 및 고성능 보장하기 때문에 선택 했습니다.
    • 대규모 실시간 채팅 기능에 적합 하다고 판단하여 선택 했습니다.
    • 확장성: 향후 알림 기능 구현 등에도 활용 가능 하기 때문에 선택 했습니다.

3. 결론

  • WebFlux는 다양한 실시간 통신 방식과 성능, 확장성을 고려한 최적의 선택입니다.
  • 실시간 채팅뿐만 아니라 향후 추가될 기능에서도 유연한 대응이 가능합니다.

채팅 기능 대규모 처리에는 어떤 기술이 적합할까?

1. 문제 인식

  • 사용자가 증가하면 채팅방메시지도 증가 → 데이터 축적 및 트래픽 문제 예상
  • 대규모 처리를 위한 적합한 메시징 시스템 필요

2. 후보 기술: Apache Kafka vs RabbitMQ

  • Apache Kafka
    • 장점:
      • 높은 처리량확장성 제공
      • 내구성파티셔닝 지원
      • 실시간 스트리밍 데이터 처리에 적합
    • 단점:
      • 복잡한 설치 및 운영
      • 메시지 브로커로서 기능 제한
    • 적합성: 트래픽이 많은 실시간 채팅 시스템에서 안정적 처리 가능
  • RabbitMQ
    • 장점:
      • 메시지 라우팅 기능 및 유연한 메시지 패턴 지원
      • 간단한 설치 및 운영
      • 메시지 우선순위딜레이 큐 지원
    • 단점:
      • 처리량 한계 존재
      • 내구성에서 제한적
    • 적합성: 복잡한 메시지 라우팅 또는 작업 큐가 필요한 중소규모 트래픽 처리에 적합

3. 최종 선택: Kafka

  • Kafka 선택 이유
    • 대규모 트래픽 처리에 더 유리
    • 수평적 확장장애 내성 지원
    • 실시간 스트리밍 데이터 처리에 적합
    • 대규모 트래픽 환경에서의 안정성확장성 중시

4. 결론

  • 대규모 트래픽과 실시간 처리가 핵심인 서비스에서는 Kafka가 더 적합
  • 트래픽이 적거나 유연한 라우팅이 필요한 시스템에서는 RabbitMQ가 적합
  • Kafka를 선택하여 대규모 실시간 처리 요구를 충족

❓ 트러블슈팅

멀티 모듈 프로젝트에서의 의존성 주입 설정 문제

image

  • 위는 현재 프로젝트에서 사용된 멀티 모듈 프로젝트의 모듈 구조입니다. 에러 핸들링 과정에서 Service단에서의 여러 분기(없는 Entity 조회, 권한 부족 등)에 따른 예외를 발생시키기 위해 직접 구현한 ErrorType 코드, Exception 클래스가 필요했습니다.

image

  • 그러나 ErrorType, Exception 클래스는 support-api 모듈에 정의되어 있어 Service 로직에서 참조가 불가하였습니다.
  • 그래서 고안한 방법들은 아래와 같습니다.
  • Custom Exception 관련 코드를 support-domain으로 옮긴다면 api모듈에서도, domain 모듈에서도 사용이 가능하지만, support-api에도 Custom Exception을 필요로 하므로 문제가 발생합니다.
  • 그렇다면 Custom Exception 관련 코드를 복사하여 support-domain에도 동시에 두게 된다면, 중복성이 발생하고 spring-boot-starter-web 의존성이 support-domain에 들어가게 되어 순수 자바 코드만 사용하기로 했던 support-domain 모듈의 컨벤션에 어긋납니다.

image

  • 최종적으로 수정된 구조입니다. 공통적으로 사용되는 error 모듈을 새로운 공통 모듈로 생성하여 api 모듈, domain 모듈에 주입하여 사용할 수 있게 함으로써 문제를 해결할 수 있었습니다.

1. WebSocket 연결 실패 문제

  • 문제 상황:
    • 실시간 채팅 구현 중 WebSocket 연결 실패 발생
    • MSA 구조에서 API 애플리케이션만 실행하고, WebSocket 애플리케이션을 실행하지 않음
  • 원인:
    • WebSocket 애플리케이션 미실행으로 양방향 통신이 불가능
  • 해결 방법:
    • API 애플리케이션WebSocket 애플리케이션동시에 실행하여 문제 해결

2. WebFlux와 WebSocket 의존성 충돌 문제

  • 문제 상황:
    • API와 WebSocket 애플리케이션 실행 시, WebFlux와 WebSocket의 의존성 충돌 발생
    • WebFlux에서 WebSocket을 사용하면서, 두 기술의 의존성이 충돌
    • WebFlux는 비동기/논블로킹 방식, WebSocket은 MVC 형태로 혼용 불가
  • 원인:
    • WebFlux와 WebSocket의 서로 다른 의존성으로 인해 충돌 발생
  • 해결 방법:
    • WebSocket 의존성 삭제 시 WebSocket 사용 불가 문제 발생

    • 해결책으로 MVC 자동 구성 제외 설정 추가:

      image

    • 위 코드를 추가해 MVC와 WebFlux 충돌 문제 해결

결론

  • WebSocket 연결 실패애플리케이션의 동시 실행으로 해결
  • WebFlux와 WebSocket 의존성 충돌MVC 자동 구성 제외 설정으로 문제 해결

👨‍🔧 CONTRIBUTIONS

팀원명 포지션 담당(개인별 기여점) 깃허브 링크
길태환(팀장) - GW
- 유저
- Auth
- 변호사
▶ 멀티 모듈 프로젝트 구조 세팅
- 전체적인 모듈 구조 작성
- 팀원 온보딩을 위한 예제 모듈 및 코드 작성
▶ Cloud 구성
- Eureka, gateway 설정
- gateway 인증 필터 구현
- 인증 서버 구현
- 인증-유저 간 통신 구현
▶ 변호사 도메인 기능 구현
- 변호사 CRUD 구현
- 변호사 유저 간 통신 구현
▶ CI/CD 구현
- dockerfile, docker-compose.yml 파일 작성 등 도커 환경 구성
- 깃헙 액션 스크립트 작성
- aws vpc 생성 등 배포 환경 세팅
https://github.com/road3144
김규준 - 채팅 ▶ 채팅 도메인 기능 구현
- 채팅방 CR + HTML 구현
- 채팅방에 변호사 초대 기능 구현
- 채팅방에 접속한 사용자 전제 조회
- 채팅방과 게시글 간 통신 구현
▶ 웹소켓 연결 및 실시간 채팅 시스템 구현
- HTML에 WebSocket 연결 실시간 채팅 기능 구현
▶ 채팅 기능 kafka 도입
- Kafka를 통해 채팅 메세지 전송, 대규모 처리
https://github.com/mbc2579
박상훈 - 게시글
- 계약
▶ 게시글 도메인 기능 구현
- 게시글 CRUD + Search 기능 구현
- 유저 도메인과 연결하여 권한 관리
▶ 계약 도메인 기능 구현
- 계약 CRUD + Search 기능 구현
- 유저 도메인과 연결하여 권한 관리
- 게시글과 연동하여 status 값 관리
▶ S3를 통한 계약서 파일 업로드 구현
- AWS S3와의 연동을 통해 계약서 파일의 업로드 구현
▶ support-error 모듈 작성
- 에러 코드 작성 및 공통모듈화
https://github.com/asd0236

Project Set-Up

Git Hook

프리 커밋 설정으로 커밋 전 코드 포맷 검사

$ git config core.hookspath .githooks

IntelliJ IDEA

  • 테스트 설정
// Gradle Build and run with IntelliJ IDEA
Build, Execution, Deployment > Build Tools > Gradle > Run tests using > IntelliJ IDEA	

Lint

수동으로 코드 포맷 수정

./gradlew format

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages