식구하자 프로젝트는 반려식물 및 식물 용품을 중고 거래를 하고, 반려식물을 관리하기 위한 정보를 얻을수 있으며 내가 키우는 반려식물의 사진과 정보를 sns 형식으로 다른 사용자와 공유하는 플랫폼입니다.
pc 환경(Chrome) 권장
- React
- Java
- SpringBoot, JPA, QueryDSL
- Spring cloud, gateway, eureka, config, feign client
- Kafka,rabbitmq, STOMP
- Prometheus & Grafana, circuitbreaker
- DB - Mysql, Redis, Mongo
- INFRA - docker, Jenkins, AWS EC2, S3, Route 53, CloudFront
- Collaboration - GitHub
![시스템 아키텍쳐](https://private-user-images.githubusercontent.com/86508110/332686627-a1752131-d883-43f3-8b6c-0e3769b2ed6a.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM3ODAwNDMsIm5iZiI6MTcyMzc3OTc0MywicGF0aCI6Ii84NjUwODExMC8zMzI2ODY2MjctYTE3NTIxMzEtZDg4My00M2YzLThiNmMtMGUzNzY5YjJlZDZhLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE2VDAzNDIyM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFiZjVmMDJlYjJhOWE3MWIzMWQ5NWEyZDAxZmU4MWE1NDU4MjI4YzdiM2U4MjBhY2ZiNTIyMTE0ZWY4NzBiY2YmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.SOuDR-2ilt4bDJeEqSeICRxzHdDitkIlADeFlX3G5J4)
![msa 설계도](https://private-user-images.githubusercontent.com/86508110/332686676-2c80db0e-342a-4f1d-8bff-11ed6f3f4015.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM3ODAwNDMsIm5iZiI6MTcyMzc3OTc0MywicGF0aCI6Ii84NjUwODExMC8zMzI2ODY2NzYtMmM4MGRiMGUtMzQyYS00ZjFkLThiZmYtMTFlZDZmM2Y0MDE1LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE2VDAzNDIyM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTg5NTc2ZDQ5YmFkNjg1MTA1MzU3MjA0MDQyNmViZWQ4OTM3NDAxNGFlMTE2NjQ0NTcwMzBjM2U1NTFkMjhlZTEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.68LZWpkpbRRUs0rW2ea4_XmKsWhy-4R6fSxYBJJxhM4)
![스크린샷 2024-05-22 오후 3 06 24](https://private-user-images.githubusercontent.com/86508110/332686884-da826aaa-37c1-476c-a93c-f74723fb6b6d.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjM3ODAwNDMsIm5iZiI6MTcyMzc3OTc0MywicGF0aCI6Ii84NjUwODExMC8zMzI2ODY4ODQtZGE4MjZhYWEtMzdjMS00NzZjLWE5M2MtZjc0NzIzZmI2YjZkLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTYlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE2VDAzNDIyM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWM5YTcyNzgzNGY2MTU1ZTA5YzFlMjhlMjJlMDkxMDA4NjA2NWFiZGFhNTgyYjI0ZTRlMGY4ZWNiMWY1MmI0ZTgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.PSuQyUaEjT8PyuDixOU73yw9QSUdb1x0ocF1QzUFX3A)
- 서비스 디스커버리 및 API Gateway에서 인증, 라우팅 역할 수행
- 설정 정보의 중앙 집중화 관리
- Spring Cloud Config를 통해 모든 서비스의 설정 정보를 중앙 저장소(Git 등)에서 관리함으로써 일관성을 유지하고, 설정 변경 이력을 체계적으로 추적할 수 있습니다. 이를 통해 설정 정보의 관리와 배포가 간편해지며, 설정 변경 시 서비스 재배포 없이도 적용할 수 있습니다.
- 동적 구성 업데이트
- Spring Cloud Bus와 RabbitMQ를 활용하여 설정 변경 사항을 실시간으로 모든 연결된 서비스에 전달할 수 있습니다. 이는 각 서비스가 개별적으로 설정을 업데이트하는 actuator refresh 방식에 비해 훨씬 효율적입니다. Spring Cloud Bus에 연결된 어느 서비스에서나 /busrefresh 엔드포인트를 POST 방식으로 호출하면, Spring Cloud Bus가 이를 감지하여 RabbitMQ를 통해 모든 관련 서비스에 변경된 설정을 전달하고 업데이트를 수행합니다. 이를 통해 설정 변경 시 서비스의 재시작이나 수동 업데이트를 할 필요 없이 자동으로 변경 사항이 반영됩니다.
- Jenkins와 Docker를 활용하여 CI/CD 파이프라인 구축
- 식물, 식물용품 중고 거래 게시글 CRUD
- 중고 게시글 검색(제목, 내용, 키워드)
- 중고 거래 게시글 조회수, 찜
- 중고 거래 게시글 사진 업로드
- S3 활용
- 중고 거래 구매자 결정
- 로그인, 소셜로그인 기능(카카오), 로그아웃
- 회원가입
- 회원 가입시 네이버 smtp 이메일 본인 인증
- 아이디, 비밀번호 찾기
- 내 정보
- 구매 내역, 판매 내역, 찜 내역, 페이 머니 조회, 쿠폰 내역, 키워드 설정정보
- JWT 토큰
- Access Token 재발급을 위해 Refresh Token을 Redis에 저장
- 농사로 API를 사용하여 100여가지 종의 식물 정보 제공
- 검색 기능에 QueryDsl을 활용한 동적 쿼리 적용
- 식물 종류 별 검색
- 식물 관리 난이도 별 검색
- 중고 거래시 판매자에게 1:1 채팅( kafka+stomp를 활용)
- 채팅 읽음 여부 표시 기능 구현
- 채팅방에 접속한 회원의 데이터는 자주 변경이 되고 휘발되는 데이터이므로 Redis를 이용하여 관리하였습니다 .
- 접속 정보를 Redis를 통한 관리로 채팅방에 모두 접속했을경우, 알림이 가지 않도록 구현
- 채팅 읽음 여부 표시 기능 구현
- SSE를 이용한 실시간 알람이 발송(분리된 마이크로서비스에서 알림이 필요할 경우 느슨한 결합을 유지하기 위해 비동기식 kafka 이벤트 활용)
- 내가 올린 SNS게시글에 댓글,좋아요가 달리거나
- 키워드 등록을 통해 유저가 원하는 키워드가 거래 게시글로 올라왔을 경우
- 내가 올림 거래 게시글에 상대방이 찜할 경우
- 채팅방에 새로운 채팅이 있을 경우 SSE를 이용한 실시간 알람이 발송
- 읽기가 잦은 채팅 내역 데이터는 RDB 대신 MongoDB를 선택하여 사용했습니다.
- 거래 게시글이 삭제되면 해당 게시글에 속한 채팅방 및 채팅 내역들의 연쇄적인 삭제가 필요하다 생각이 들었습니다. 하지만 거래 게시글은 게시글 마이크로서비스이고 채팅 관련 데이터는 채팅 마이크로 서비스의 단일 DB에 저장이 되있으므로 kafka를 사용하여 이벤트 발생시 데이터 동기화를 진행하게 구현
실제로 결제가 되지 않고, 테스트 환경입니다
- 중고 식물 거래 시 , 페이 머니 충전을 통한 결제 기능
- 실제 계좌 이체 연동은 대신, iamport api 사용한 결제 기능 구현
- 나의 페이 머니 조회
- 페이 머니 계좌 환불 기능(실제로 계좌에 환불되지 않습니다)
- 중고 식물 거래시 사용 가능한 3,000원 할인 쿠폰을 매일 13시에 선착순 100명에게 제공하는 기능을 구현
- 매일 정오 시각에 사용 완료및 유효기간이 지난 쿠폰 데이터를 scheduler를 통해 삭제 할 수 있도록 기능을 구현
- 유저 별 하루 1개의 쿠폰 발급을 위해 중복 방지를 Redis의 Set 자료구조를 활용하였고 다수의 사용자가 쿠폰 발급을 요청하더라도 정확히 100개의 쿠폰 발급을 위해 redis 싱글스레드 특성을 이용하여 원자적 연산을 통한 동시성 제어
- 쿠폰 발급시 RDB의 저하 이슈를 Kafka를 통해 처리량 조절을 통해 최적화
- 결제 시스템과의 통합
- 쿠폰 서비스는 결제 마이크로서비스와 통합되어, 사용자가 식물 중고 거래 시 쿠폰을 적용할 수 있도록 구현되었습니다. 이 과정에서, 사용자는 할인된 가격으로 거래를 진행할 수 있으며, 판매자는 할인 전 가격을 받습니다.
- 분산 트랜잭션의 제어를 위해 SAGA Choreography 패턴을 적용하였습니다.
- 유저별 쿠폰 조회
- 자신이 키우는 반려식물 sns 형식의 공유 서비스
- sns 게시글 crud 구현
- sns 게시글 댓글, 대댓글 기능 구현
- sns 게시글 좋아요 및 조회수 기능
- 게시글 좋아요 기능에서 Redisson 분산락과 Facade 패턴을 사용하여 동시성 문제 해결 패턴을 사용하여 동시성 문제 해결
- 게시글에 이미지 업로드 기능(S3)
- 이주의 게시글, 이달의 게시글 조회
- 인기 해시 태그 조회
- 게시글 검색기능
- QueryDSL을 활용한 동적 쿼리 작성
- 태그(완전일치)
- 제목(포함)
- 내용(포함)
- 닉네임(완전일치
- QueryDSL을 활용한 동적 쿼리 작성
- 쿠폰 적용 및 결제 프로세스에서 분산 트랜잭션 제어를 위해 SAGA Choreography 패턴 적용
- 각 마이크로서비스의 로컬 트랜잭션과 보상 트랜잭션을 통한 데이터 일관성 유지
- Kafka를 활용한 이벤트 기반 비동기 통신으로 서비스 간 느슨한 결합 구현
- 3대의 EC2 인스턴스를 활용하여 Kafka 브로커 3개와 Zookeeper 인스턴스 3개로 구성된 클러스터 구축
- 시스템의 고가용성, 확장성 향상 및 단일 실패 지점 제거
- 멱등성 프로듀서 설정으로 메시지 중복 전송 방지 및 데이터 무결성 보장
- 데이터베이스 변경 사항을 실시간으로 감지하고 Kafka로 전송하는 CDC 구현
- Transactional Outbox Pattern을 통한 데이터베이스 트랜잭션과 메시지 발행의 원자성 보장
- 서비스 간 데이터 일관성 유지 및 메시지 손실 위험 최소화
- Jenkins CI/CD 적용
- 1:1 채팅 시 읽지 않은 채팅 관련 문제 해결
- JPA open-in-view SSE Connection 고갈 문제 && 마이크로 서비스간 단일 DB 데이터 동기화 문제 해결
- 선착순 쿠폰 발급시 동시성 제어 및 DB 성능 문제 해결
- Redisson및 퍼사드 패턴을 활용한 SNS 서비스 좋아요 동시성 문제 해결
- 마이크로 서비스간 분산 트랜잭션 제어 문제 해결 By Saga Pattern
- 로그인 기능 리팩터링-Redis를 이용한Refresh Token 재발급
- Kafka cluster 구축해서 가용성 높이기
- CDC+ Transactional Outbox Pattern 적용
요구사항 | 선택지 | 설명 |
---|---|---|
MQ | Kafka vs RabbitMQ | MQ는 Kafka와 RabbitMq를 함께 사용하였습니다. Kafka는 마이크로서비스 간의 느슨한 결합을 유지하고, 채팅 서비스와 같은 대용량 트래픽을 처리하기 위해 사용되었습니다. Kafka는 높은 처리량과 내구성을 제공하여 대규모 데이터 처리에 적합하며, 분산 아키텍처를 통해 확장성이 뛰어나고 높은 처리량을 안정적으로 지원합니다. 이는 마이크로서비스 간의 통신을 비동기 이벤트 기반으로 처리하여 시스템의 유연성과 확장성을 높여줍니다. 반면, RabbitMQ는 Spring Cloud Config & Bus와 함께 사용되어, 적은 데이터를 처리하면서 신뢰성과 보안이 중요한 경우에 적합합니다. RabbitMQ는 메시지의 신속한 전달과 처리 보장, 그리고 손쉬운 설정 변경을 통해 실시간 동적 구성을 효율적으로 관리할 수 있습니다. |
마이크로 서비스 간 통신 | Kafka vs Feign client | 데이터 조회용으로는 Feign Client를 사용하여 마이크로서비스 간의 통신을 간편하게 하였습니다. Feign Client는 선언적인 방식으로 HTTP 요청을 보낼 수 있어 코드의 가독성과 유지보수성이 뛰어납니다. 데이터의 수정, 삭제, 삽입 작업에서는 Kafka를 활용한 이벤트 기반의 비동기 처리를 통해 느슨한 결합 및 데이터 동기화를 유지하였습니다. |
실시간 통신 | Websocket vs Stomp | Stomp로 채팅을 구현하면, 사용자가 채팅방에 접속했을 때, 채팅방을 구독하기만 하면 누가 접속 중인지 따로 관리하지 않더라도 메시지를 보낸 사용자가 포함된 채팅방의 모든 사람에게 메시지가 갈 수 있다는 장점이 있기 때문에 사용하였습니다. |
데이터베이스 | Mongo vs Mysql | 데이터베이스는 MongoDB와 MySQL을 함께 사용하였습니다. MongoDB는 채팅 데이터에만 사용하였는데, 채팅 데이터는 수정될 필요가 없고 조회와 삽입 작업만 이루어지므로, NoSQL의 장점인 빠른 읽기 성능을 활용할 수 있었습니다. 나머지 데이터는 관계형 데이터베이스인 MySQL을 사용하여 데이터 무결성과 복잡한 쿼리 작업에 적합하도록 하였습니다. |
CI/CD | Github action vs Jenkins | 이번 프로젝트는 여러 서버를 구성하고 관리해야 하는 MSA 프로젝트였기 때문에, Jenkins의 유연성과 확장성을 고려하여 CI/CD 도구로 선택하였습니다. 대규모 시스템의 경우 Github Actions보다 Jenkins가 빠른 실행되므로 Jenkins로 선택하였습니다. |