TreeNut-KR / ChatBot

ChatBot 웹사이트 프로젝트
GNU General Public License v3.0
1 stars 0 forks source link

chatroom 기능 구현 계획 #28

Open CutTheWire opened 1 week ago

CutTheWire commented 1 week ago

chatbot(캐릭터 채팅) & office(GPT)의 채팅 생성 방식 설명

도메인은 nono.me라고 가정

CutTheWire commented 1 week ago

기본 설계 방식

  1. JWT 토큰 기반 인증 미들웨어: TokenAuth.kt 파일에서 JWT 토큰을 처리하여 사용자의 user_id를 추출하는 미들웨어를 사용. 이 미들웨어는 각 요청에 대해 유저를 인증하고 user_id를 제공하여 MongoDB 관련 기능과 통합할 수 있도록 처리.

  2. 라우팅 및 URL 구조:

    • Chatbot
      • nono.me/chatroom/c/캐릭터 고유번호 페이지에서 유저가 채팅을 입력하면 FastAPI 서버에 해당 데이터를 전송하여 MongoDB에 chatbot_log_{user_id} 컬렉션을 생성.
      • nono.me/chatroom/c/캐릭터 고유번호/u/채팅방 고유번호 페이지에서 해당 채팅방 데이터를 로드.
    • Office (GPT)
      • nono.me/chatroom/o/gpt 페이지에서 채팅을 입력하면 FastAPI 서버에 해당 데이터를 전송하여 MongoDB에 office_log_{user_id} 컬렉션을 생성.
      • nono.me/chatroom/o/gpt/u/채팅방 고유번호 페이지에서 해당 채팅방 데이터를 로드.

Spring Boot 구성 제안

  1. 컨트롤러 (Controller) 구성

    • Spring Boot에서 사용자가 해당 URL에 접근할 때 필요한 요청을 처리하는 컨트롤러를 정의.
    • FastAPI 서버에 필요한 데이터를 전달하고, MongoDB에서 채팅 방 정보를 가져오거나 업데이트하는 역할을 담당.
    @RestController
    @RequestMapping("/server/chatroom")
    class ChatController(private val tokenAuth: TokenAuth) {
    
       // 채팅방 생성 (Chatbot)
       @PostMapping("/c/{characterId}")
       fun createChatbotRoom(
           @RequestHeader("Authorization") token: String,
           @PathVariable characterId: String
       ): ResponseEntity<String> {
           val userId = tokenAuth.authGuard(token)
           // FastAPI 서버로 채팅방 생성 요청을 보내는 로직
           // ...
           return ResponseEntity.ok("chatroom created with characterId: $characterId")
       }
    
       // 채팅방 생성 (Office GPT)
       @PostMapping("/o/gpt")
       fun createGptRoom(@RequestHeader("Authorization") token: String): ResponseEntity<String> {
           val userId = tokenAuth.authGuard(token)
           // FastAPI 서버로 GPT 채팅방 생성 요청을 보내는 로직
           // ...
           return ResponseEntity.ok("GPT chatroom created")
       }
    
       // 채팅 로드 (Chatbot)
       @GetMapping("/c/{characterId}/u/{chatroomId}")
       fun getChatbotLog(
           @RequestHeader("Authorization") token: String,
           @PathVariable characterId: String,
           @PathVariable chatroomId: String
       ): ResponseEntity<String> {
           val userId = tokenAuth.authGuard(token)
           // FastAPI 서버로부터 MongoDB에서 데이터를 받아오는 로직
           // ...
           return ResponseEntity.ok("chat logs for chatbot")
       }
    
       // 채팅 로드 (Office GPT)
       @GetMapping("/o/gpt/u/{chatroomId}")
       fun getGptLog(
           @RequestHeader("Authorization") token: String,
           @PathVariable chatroomId: String
       ): ResponseEntity<String> {
           val userId = tokenAuth.authGuard(token)
           // FastAPI 서버로부터 MongoDB에서 데이터를 받아오는 로직
           // ...
           return ResponseEntity.ok("chat logs for GPT")
       }
    }
  2. Feign 클라이언트로 FastAPI 서버 호출:

    • Spring Boot에서 FastAPI 서버로 데이터를 주고받기 위해 FeignClient 또는 RestTemplate을 사용할 수 있습니다. FeignClient를 사용하면 간결하게 외부 API를 호출할 수 있습니다.
    @FeignClient(name = "chatService", url = "\${fastapi.server.url}")
    interface ChatServiceClient {
    
       @PostMapping("/mongo/chatbot/create")
       fun createChatbotRoom(@RequestBody userId: Long): ResponseEntity<String>
    
       @PostMapping("/mongo/office/create")
       fun createGptRoom(@RequestBody userId: Long): ResponseEntity<String>
    
       @GetMapping("/mongo/chatbot/load/{chatroomId}")
       fun getChatbotLog(@PathVariable chatroomId: String): ResponseEntity<String>
    
       @GetMapping("/mongo/office/load/{chatroomId}")
       fun getGptLog(@PathVariable chatroomId: String): ResponseEntity<String>
    }

    설명:

    • @FeignClient를 통해 FastAPI 서버와 통신하며, 채팅방 생성, 로그 저장, 로그 불러오기 등의 작업을 FastAPI에 요청.
    • RestTemplate을 사용할 경우 더 세부적인 설정이 필요하지만, 그만큼 유연한 커스터마이징이 가능합니다.
  3. 의존성 주입 및 환경 설정:

    • application.yml 파일에 FastAPI 서버의 URL을 정의합니다.
    fastapi:
     server:
       url: http://localhost:8000  # FastAPI 서버의 주소
  4. 예외 처리 (Custom Exceptions):

    • TokenAuth.kt에서 정의한 JWT 관련 예외들을 전역적으로 처리하는 방식으로 Spring Boot의 @ControllerAdvice를 사용해 처리합니다.
    @ControllerAdvice
    class GlobalExceptionHandler {
    
       @ExceptionHandler(TokenExpiredException::class)
       fun handleTokenExpiredException(ex: TokenExpiredException): ResponseEntity<String> {
           return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ex.message)
       }
    
       @ExceptionHandler(TokenMalformedException::class)
       fun handleTokenMalformedException(ex: TokenMalformedException): ResponseEntity<String> {
           return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.message)
       }
    
       // 다른 예외 처리 로직도 동일하게 추가
    }