Conversation
Walkthrough베팅 컴포넌트를 Changes
Sequence Diagram(s)sequenceDiagram
participant User as 사용자
participant UI as Betting.jsx
participant API as /api/user-bets
participant Hist as bettingHistory.js / BettingHistory.jsx
rect rgb(240,249,255)
User->>UI: 베팅 버튼 클릭 (RISE/FALL)
activate UI
UI->>API: POST /api/user-bets (async)
activate API
API-->>UI: 응답 (성공 / 409 / 오류)
deactivate API
UI->>UI: userBets 업데이트, 에러/알림 처리
UI-->>User: 상태/알림 표시
deactivate UI
end
rect rgb(255,247,240)
User->>UI: 히스토리 조회 (period)
UI->>Hist: getDailyBetHistory / getWeeklyBetHistory
activate Hist
Hist-->>UI: 필터된 히스토리 (roundTitle.includes)
deactivate Hist
UI-->>User: BettingHistory 렌더링 (earnedPoints, resultOption 등)
end
rect rgb(247,255,240)
User->>UI: 베팅 취소 요청
activate UI
UI->>API: DELETE /api/user-bets/{userBetId}
activate API
API-->>UI: 삭제 응답
deactivate API
UI->>UI: userBets 동기화
UI-->>User: 취소 결과 표시
deactivate UI
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🔇 Additional comments (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/components/stockgame/BettingHistory.jsx (1)
57-59: 0으로 나누기 예외 처리 누락
prev(이전 가격)가 0일 경우Infinity또는NaN이 반환되어 UI에 잘못된 값이 표시될 수 있습니다.다음과 같이 수정하세요:
const getPercentChange = (prev, next) => { + if (prev === 0) return '0.00'; return (((next - prev) / prev) * 100).toFixed(2); };
🧹 Nitpick comments (1)
frontend/src/components/stockgame/BettingHistory.jsx (1)
102-106: 데이터 필드 존재 여부 확인 권장
item.upBetCount와item.downBetCount에 접근할 때 해당 필드가 존재하지 않으면undefined가 표시될 수 있습니다. 백엔드 API가 항상 이 필드를 반환한다고 보장되면 문제없지만, 방어적 코딩을 위해 기본값 처리를 권장합니다.다음과 같이 수정하는 것을 고려하세요:
<span> {item.resultOption === 'RISE' - ? item.upBetCount - : item.downBetCount} + ? (item.upBetCount ?? 0) + : (item.downBetCount ?? 0)} 명 </span>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
frontend/src/components/Header.module.css(2 hunks)frontend/src/components/stockgame/Betting.jsx(4 hunks)frontend/src/components/stockgame/BettingHistory.jsx(2 hunks)frontend/src/components/stockgame/BettingHistory.module.css(1 hunks)frontend/src/utils/bettingHistory.js(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
frontend/src/components/stockgame/Betting.jsx (2)
frontend/src/utils/bettingHistory.js (7)
data(14-14)data(20-20)res(5-5)getDailyBetHistory(13-17)getDailyBetHistory(13-17)getWeeklyBetHistory(19-23)getWeeklyBetHistory(19-23)frontend/src/utils/bettingInfo.js (6)
res(5-5)res(15-15)dailyBet(3-11)dailyBet(3-11)weeklyBet(13-21)weeklyBet(13-21)
frontend/src/components/stockgame/BettingHistory.jsx (1)
frontend/src/components/stockgame/StockInfoItem.jsx (1)
StockInfoItem(3-10)
frontend/src/utils/bettingHistory.js (2)
frontend/src/components/stockgame/Betting.jsx (1)
data(14-14)frontend/src/components/stockgame/BettingHistory.jsx (1)
data(12-12)
🔇 Additional comments (7)
frontend/src/components/Header.module.css (2)
15-15: 깔끔한 코드 포맷팅 ✓스타일 블록 사이의 공백 추가로 가독성을 개선했습니다.
41-41: 반응형 레이아웃 개선 - 좋은 CSS 수정
.menuButton에flex-shrink: 0을 추가하여 고정 크기(22px × 16px)를 유지하도록 하고,.menuButton span에width: 100%를 적용하여 라인들이 버튼 전체 너비를 일관되게 채우도록 개선했습니다. 이는 베팅 UI 통합에 따른 레이아웃 변경에서 헤더 버튼의 반응형 동작을 안정화하는 좋은 개선입니다.Also applies to: 46-46
frontend/src/components/stockgame/BettingHistory.module.css (1)
132-133: 페이지네이션 중앙 정렬 변경 승인페이지네이션을 중앙 정렬로 변경한 것은 적절한 UI 개선입니다.
frontend/src/components/stockgame/Betting.jsx (2)
53-58: 하드코딩된 베팅 파라미터 확인 필요
stakePoints: 0과isFree: true가 하드코딩되어 있습니다. 향후 유료 베팅이나 포인트 베팅 기능을 추가할 계획이 있다면 이를 props나 state로 관리하는 것이 좋습니다.현재 요구사항에서 모든 베팅이 무료이고 포인트가 0인 것이 맞는지 확인해주세요. 향후 확장 가능성이 있다면 다음과 같이 리팩토링을 고려하세요:
const onClickUpBet = async (stakePoints = 0, isFree = true) => { // ... const res = await api.post('/api/user-bets', { roundId: data.betRoundId, option: 'RISE', stakePoints, isFree, }); // ... };
35-46: 베팅 상태 동기화 로직 승인
data와userBets의 변경을 감지하여 베팅 상태를 자동으로 동기화하는 로직이 잘 구현되었습니다. null 체크와 betRoundId 비교를 통해 안전하게 처리하고 있습니다.frontend/src/components/stockgame/BettingHistory.jsx (2)
72-78: 데이터 구조 변경 반영 완료
item.collect에서item.correct로의 변경과 결과 아이콘 렌더링이 올바르게 구현되었습니다.
79-93: API 응답 데이터 구조 변경 반영 완료중첩된
item.round.*구조에서 플랫한item.*구조로 변경이 잘 적용되었습니다.roundTitle,symbol,settleClosePrice,previousClosePrice필드가 올바르게 사용되고 있습니다.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (5)
frontend/src/utils/bettingHistory.js (2)
17-17: 문자열 부분 매칭 방식의 필터링 개선 필요
includes('DAILY')는 "DAILY"가 포함된 모든 문자열과 매칭됩니다. 예를 들어 "MY_DAILY_SPECIAL" 같은 roundTitle도 잘못 매칭될 수 있습니다.이전 리뷰에서 제안한 대로 다음과 같이 수정하는 것을 권장합니다:
- return data.filter((item) => item.roundTitle.includes('DAILY')); + return data.filter((item) => item.roundTitle === 'DAILY' || item.roundTitle.startsWith('DAILY_'));
23-23: 문자열 부분 매칭 방식의 필터링 개선 필요Line 17과 동일한 이슈입니다.
includes('WEEKLY')는 "WEEKLY"가 포함된 모든 문자열과 매칭되므로 더 정확한 매칭 방식이 필요합니다.다음과 같이 수정하는 것을 권장합니다:
- return data.filter((item) => item.roundTitle.includes('WEEKLY')); + return data.filter((item) => item.roundTitle === 'WEEKLY' || item.roundTitle.startsWith('WEEKLY_'));frontend/src/components/stockgame/Betting.jsx (3)
59-83: Axios 에러 객체 접근 방식을 수정해야 합니다.Line 75에서
error.status로 접근하고 있지만, Axios는 HTTP 상태 코드를error.response.status에 저장합니다. 현재 코드는 409 에러를 제대로 감지하지 못합니다.다음과 같이 수정하세요:
} catch (error) { // 409 처리 - if (error.status === 409) { + if (error.response?.status === 409) { alert('베팅 가능 시간이 아닙니다.'); return; } alert('오류가 발생했습니다. 다시 시도해주세요.'); return null; }
85-109: Axios 에러 객체 접근 방식을 수정해야 합니다.Line 101에서 Line 75와 동일한 문제가 있습니다.
error.status대신error.response?.status를 사용해야 합니다.다음과 같이 수정하세요:
} catch (error) { // 409 처리 - if (error.status === 409) { + if (error.response?.status === 409) { alert('베팅 가능 시간이 아닙니다.'); return; } alert('오류가 발생했습니다. 다시 시도해주세요.'); return null; }
111-121: 사용자에게 원시 에러 메시지 노출을 피하세요.Line 118에서
error.message를 직접 표시하고 있습니다. 이는 기술적인 세부사항을 노출하여 사용자 경험을 해칠 수 있습니다.다음과 같이 수정하는 것을 권장합니다:
} catch (error) { - alert(error.message); + console.error(error); + alert('베팅 취소 중 오류가 발생했습니다. 다시 시도해주세요.'); }
🧹 Nitpick comments (2)
frontend/src/utils/bettingHistory.js (1)
6-7: 원본 배열 변경을 피하기 위해 비파괴적 방식 사용을 권장합니다.
reverse()는 원본 배열을 변경(mutate)합니다.res.data가 다른 곳에서도 참조될 가능성이 있다면 예상치 못한 부작용이 발생할 수 있습니다.다음과 같이 수정하는 것을 권장합니다:
- // 최신순으로 정렬 - return res.data.reverse(); + // 최신순으로 정렬 + return [...res.data].reverse();또는 React 19를 사용 중이므로
toReversed()를 사용할 수도 있습니다:- return res.data.reverse(); + return res.data.toReversed();frontend/src/components/stockgame/Betting.jsx (1)
59-109: 상승/하락 베팅 핸들러의 코드 중복을 제거하는 것을 고려하세요.
onClickUpBet과onClickDownBet은 거의 동일한 로직을 가지고 있으며,option값과 메시지만 다릅니다. 공통 함수로 리팩토링하면 유지보수성이 향상됩니다.다음과 같이 리팩토링할 수 있습니다:
const handleBet = async (option, direction) => { if (isBetting !== 'none') { alert('이미 베팅하셨습니다.'); } else if (confirm(`${direction}에 베팅하시겠습니까?`)) { try { const res = await api.post('/api/user-bets', { roundId: data.betRoundId, option, stakePoints: 0, isFree: true, }); await update(); alert('베팅이 완료되었습니다.'); return res; } catch (error) { if (error.response?.status === 409) { alert('베팅 가능 시간이 아닙니다.'); return; } alert('오류가 발생했습니다. 다시 시도해주세요.'); return null; } } }; const onClickUpBet = () => handleBet('RISE', '상승'); const onClickDownBet = () => handleBet('FALL', '하락');
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
frontend/src/components/stockgame/Betting.jsx(4 hunks)frontend/src/utils/bettingHistory.js(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
frontend/src/components/stockgame/Betting.jsx (3)
frontend/src/utils/bettingHistory.js (7)
data(15-15)data(21-21)res(5-5)getDailyBetHistory(14-18)getDailyBetHistory(14-18)getWeeklyBetHistory(20-24)getWeeklyBetHistory(20-24)frontend/src/components/stockgame/BettingHistory.jsx (2)
data(12-12)error(15-15)frontend/src/utils/bettingInfo.js (6)
res(5-5)res(15-15)dailyBet(3-11)dailyBet(3-11)weeklyBet(13-21)weeklyBet(13-21)
frontend/src/utils/bettingHistory.js (1)
frontend/src/utils/bettingInfo.js (2)
res(5-5)res(15-15)
🔇 Additional comments (3)
frontend/src/components/stockgame/Betting.jsx (3)
22-23: 배열 안전성 검사가 올바르게 추가되었습니다.이전 리뷰에서 지적된 배열 접근 시 안전성 문제가 적절히 해결되었습니다.
history && history.length > 0조건으로 빈 배열 접근을 방지하고 있습니다.Also applies to: 27-28
34-46: 베팅 상태 동기화 로직이 잘 구현되었습니다.
data와userBets의 변경을 감지하여isBetting상태를 동기화하는 로직이 명확하게 구현되었습니다. null 체크와betRoundId비교를 통해 현재 라운드의 베팅 여부를 정확히 판단하고 있습니다.
48-57: 데이터 갱신 로직을 별도 함수로 분리한 것이 좋은 개선입니다.
update()함수로 데이터와 베팅 히스토리 갱신 로직을 중앙화하여 코드 중복을 제거했습니다. 이전 리뷰에서 요청한 데이터 동기화 문제도 해결되었습니다.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
frontend/src/utils/bettingHistory.js (2)
17-17: 문자열 부분 매칭과 null 안전성 문제이전 리뷰에서 지적된
.includes('DAILY')사용 이슈가 여전히 해결되지 않았습니다. 또한item.roundTitle이null또는undefined일 경우 런타임 에러가 발생할 수 있습니다.다음과 같이 수정하여 두 문제를 모두 해결하세요:
- return data.filter((item) => item.roundTitle.includes('DAILY')); + return data.filter((item) => item.roundTitle?.startsWith('DAILY_') || item.roundTitle === 'DAILY');
23-23: 문자열 부분 매칭과 null 안전성 문제Line 17과 동일한 이슈입니다. 이전 리뷰에서 지적된
.includes('WEEKLY')사용 이슈가 여전히 해결되지 않았으며,item.roundTitle에 대한 null 체크도 누락되었습니다.다음과 같이 수정하세요:
- return data.filter((item) => item.roundTitle.includes('WEEKLY')); + return data.filter((item) => item.roundTitle?.startsWith('WEEKLY_') || item.roundTitle === 'WEEKLY');
1) 작업한 이슈번호
SISC1-30
2) 변경 요약 (What & Why)
3) 스크린샷/동영상 (UI 변경 시)
4) 상세 변경사항 (전부 다)
5) 참고사항
베팅 가능 기간이 아닌 경우에 베팅 시 409 에러를 받아 베팅 기간이 아니라는 알림 출력 예정
Summary by CodeRabbit
New Features
Style
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.