- 가상화폐 모의투자 플랫폼 지향 웹 서비스 “FUNCO” (ssafy 우수 프로젝트 1등 수상)
- 실시간 가상화폐 시세로 다른 사람들과 함께 투자하며 즐기는 모의투자 서비스
- 다른 사람에게 투자하는 팔로윙 투자
- 짜릿한 100배 배율이 가능한 선물 거래
- 모두와 함께 즐기고 경쟁하는 랭킹 시스템
- 투자에 대해 소통하는 인사이트 게시판
- 나의 투자 통계를 보고싶어? 투자내역 및 통계
- SPA React.js와 Monolithic Architecture Spring Boot Server로 1차 개발 완료 및 배포
- ➡️ 2차 개발 기간 동안 Next.js와 12개의 MSA Spring Boot Server로 전환 및 고도화 개발 및 배포
박세웅 [팀장, BE] | 소재열 [CTO, BE, INFRA] | 이선주 [BE] | 이태호 [BE, INFRA] | 엄소현 [FE, BE] | 황주영 [FE] |
- ✅ WEB service URL :
https://funco.co.kr - ✅ API URL :
https://api.funco.co.kr
분류 | 기술 스택 |
---|---|
BE | |
FE | |
Infra | |
협업도구 |
메인 페이지 | 시세 | 호가 | 거래 |
선물거래 | 투자내역 | 팔로우 | 원 초기화 |
랭킹 | 알림 | 포트폴리오 구매 | 투자노트 | 투자노트 상세보기 및 댓글 |
- 시간대 별 코인 시세 차트 조회
- 실시간 코인 시세 조회 및 검색
- 시장가(간편 거래) 매수, 매도
- 지정가(예약 거래) 매수, 매도
- 가상화폐 체결, 미체결 내역 조회
- 거래 체결 시 알림
- 관심 코인 추가, 조회, 삭제
- 보유 코인 조회
- 선물 거래 레버리지(배율) 설정
- Long 거래
- Short 거래
- 자동 청산 및 정산 시스템
- 선물 거래 내역
- 보유자산 목록 조회
- 일별, 월별 투자 손익 조회
- 기간/거래종류/자산종류 별 자산 변동 내역 조회
- 팔로잉, 팔로워 투자 자산 조회
- 팔로우 거래, 보유 내역 조회
- 모든 가상화폐 미체결 거래 내역 조회
- 팔로우 시 자산 동기화
- 팔로잉의 투자에 따라 자동 투자
- 팔로우 정산 시 알림
- 정각 기준 1분 마다 랭킹 업데이트
- 총 팔로워 금액에 따른 랭킹 조회
- 총 자산에 따른 랭킹 조회
- 코인 별 투자 게시판
- 다양한 카테고리의 게시판 글쓰기 및 댓글
- 내 투자내역 ( 포트폴리오 )을 비공개로 가격 설정하여 구독판매
💡 회원은 Spring Security & JWT & Oauth2.0 사용하여 구글 소셜 로그인 구현
- 회원 가입
- 로그인, 로그아웃
- 유저 투자 포트폴리오 조회
- 닉네임 수정
- 한줄 소개 수정
- 실시간 알림 및 알림 히스토리 조회
- 투자 정산, 팔로우 정산, 선물 청산, 게시글 댓글, 답글 등 다양한 알림기능
- QueryDslItemReader를 활용하여 Chunk-oriented Processing으로 데이터를 처리하여 저장
- 매일 오전 6시에 전날의 거래 내역으로 일별 통계 내역을 생성하는 Job
- 체결 내역 테이블의 데이터를 누적 계산하여 도출된 손익을 임시 손익 테이블에 저장하는 Step
- 임시 손익 테이블의 데이터를 일별 통계 테이블에 저장하는 Step
- 매월 1일 자정에 전달의 일별 통계 내역으로 월별 통계 내역을 생성하는 Job 실행
- 전달의 일별 통계 테이블의 데이터를 누적 계산하여 월별 통계 테이블에 저장하는 Step
- 100여 개의 코인의 시세를 실시간 웹소켓으로 받아오는데 보유 및 관심 코인 리스트에서는 백여 개의 코인 시세를 실시간으로 받아올 필요가 없습니다
- 웹소켓을 모듈화 하여 다른 파일에서도 웹소켓의 send 요청을 보낼 수 있도록 했습니다
- 랭킹은 어쩔 수 없이 매번 총 자산과 총 팔로워 금액을 구해야하기 때문에 성능에 대한 고민이 있을 수 밖에 없었습니다.
- 실시간은 쿼리가 많이 발생하여 너무 서버에 부담이 갈 것 같아서 30분마다 스케줄링을 돌려 계산을 하고 계산한 값들은 레디스에 넣도록 했습니다.
- 조회가 많이 일어나기 때문에 redis 사용을 고려했습니다.
- 정렬 기능을 필요로 했기 때문에 레디스의 ZSet을 활용하여 정렬을 하였고 조회할 때마다 레디스에서 캐싱하여 보여주었습니다.
- ZSet 연산은 O(log(n))으로 단순히 java의 timsort, Arrays.sort()의 평균 O(nlog(n))보다 훨씬 효율적입니다.
- zrange의 시간복잡도는 O(log(n) + m(반환받는 멤버들의 개수))로 효율적으로 페이징 처리를 했습니다.
- 서버에서 실시간으로 등록된 예약 거래가 처리되어야 했다.
- 서버가 웹소켓 클라이언트가 돼서 실시간으로 메모리에 코인 시세들을 받아와 저장한다.
- 예약 거래를 동시성 처리를 위해 ConcurrentHashMap으로 관리했고 각 코인 별 매수, 매도 우선순위 큐를 사용해 시세를 감지하여 거래가 될 수 있는 데이터 또는 하나의 데이터만 확인하도록 O(1)로 구현했습니다.
- 성능 최적화를 위해 예약 거래에 등록된 코인의 시세 데이터만 유동적으로 받아오도록 웹소켓 메시지를 동적으로 처리했습니다.
- 핀테크 프로젝트 특성 상 정확한 소수점 연산을 다뤄야 함. 우리의 경우 정확한 코인 수량과 가격에 대한 정확하고 일관적인 연산 결과가 필요.
- BigDecimal Utility class 를 만들어 전역으로 사용함으로써 일관적인 연산과 정확한 소수점 연산을 할 수 있게 됐다.
- Offset 방식의 Pagination은 Offset 값이 커질수록 그만큼의 row를 읽어야하므로 성능저하가 일어납니다.
- 가상화폐 거래 사이트 특성상 무수히 많은 거래 내역이 저장 될 것이므로 Cursor Pagination을 사용하여 조회 성능을 최적화 하였습니다.
- 이러한 방식은 Batch의 ItemReader에도 적용하였습니다.
- 전날의 모든 거래 내역으로 일별 통계를 생성하는 Job에서 QueryDslNoOffsetItemReader를 사용하여 Offset 없이 Chunk 단위로 데이터를 읽어 프로세싱합니다.
- java 우선순위 큐 동시성문제 (https://sohy.notion.site/632d97099fb94a07a38c62183518b75e)
- jwt 인증 로직 고민 (https://www.notion.so/sohy/3f5cdc34f3ee4656ac4726f9b09bff69)
- architecture 개선 고민(https://www.notion.so/sohy/Architecture-75d01b54d0d84e0fb188e85078db3fe4)
- docker-compose 고민(https://www.notion.so/sohy/docker-compose-a86e09b85ea64963b21ea9dddb95cd62)
- message queue 뭐 쓸지 고민(https://www.notion.so/sohy/RabbitMQ-vs-Kafka-c2a8d8ecee614a1993b141381d12ec16)
- cloudflare 속도 문제 (https://www.notion.so/sohy/cloudflare-dns-91d5f7e242b24084a75bcb55cf81f2fd)