Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] 고급 모의투자 게임 구현 #55

Merged
merged 12 commits into from
Nov 28, 2024

Conversation

Preta3418
Copy link
Collaborator

@Preta3418 Preta3418 commented Nov 27, 2024

#️⃣ 연관된 이슈 번호

closed #51
related to #27
related to #25

✅ PR 유형

  • 새로운 기능 추가

코드 확인할떄 StockRecord 부터 확인하고 AdvancedInvest 로 넘어가면 좀 더 이해하기 편합니다/

StockRecord : 유저가 진행한 모든 구매와 판매 관련된 기록을 남기고, 해당 기록들을 통해 보유한 주식을 계산하는 도메인
AdvancedInvest : 게임을 진행하는 도메인으로 WebSocket 으로 구현되어 있음.

StockRecord

1. Stock Record 구성

1.1 Controller

  • StockRecordController
    • HTTP API를 통해 StockRecord 엔티티와 관련된 데이터 처리 담당.
    • POST /api/v1/stock-records: 거래 내역 저장.
      • StockRecordRequestDto를 사용하여 데이터 전송.
      • 멤버를 조회 후 거래 내역을 StockRecordService에 전달하여 저장.
    • GET /api/v1/stock-records/{advId}: 특정 AdvancedInvest ID의 거래 내역 조회.
      • 응답으로 StockRecordResponseDto 반환.
    • GET /api/v1/stock-records/{advId}/{stockSymbol}/quantity: 특정 주식의 보유량 조회.
      • calculateOwnedStock 메서드로 계산된 보유량 반환.
    • GET /api/v1/stock-records/{advId}/all-quantities: 모든 주식의 보유량 조회.
      • Map 형태로 주식 심볼과 보유량 반환.

1.2 DTOs

  • StockRecordRequestDto

    • 거래 내역 저장 요청을 위한 DTO.
    • 필드:
      • stockSymbol: 주식 심볼.
      • tradeType: 거래 유형 (구매/판매).
      • price: 거래 단가.
      • quantity: 거래 수량.
      • advId: AdvancedInvest ID.
      • memberId: 사용자 ID.
    • toEntity(Member member) 메서드를 통해 엔티티로 변환 가능.
  • StockRecordResponseDto

  • 거래 내역 응답을 위한 DTO.

  • 필드:

    • tradeId: 거래 ID.
    • stockSymbol: 주식 심볼.
    • tradeType: 거래 유형.
    • price: 거래 단가.
    • quantity: 거래 수량.
    • tradeDate: 거래 날짜.
  • fromEntity(StockRecord stockRecord) 메서드를 통해 엔티티에서 변환 가능.

1.3 Entity

  • StockRecord
    • 주식 거래 내역을 저장하는 엔티티.
    • 주요 필드:
      • member: 거래를 수행한 사용자.
      • symbol: 주식 심볼.
      • quantity: 거래 수량.
      • pricePerUnit: 단위당 가격.
      • tradeType: 거래 유형 (BUY/SELL).
      • tradeDate: 거래 날짜.
    • decreaseQuantity(int soldQuantity): 판매 시 수량 감소 메서드.

1.4 Enum

  • TradeType
    • 거래 유형을 정의하는 열거형.
    • :
      • BUY: 구매.
      • SELL: 판매.

1.5 Repository

  • StockRecordRepository
    • JPA를 사용하여 데이터베이스와의 상호작용 담당.
    • 주요 메서드:
      • findByAdvId(Long advId): 특정 AdvancedInvest ID의 거래 내역 조회.
      • findByAdvIdAndStockSymbol(Long advId, String stockSymbol): 특정 주식의 거래 내역 조회.
      • findByMemberIdAndSymbol(Long memberId, String symbol): 특정 사용자의 주식 거래 내역 조회.

1.6 Service

  • StockRecordService (인터페이스)

    • 거래 내역 저장, 조회 및 보유량 계산 기능 정의.
    • 주요 메서드:
      • saveRecord(StockRecordRequestDto requestDto, Member member): 거래 내역 저장.
      • getRecordsByAdvId(Long advId): 특정 AdvancedInvest ID의 거래 내역 조회.
      • getRecordsByStock(Long advId, String stockSymbol): 특정 주식의 거래 내역 조회.
      • calculateOwnedStock(Long advId, String stockSymbol): 특정 주식의 보유량 계산.
      • calculateAllOwnedStocks(Long advId): 모든 주식의 보유량 계산.
  • StockRecordServiceImpl

    • StockRecordService 구현체.
    • 주요 기능:
      • saveRecord: 거래 내역 저장. DTO를 엔티티로 변환 후 데이터베이스에 저장.
      • getRecordsByAdvId: AdvancedInvest ID로 거래 내역 조회.
      • getRecordsByStock: 주식 심볼로 특정 거래 내역 조회.
      • calculateOwnedStock: 구매 및 판매 수량을 계산하여 최종 보유량 반환.
      • calculateAllOwnedStocks: Map 형태로 모든 주식의 보유량 반환.

