Skip to content

Commit f206915

Browse files
committed
docs: 실제 내용 적용
1 parent 41fb803 commit f206915

File tree

2 files changed

+28
-92
lines changed

2 files changed

+28
-92
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
## ✨ 핵심 기능
4747

4848
### 채팅 시스템
49-
- **이중 프로토콜**: WebSocket + HTTP REST API
50-
- **메시지 관리**: User/Assistant/System 역할 기반 대화
49+
- **HTTP-WebSocket Bridge**: 비동기 장기 실행 작업의 브리지 패턴
50+
- **ChatService 오케스트레이션**: Facade 패턴으로 복합 처리 파이프라인 관리
5151
- **외부 서비스 연동**: LLM, Memory, TTS 서비스 통합
5252
- **페이지네이션**: 대화 기록 조회
5353

@@ -58,7 +58,6 @@
5858
- **다중 헤더**: Authorization, X-Access-Credit, X-Refresh-Credit
5959

6060
### 크레딧 시스템
61-
- **정밀 계산**: Decimal(18,2) 잔액 관리
6261
- **거래 기록**: 완전한 audit trail
6362
- **동시성 제어**: Optimistic concurrency 지원
6463

docs/overview/features.md

Lines changed: 26 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -125,44 +125,42 @@ private async Task ProcessChatRequestInternalAsync(ChatProcessContext context)
125125
}
126126
```
127127

128-
### WebSocket 세션 관리: 실시간 결과 전송
128+
### 페이지네이션: 대화 기록 조회
129129

130-
**설명**: WebSocket을 통한 실시간 채팅 결과 전송 시스템. 클라이언트가 `/ws` 엔드포인트로 연결하면 채팅 처리 완료 시 결과를 자동으로 수신합니다.
130+
**설명**: 효율적인 대화 기록 조회를 위한 페이지네이션 시스템. 대용량 대화 기록을 페이지 단위로 나누어 조회하고 클라이언트에서 점진적으로 로드할 수 있습니다.
131131

132132
**구현 위치**:
133-
- **WebSocket 미들웨어**: [`ProjectVG.Api/Middleware/WebSocketMiddleware.cs`](../../ProjectVG.Api/Middleware/WebSocketMiddleware.cs)
134-
- **WebSocket 매니저**: [`ProjectVG.Application/Services/WebSocket/WebSocketManager.cs`](../../ProjectVG.Application/Services/WebSocket/WebSocketManager.cs)
135-
- **연결 관리**: [`ProjectVG.Infrastructure/Realtime/WebSocketConnection/WebSocketClientConnection.cs`](../../ProjectVG.Infrastructure/Realtime/WebSocketConnection/WebSocketClientConnection.cs)
133+
- **대화 컨트롤러**: [`ProjectVG.Api/Controllers/ConversationController.cs`](../../ProjectVG.Api/Controllers/ConversationController.cs)
134+
- **대화 서비스**: [`ProjectVG.Application/Services/Conversation/ConversationService.cs`](../../ProjectVG.Application/Services/Conversation/ConversationService.cs)
135+
- **대화 리포지토리**: [`ProjectVG.Infrastructure/Persistence/Repositories/Conversation/SqlServerConversationRepository.cs`](../../ProjectVG.Infrastructure/Persistence/Repositories/Conversation/SqlServerConversationRepository.cs)
136136

137137
**핵심 코드**:
138138
```csharp
139-
// WebSocket 연결 처리 (미들웨어)
140-
if (context.Request.Path == "/ws" && context.WebSockets.IsWebSocketRequest)
139+
// 페이지네이션 조회 (컨트롤러)
140+
[HttpGet("{characterId}")]
141+
[JwtAuthentication]
142+
public async Task<ActionResult<ConversationHistoryResponse>> GetConversationHistory(
143+
Guid characterId,
144+
[FromQuery] int page = 1,
145+
[FromQuery] int pageSize = 10)
141146
{
142-
var webSocket = await context.WebSockets.AcceptWebSocketAsync();
143-
var userId = await AuthenticateWebSocketAsync(context);
147+
var userId = GetCurrentUserId();
148+
var history = await _conversationService.GetConversationHistoryAsync(
149+
userId.Value, characterId, page, pageSize);
144150

145-
if (userId.HasValue)
146-
{
147-
await _webSocketManager.AddConnectionAsync(userId.Value, webSocket);
148-
await HandleWebSocketCommunication(webSocket, userId.Value);
149-
}
151+
return Ok(history);
150152
}
151153

