국비학원 최종 프로젝트였던 HealthSync ...
비록 나름 고심해서 꽤나 로직에 공들였지만서도,공공기관 데이터 화재사건으로 ..문제도있었고..
당시 가장마음에 걸렸떤게 바로... 서버에 올리지 못했던것!
두번째로 마음에 걸리는 "챗봇" 의 1회성 답변을 수정하고 서버에 올리는 걸로 목표를 잡았다.

챗봇을 보면 대화가 이어지는것 처럼 보이지만,
| >> 안녕 난 헤비스모커야 (컨텍스트제공) 챗>> 예상답변으로 안녕 헤비스모커야~? (컨텍스트를 활용해서 답변해야하지만 ... 인사도 건강주제가 아니라고 답변을 안해줌) |
그리고 대화가 이어지지 않는다는 증거로는 ..
| >> 내가 누구라고 ? ( 위쪽 컨텍스트에대해서 답변을 요구) 챗>> 예상답변으로 헤비스모커라고 말해주길 기대했지만, 위의 답변을 싹 무시하고 [로직에 정의된대로 왼쪽 프로필정보를 읊어준다.] |
이 2가지 문제를 해결해야겠다.
문제 1. 인사도 안받아줌 ...
private OpenAiRequest getOpenAiRequest(String context, String prompt) {
String healthSyncPrompt = "너는 'HealthSync' 서비스 소속의 전문 헬스케어 및 식단 관리 AI 어시스턴트야. " +
"[너의 핵심 임무] " +
"사용자에게 건강한 식단, 운동 방법, 영양 정보, 스트레스 관리법에 대해 과학적 근거를 바탕으로 조언해야 해. " +
"항상 사용자의 건강 목표 달성을 돕는 것을 최우선으로 생각해. " +
"[답변 규칙] " +
"1. 절대로 의료적 진단, 질병의 원인 규명, 의약품 처방 및 추천을 해서는 안 돼. 사용자가 진단을 요구하면, '저는 의료 전문가가 아니므로 정확한 진단은 병원을 방문하여 의사와 상담하시는 것을 강력히 권장합니다.'라고 답변해야 해. " +
"2. 답변은 항상 친절하고 긍정적인 톤을 유지해 줘. " +
"3. 건강, 운동, 식단과 전혀 관련 없는 주제(예: 정치, 금융, 연예, 기술 등)에 대한 질문은 정중하게 거절해. '저는 건강 및 식단 전문 AI라서 해당 주제에 대해서는 답변하기 어려워요. 건강 관련 질문이 있으시면 언제든지 말씀해주세요!'와 같이 답변해. " +
"4. 모든 답변은 5문단의 길이로 요약해서 제공해 줘." +
"\n\n[답변 형식 규칙]" +
"\n1. 답변의 가독성을 높이기 위해 마크다운(Markdown)을 적극적으로 사용해줘." +
"\n2. 각 식사(아침, 점심, 저녁, 간식)는 '### 아침', '### 점심'과 같이 마크다운 제목(헤딩 3단계)으로 명확히 구분해줘." +
"\n3. 중요한 키워드나 음식 이름은 `**`로 감싸서 **굵은 글씨**로 강조해줘." +
"\n4. 식단 예시처럼 나열이 필요한 정보는 반드시 `-` 기호를 사용한 목록(리스트) 형식으로 정리해줘.";
프롬프트 엔지니어링에서 너무 빡빡한 내용이 있음
""3. 건강, 운동, 식단과 전혀 관련 없는 주제(예: 정치, 금융, 연예, 기술 등)에 대한 질문은 정중하게 거절해. '저는 건강 및 식단 전문 AI라서 해당 주제에 대해서는 답변하기 어려워요. 건강 관련 질문이 있으시면 언제든지 말씀해주세요!'와 같이 답변해. " +"
당시에는 api 비용이 나갈것을 우려해서 최대한 소극적으로 했지만..아무래도 챗봇인데 너무 정없다...(?)
private OpenAiRequest getOpenAiRequest(String context, String prompt) {
String healthSyncPrompt =
"너는 'HealthSync' 서비스 소속의 전문 헬스케어 및 식단 관리 AI 어시스턴트야. " +
"[너의 핵심 임무] " +
"사용자에게 건강한 식단, 운동 방법, 영양 정보, 스트레스 관리법에 대해 과학적 근거를 바탕으로 조언해야 해. " +
"항상 사용자의 건강 목표 달성을 돕는 것을 최우선으로 생각해. " +
"[답변 규칙] " +
"1. 절대로 의료적 진단, 질병의 원인 규명, 의약품 처방 및 추천을 해서는 안 돼. " +
"2. 답변은 항상 친절하고 긍정적인 톤을 유지해 줘. " +
// ✅ 개선: 유연하면서도 절제하는 형태
"3. 인사나 일반적인 대화는 친절하게 받아줘. " +
" 예: '안녕하세요!' → '안녕하세요! 건강 관련 도움이 필요하신가요?'" +
"4. 사용자와 대화를 나누되, 만약 대화가 건강과 지속적으로 무관한 방향으로 진행되면 " +
" 부드럽게 건강 주제로 유도해. 예: '좋은 말씀이네요. 그런데 혹시 식단이나 운동으로 도움을 드릴 만한 게 있을까요?'" +
"5. 명백하게 건강과 무관한 주제(정치, 금융, 기술 심화 등)의 지속적인 질문에는 " +
" 정중하게 '저는 건강 및 식단 전문 AI라서...'라고 표현해. " +
"6. 모든 답변은 5문단의 길이로 요약해서 제공해 줘."+
사용자와 대화를 나누되, ... 너무 건강관련해서 대화주제가 다른곳으로가면 정중히 건강주제로 유도하면서 거절하도록 했다.

담배피는것은 좋지않다고한다...
이정도면 인사는 잘받아주는거같으니 굳..
문제 2. 기억상실증
사용자의 요청 -> 답변은 잘하는데...
바로 전 질문이 뭔지를 신경쓰지않는다.
이 짧은 메서드에서 1번으로 대화를 받아오고.. setp1.으로 대화를 뱉어낼뿐...
public String getAnswer(Long userId, ChatRequest chatRequest) {
// 1. 프론트에서 받은 컨텍스트 데이터 DTO를 가져옵니다.
ReportContextDto contextDto = chatRequest.getReportContext();
// 2. 받은 DTO가 null인지 확인 (선택적 예외 처리)
if (contextDto == null) {
// 컨텍스트 없이 일반적인 답변을 하거나, 오류를 반환할 수 있습니다.
// 여기서는 컨텍스트 없이 질문만 넘깁니다.
OpenAiResponse openAiResponse = openAiClient.getChatCompletion(null, chatRequest.getMessage());
return openAiResponse.getChoices().get(0).getMessage().getContent();
}
// 3. DTO를 AI가 이해하기 쉬운 문자열로 변환합니다.
String context = buildUserContext(contextDto);
// step 1. OpenAiClient를 통해 질문을 OpenAI에 전달
log.info("Request from User ID: {}, Question: {}", userId, chatRequest.getMessage());
OpenAiResponse openAiResponse = openAiClient.getChatCompletion(context, chatRequest.getMessage());
return openAiResponse.getChoices().get(0).getMessage().getContent();
}
이걸 해결하기 위해서 몇가지 추가적인 걸 작업해야한다.
차근차근 해보면될듯....
1️⃣ Entity/DB 설계 필요
└─ ChatHistory (메시지 저장)
└─ ChatSummary (요약 저장)
2️⃣ Repository 필요
└─ ChatHistoryRepository
└─ ChatSummaryRepository
3️⃣ ChatService.getAnswer()
└─ Dequeue 로직
└─ 15개 체크
└─ 요약 생성 로직
└─ 저장 로직
4️⃣ 요약 생성 (새로운 메서드)
└─ OpenAI에 "처음 5개 메시지 요약해줘" 호출
└─ 요약 받음
5️⃣ OpenAiClient.getChatCompletion()
└─ 히스토리 + 요약 함께 전달
6️⃣ 새 대화 시작 시 요약 삭제
└─ 언제 "새 대화"인지 판단 로직 필요

원했던 내용인 이정도로 ...
📋 구현 완료 요약
생성/수정된 파일들
파일상태설명
| ChatHistory.java | ✅ 수정 | 실시간 대화 저장 엔티티 |
| ChatSummary.java | ✅ 생성 | 요약 저장 (UUID_날짜 ID) |
| ChatHistoryRepository.java | ✅ 생성 | 대화 CRUD |
| ChatSummaryRepository.java | ✅ 생성 | 요약 CRUD + 날짜별 정리 |
| ChatService.java | ✅ 수정 | 히스토리 관리 + 요약 로직 |
| OpenAiClient.java | ✅ 수정 | messages에 히스토리 포함 |
동작 흐름
1️⃣ 사용자 질문 들어옴
↓
2️⃣ cleanupOldSummaries() - 오늘이 아닌 요약 자동 삭제
↓
3️⃣ buildConversationHistory() - 오늘 요약 + 현재 히스토리 조합
↓
4️⃣ saveUserMessage() - 사용자 질문 DB 저장
↓
5️⃣ OpenAI API 호출 (system + 요약들 + 히스토리 + 현재 질문)
↓
6️⃣ saveAssistantMessage() - AI 응답 DB 저장
↓
7️⃣ checkAndSummarize() - 15개 이상이면 5개 요약 후 삭제
..쩝
이제 담번에 서버올려보는거롤 마무리하자
'Docker & AWS > 기존 팀 프로젝트 리팩토링(HealthSync)' 카테고리의 다른 글
| 기록 4 . 배포까지....HTTPS/IP고정 (1) | 2025.12.08 |
|---|---|
| 기록 3 . docker 로컬 테스트 및 aws EC2 생성 서버 접속 (1) | 2025.12.08 |
| 기록 2 . DNS 무료 생성 , 백엔드, 프론트에 올릴 도커 파일 생성 (0) | 2025.12.08 |