핵심 요약

  • 구매와 판매 관리:
    • 모든 구매 및 판매 기록은 StockRecord 엔티티에 저장.
    • DTO를 통해 요청을 처리하며, 보유량 및 거래 내역을 정확히 계산.
  • HTTP API:
    • 거래 내역 저장, 조회, 보유량 계산 기능을 제공.
    • WebSocket과 함께 사용 가능. WebSocket은 실시간 데이터 전송에 적합, HTTP는 특정 데이터 조회나 상태 점검에 적합.

AdvancedInvest


1. 핵심 WebSocket 구성

1.1 WebSocketHandler

  • AdvancedInvestWebSocketHandler
    • WebSocket 핸들러로 클라이언트와의 실시간 통신을 관리.
    • 주요 처리:
      • 액션 처리: START_GAME, PAUSE_GAME, RESUME_GAME, END_GAME, BUY_STOCK, SELL_STOCK, GET_REMAINING_TIME와 같은 요청을 처리.
      • JSON 파싱: 메시지를 JSON 형태로 받아 DTO(WebSocketRequestDto)로 변환 후 처리.
      • 서비스 호출: 요청에 따라 AdvancedInvestService의 메서드 호출.
      • 메시지 응답: WebSocket을 통해 성공/실패 메시지를 클라이언트로 전송.

1.2 WebSocketConfig

  • WebSocket을 활성화하고 핸들러를 등록.
  • 경로 설정: /ws/advanced-invest 경로로 WebSocket 연결을 설정.
  • SockJS 지원: 다양한 클라이언트 연결 방식을 지원.

1.3 WebSocketUtil

  • WebSocket 메시지 전송을 간소화하는 유틸리티.
  • 기능:
    • JSON 직렬화 및 메시지 전송을 처리.
    • WebSocketSession이 열려 있을 때만 동작.

2. 게임 상태 및 타이머 관리

2.1 AdvancedInvestService (인터페이스)

  • 게임의 상태 관리 및 주식 거래 기능 정의.
  • 주요 메서드:
    • 타이머 관리: startGameTimer, pauseGame, resumeGame, getRemainingTime.
    • 게임 상태: startGame, endGame, resetPlayedTodayStatus.
    • 주식 거래: buyStock, sellStock.

2.2 AdvancedInvestServiceImpl

  • 서비스 구현체로 실제 게임 로직 및 상태 관리 처리.
  • 주요 기능:
    • 게임 타이머:
      • startGameTimer: 게임 타이머를 시작하며, 각 단계(장전, 거래, 장후)에 맞는 데이터를 클라이언트로 전송.
      • pauseGame: 타이머를 멈추고 현재 초를 저장.
      • resumeGame: 저장된 초부터 타이머를 재개.
    • 게임 상태 관리:
      • startGame: AdvancedInvest 엔티티를 생성하고 타이머 시작.
      • endGame: 게임을 종료하고 WebSocket 연결을 닫음.
      • resetPlayedTodayStatus: 매일 오전 7시에 진행 중인 게임을 초기화.
    • 데이터 전송:
      • sendReferenceData, sendLiveData, sendEndSignal 메서드를 통해 데이터를 WebSocket으로 전송.
    • 주식 거래:
      • buyStock, sellStock: 주식 구매/판매 로직 처리.

3. DTO

3.1 WebSocketRequestDto

  • WebSocket 요청을 처리하기 위한 DTO.
  • 필드:
    • action: 요청 액션 (START_GAME, BUY_STOCK 등).
    • advId: AdvancedInvest ID.
    • stockSymbol: 주식 심볼.
    • quantity: 거래 수량.
    • points: 거래 금액.
    • memberId: 사용자 ID.

3.2 StockTransactionRequestDto

  • 주식 거래 요청을 처리하기 위한 DTO.
  • 필드:
    • stockSymbol: 주식 심볼.
    • quantity: 거래 수량.
    • points: 거래 금액.
    • memberId: 사용자 ID.
    • tradeType: 거래 유형 (BUY/SELL).

4. 엔티티 및 저장소

4.1 AdvancedInvest

  • 게임 상태를 저장하는 엔티티.
  • 필드:
    • member: 게임을 시작한 사용자.
    • startTime: 게임 시작 시간.
    • paused: 게임 일시정지 여부.
    • currentSecond: 현재 진행 시간 (초 단위).
    • playedToday: 당일 게임 진행 여부.
    • stockRecords: 관련 주식 거래 내역.