152-
// 채팅 결과 WebSocket으로 전송
153-
public async Task SendChatResultAsync(Guid userId, ChatResult result)
154+
// 데이터베이스 페이지네이션 (리포지토리)
155+
public async Task<IEnumerable<ConversationHistory>> GetConversationHistoryAsync(
156+
Guid userId, Guid characterId, int page, int pageSize)
154157
{
155-
var connection = _connections.GetValueOrDefault(userId);
156-
if (connection != null)
157-
{
158-
var message = JsonSerializer.Serialize(new WebSocketMessage
159-
{
160-
Type = "chat_result",
161-
Data = result
162-
});
163-
164-
await connection.SendAsync(message);
165-
}
158+
return await _context.ConversationHistories
159+
.Where(ch => ch.UserId == userId && ch.CharacterId == characterId)
160+
.OrderByDescending(ch => ch.Timestamp)
161+
.Skip((page - 1) * pageSize)
162+
.Take(pageSize)
163+
.ToListAsync();
166164
}
167165
```
168166

@@ -292,51 +290,6 @@ private string? ExtractToken(HttpRequest request)
292290

293291
## 3. 크레딧 시스템
294292

295-
### 정밀 계산: Decimal(18,2) 잔액 관리
296-
297-
**설명**: 금융급 정밀도의 Decimal(18,2) 타입을 사용한 크레딧 잔액 관리
298-
299-
**구현 위치**:
300-
- **사용자 엔티티**: [`ProjectVG.Domain/Entities/User/User.cs`](../../ProjectVG.Domain/Entities/User/User.cs)
301-
- **크레딧 거래 엔티티**: [`ProjectVG.Domain/Entities/Credit/CreditTransaction.cs`](../../ProjectVG.Domain/Entities/Credit/CreditTransaction.cs)
302-
- **크레딧 서비스**: [`ProjectVG.Application/Services/Credit/CreditService.cs`](../../ProjectVG.Application/Services/Credit/CreditService.cs)
303-
304-
**핵심 코드**:
305-
```csharp
306-
// 사용자 엔티티의 크레딧 필드
307-
[Precision(18, 2)]
308-
public decimal CreditBalance { get; set; } = 0;
309-
310-
[Precision(18, 2)]
311-
public decimal TotalCreditsEarned { get; set; } = 0;
312-
313-
[Precision(18, 2)]
314-
public decimal TotalCreditsSpent { get; set; } = 0;
315-
316-
// 크레딧 거래 엔티티
317-
public class CreditTransaction : BaseEntity
318-
{
319-
[Precision(18, 2)]
320-
public decimal Amount { get; set; }
321-
322-
[Precision(18, 2)]
323-
public decimal BalanceAfter { get; set; }
324-
325-
public CreditTransactionType Type { get; set; } // Earn = 1, Spend = 2
326-
}
327-
328-
// 크레딧 계산 로직
329-
public async Task<decimal> AddCreditsAsync(Guid userId, decimal amount, string source, string description)
330-
{
331-
var user = await _userRepository.GetByIdAsync(userId);
332-
var newBalance = user.CreditBalance + amount;
333-
334-
user.CreditBalance = newBalance;
335-
user.TotalCreditsEarned += amount;
336-
337-
return newBalance;
338-
}
339-
```
340293

341294
### 거래 기록: 완전한 audit trail
342295

@@ -548,15 +501,6 @@ public bool CanBeViewedBy(Guid? userId)
548501
return userId.HasValue && IsOwnedBy(userId.Value);
549502
}
550503

551-
// 편집 권한 확인
552-
public bool CanBeEditedBy(Guid? userId)
553-
{
554-
// 시스템 캐릭터는 편집 불가
555-
if (IsSystemCharacter()) return false;
556-
557-
// 소유자만 편집 가능
558-
return userId.HasValue && IsOwnedBy(userId.Value);
559-
}
560504
```
561505

562506
### 프롬프트 생성: 설정 기반 SystemPrompt 구성
@@ -601,11 +545,4 @@ public string BuildSystemPrompt()
601545
}
602546
```
603547

604-
---
605-
606-
## 📚 추가 리소스
607-
608-
- **API 문서**: [README.md](../../README.md)
609-
- **아키텍처 가이드**: [CLAUDE.md](../../CLAUDE.md)
610-
- **개발 환경 설정**: [scripts/](../../scripts/) 디렉토리
611-
- **테스트 가이드**: [ProjectVG.Tests/](../../ProjectVG.Tests/) 디렉토리
548+
<br>

0 commit comments

Comments
 (0)