# CLAUDE.md ## Project Overview ANTOOZA(개미투자) - Clean Architecture 기반 커머스·커뮤니티 플랫폼 (.NET 10.0) - **Framework**: .NET 10.0, ASP.NET Core - **CQRS**: 사내 디스패처 (ISender/IMediator) — 2026-07 MediatR 제거 (라이선스 회피, 순수 C#) - **ORM**: Entity Framework Core 10.0 (SQL Server) - **Cache**: StackExchange.Redis 10.0 - **Logging**: Serilog 10.0 ## Solution Structure ``` Admin/ → Razor Pages 관리자 패널 (https://localhost:5000) Web.Api/ → RESTful Minimal API (https://localhost:4000) Application/ → CQRS Handler (사내 디스패처) └── Features/ ├── Api/ → Auth(+Social), Banner, Channel(비활성), Chat, Document, Faq, Forum, Member, MyPage, Note, Notification, Payment, Popup, Stocks, Store, Studio(비활성) └── Admin/ → Banner, Cache, Channel, Document, Faq, Forum, Member, MemberGrade, Payment, Popup, ReferenceData, Store Domain/ → Entity, ValueObject └── Entities/ ├── Common/ → Config, Document, etc. ├── Members/ → Member, Channel(비활성), RefreshToken, MemberOAuthToken ├── Wallets/ → Wallet, WalletBalance(rowversion), WalletTransaction ├── Stocks/ → Stock, StockDailyPrice, MarketHoliday (M1 신규) ├── Chat/ → ChatRoomConfig, ChatBan (룸 기반 채팅) ├── Store/ → Product, Order, CouponCode, GameSettlement 등 ├── Notes/ → Note (쪽지) ├── Notifications/ → Notification (알림) ├── Payments/ → PaymentOrder, Toss(Confirm/Cancel/Log), PaymentReconcileLog └── Forum/ → Board, Post, Comment Infrastructure/ → DB, Auth, Storage, Email ├── Authentication/ → JWT, Identity, GoogleOAuth, NaverAuthProvider, KakaoAuthProvider ├── Cache/ → Redis ├── Hubs/ → AppHub (전역 실시간 — 알림/쪽지) ├── Chat/ → Redis 메시지 스토어/접속 추적 (ChatHub 는 Web.Api/Hubs) ├── Notification/ → NotificationService (쪽지/알림 발송) ├── StockData/ → 금융위(data.go.kr) 종목마스터·일별시세 수집 배치 (M1 신규) ├── YouTube/ → [비활성 — Features:Channel 플래그] YouTubeApiService, PubSub, LiveChat ├── Payment/ → TossPaymentService (PG 결제) ├── Forum/ → 게시판 비즈니스 로직 ├── Messaging/ → Email (SMTP, MimeKit) ├── Persistence/ → AppDbContext, IdentityDbContext, Migrations ├── Storage/ → 파일 업로드 └── Extensions/ → 확장 메서드 SharedKernel/ → AppSettings, Result Pattern Database/ → SQL 배포 스크립트 (deploy-app.sql, deploy-identity.sql, deploy-missing.sql) Tests/ → Application.Tests (MSTest + LocalDB antooza_test — 결제/지갑/채팅/종목/소셜) ``` > 제거된 도메인(2026-07-03 Phase B): Donation/Settlement/Crew/Developers(공개 v1 API) — 전부 삭제됨. Channel/YouTube 는 `Features:Channel` 플래그로 비활성(코드 보존). ## API Endpoints (Web.Api/Endpoints/) Auth(social-login/disconnect 포함), Banner, Channel(플래그 게이트), Chat, Config, Document, Faq, Forum, MyPage, Note, Notification, Payment, Popup, Stocks, Store, Studio(플래그 게이트), Wallet, YouTube(플래그 게이트) ## Code Style Rules - PK/ID 변수명: `memberID`, `userID` (camelCase + 대문자 ID) - if 문은 반드시 `{}` 사용 - Tuple 속성은 각 필드를 별도 줄에 작성 - 외부 라이브러리 대신 순수 C# 우선 (FluentValidation 등 사용 안 함) - 배열 패턴 사용 (체이닝 `||` 대신) - Handler에서 직접 유효성 검사 (Data Annotation 사용 안 함) - 파일 내용의 마지막 줄 제거 - EF Core 문은 항상 한 줄로 작성(단, 객체나 data 사용 시 여러 줄로 표시) ## Architecture Rules - Domain layer has ZERO external dependencies - Application layer defines interfaces, Infrastructure implements them - All database access goes through EF Core DbContext (no repository pattern) - Use the in-house ISender/IMediator dispatcher for all command/query handling (MediatR removed) - API layer is thin — endpoint definitions only ## Code Conventions ### Patterns We Use - Primary constructors for DI - Records for DTOs and commands - Result pattern for error handling (no exceptions for flow control) - File-scoped namespaces - Always pass CancellationToken to async methods (단, StackExchange.Redis 등 CancellationToken을 지원하지 않는 라이브러리는 예외) ### Patterns We DON'T Use (Never Suggest) - Repository pattern (use EF Core directly) - AutoMapper (write explicit mappings) - Exceptions for business logic errors - Stored procedures ## Architecture - CQRS: 사내 ISender/IMediator 디스패처 (Command/Query → Handler), 구현 `Application/Messaging/Sender.cs` - Auth: API는 Member 엔티티 + PBKDF2 해싱, Admin은 ASP.NET Identity - DB: SQL Server (AppDbContext + IdentityDbContext) - Cache: Redis (StackExchange.Redis) - Real-time: SignalR WebSocket - AppHub (`/hubs/app`) — 전역 (접속자 추적, 알림, 쪽지) - ChatHub (`/hubs/chat`) — 룸 기반 채팅: `JoinRoom(roomKey)` = `main` | `stock:{code}` (게스트 읽기 허용, 전송은 인증) - YouTube: [비활성 — Features:Channel] YouTubeApiService, PubSubHubbub, LiveChatService - Payment: 토스페이먼츠(TossPayments) PG 결제 연동 (Confirm/Cancel + PaymentReconcileLog 대사, NeedsReconciliation 상태) - Social Login: Google + Naver/Kakao (`/api/auth/social-login`, 자동 계정연결 금지, disconnect 웹훅) - StockData: 금융위 T+1 시세·종목마스터 배치 (`StockData:Enabled` + ServiceKey 필요) - DI: 각 레이어별 DependencyInjection.cs - `AddApplication()` → 리플렉션 스캔으로 전체 Handler(Scoped) 등록 + `ISender`/`IMediator` 디스패처(`Sender`) 등록 - `AddApiInfrastructure()` → API 전용 (JWT Bearer + 모든 서비스) - `AddAdminInfrastructure()` → Admin 전용 (Identity + 모든 서비스) - `AddPresentation()` → Swagger, ExceptionHandler ## Build & Run ```bash # Solution build dotnet build Backend.slnx # API 실행 dotnet run --project Web.Api # Admin 실행 dotnet run --project Admin # Migration dotnet ef migrations add --project Infrastructure --startup-project Admin --context AppDbContext dotnet ef database update --project Infrastructure --startup-project Admin --context AppDbContext ``` ## Key Patterns - Result Pattern: `Result` / `Error` (SharedKernel/Results/) - ErrorType: Validation(400), Problem(400), Unauthorized(401), NotFound(404), Forbidden(403), Conflict(409), MethodNotAllowed(405) - Endpoint: `IEndpoint` 인터페이스 → `MapEndpoint()` 구현 - Feature 구조: `Application/Features/{Domain}/{Action}/Command.cs, Handler.cs, Response.cs` ## 사용 Domain - https://antooza.com -> 사용자 단 사용 URL - https://admin.antooza.com -> 관리자 단 사용 URL - https://api.antooza.com -> 사용자 단 통신 API URL > dev 서버도 위 운영 도메인 사용 — `dev-` 접두사 제거(2026-07-11). prod 서버는 추후 구축. ## Code Style Rules (추가) - C# 람다 `) => {` 한 줄에 붙여 작성 (개행 금지) - button 태그에 submit type이 아니면 `type="button"` 필수 - Endpoint 파일 = 1 class = 1 액션 (예: `Send.cs`, `History.cs`) - inline CSS 사용 금지 → SCSS 또는 Tailwind 사용 - BEM 네이밍: `block__element--modifier` - `migrationBuilder.Sql(...)` 내부 한글 문자열 리터럴은 반드시 `N'...'` 형식 사용 (non-Unicode 파싱으로 `??` 저장 방지) ## 용어 규칙 (개미투자 — d0-overview §2.2 확정) - **캐시**: 충전 재화 = WalletBalanceType `PgCharged + Deposit` (Toss PG 충전). **상점 구매 전용** (`SpendPolicy.StoreOrderSpendOrder` = 캐시만) - **토큰**: 활동 적립 재화 = `Reward + Airdrop` (가입/출석/글/댓글 보상 + 모의투자 운용). 기존 "코인"에서 최종 개명(2026-07-05). 상점 구매 불가 — 활동·모의투자 폐쇄 루프 - 후원/머니 개념은 Phase B 에서 제거됨. `Donation`/`StoreRevenue` enum 값은 원장 호환용으로만 보존(`[비활성]` 주석) ## Payment Gateway (토스페이먼츠 PG) - SDK: Toss V2 JS SDK (`@tosspayments/tosspayments-sdk`, Frontend) - Server: `Infrastructure/Payment/TossPaymentService.cs` (V2 REST — api.tosspayments.com) - 테이블: PaymentOrder → TossConfirm → TossCancel, TossLog (+ PaymentReconcileLog 대사) - 결제수단: Card, VirtualAccount, Mobile, Transfer, NaverPay, KakaoPay, Payco - Config: DB Config.External 에 TossPayMode(test/live) + Test/Live ClientKey·SecretKey 저장 (AES-GCM 암호화, `enc:v{n}:...` 포맷) - 라우트(Web.Api): POST `/api/payments/orders` · `/confirm` · `/cancel` (인증) · `/webhook` (Anonymous) ## Database Schema **AI 지시**: DB 테이블/컬럼/관계 관련 작업 시 먼저 아래 스키마 파일을 Read로 확인할 것. - [../docs/database/schema-local.md](../docs/database/schema-local.md) — 현행 (2026-07-04 갱신, Phase B 드랍+M1 신규 반영) - [../docs/database/schema-live.md](../docs/database/schema-live.md) — prod (⚠️ Phase B 마이그레이션 미적용 구스키마)