4.2 AdvancedInvestRepository

  • JPA를 사용해 데이터베이스와 상호작용.
  • 주요 메서드:
    • findByMemberIdAndPlayedTodayTrue: 당일 게임을 실행한 사용자 조회.
    • resetPlayedToday: 모든 게임의 playedToday 상태 초기화.
    • findAllByPausedTrue: 정지 상태의 게임 조회.

5. 핵심 기능 요약

  • WebSocket 기반 실시간 처리:
    • 게임 진행, 주식 거래, 상태 조회 등 모든 주요 기능을 WebSocket을 통해 처리.
  • 게임 타이머 관리:
    • 타이머를 통한 단계적 데이터 전송 및 상태 관리.
  • AdvancedInvest 상태 활용:
    • 게임의 시작, 정지, 재개, 종료를 효율적으로 처리.


🔍 테스트 결과

WebSocket 사용으로 실제 테스트는 프론트가 만들어져야 가능
WebSocket 을 제외한 기능들은 테스트 완료
서버 실행 자체에도 오류 없음. WebSocket 을 통한 서비스들이 어떻게 진행되는지는 프론트 만들면 바로 해보겠습니다


🎈 변경 사항 체크리스트

  • 코드에 영향이 있는 모든 부분에 대한 테스트를 작성하고 실행했나요?
  • 문서를 작성하거나 수정했나요? (필요한 경우)
  • 코드 컨벤션에 따라 코드를 작성했나요?
  • 본 PR에서 발생할 수 있는 모든 의존성 문제가 해결되었나요?

✨ 피드백 반영사항

피드백 받은 내용이 있으면 작성해주세요.


💬 리뷰 요구사항

생각보다 코드가 많지 않았네요? 그냥 구현하면서 힘들어서 그렇게 보인거 같아요 ㅋㅋㅋㅋㅋㅋㅋ 편안하게 봐주시면 되겠습니다.


Advanced Invest, 즉 게임 시스템 구현이 완료되었습니다. 현재 Stock Record 구현이 완료 되지 않아 오류가 생깁니다. 이는 곧 구현 완료 할 예정입니다

related to: #27
StockRecord 기능을 구현하면서 AdvancedInvest 쪽 기능까지 완전히 구현 완료 하였습니다.

related to: #27
몇몇 버그를 픽스 했습니다

close: #27
WebSocket 구현이 완료되었습니다. WebSocket 설정 뿐만이 아니라 실질적인 게임의 모든 기능이 이제 Service 에서 진행됩니다

related to: #51
주식의 구매와 판매 관련하여 handler 구현이 정상적으로 완료되지 않아 수정하였습니다

related to: #51
게임 종료시 WebSocket Session 이 종료되지 않고 영원히 유지되는 이상한 일이 일어나서 이를 고쳤습니다.

close: #51
StockRecord Repository 에서 활용되는 advId 가 제대로 매핑이 되지 않아 생기는 오류를 수정하였습니다

related to: #51
@Preta3418 Preta3418 added the ✨ Feature 기능 개발 label Nov 27, 2024
@Preta3418 Preta3418 self-assigned this Nov 27, 2024
@Preta3418 Preta3418 requested a review from deveunhwa November 27, 2024 12:01
Copy link
Collaborator

@deveunhwa deveunhwa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다!

간단한 URI 변경 입니다. 테스트용으로 만들었던걸 그대로 쓰고 있는걸 확인하여 컨베션에 맞게 변경하였습니다

related to: #51
stock 수치를 보낼때 쓰지 않는 수치들이 상당히 많이 존재하여 AdvStockResponseDto 를 다시 사용하기 시작했습니다

related to: #51
주식 수량을 정하는 quantity 필드가 int 로 되어 있던것을 double 로 변경하였습니다.

related to: #51
stockRecord 내부에서 advId 를 받아 조회하면 특정 게임의 내역만 조회가 되어 memberId 로 수정하였습니다

related to: #51
전 refactoring 과 같은 이유로, advId 로 조회하는 주식을 전부 memberId 로 추가적으로 변환하였습니다

related to: #51
@Preta3418 Preta3418 merged commit 9d969c0 into develop Nov 28, 2024
@Preta3418 Preta3418 deleted the feature/adv-stock/SCRUM-51 branch November 28, 2024 02:46
@@ -0,0 +1,80 @@
package com.prgrms.ijuju.domain.stock.adv.advancedinvest.controller;

/**
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR에는 사용되는 코드를 올리셔야 합니다.


@Service
@RequiredArgsConstructor
public class AdvancedInvestServiceImpl implements AdvancedInvestService {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전반적으로 비즈니스 로직이 조금 방대하게 있는 편이어서

  • 도메인
  • 서비스
    쪽으로 로직을 던져보면 좋을 것 같습니다.

단, 서비스는 순환 참조가 발생하지 않도록 막아야 합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ Feature 기능 개발
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants