Skip to content

Commit e5ba769

Browse files
committed
Feat: 미들웨어에서 JWT 토큰 이름 변경 및 공개 경로 추가, 로그인 페이지 리다이렉트 로직 수정. AuthProvider 추가 및 홈 페이지에 로그인 기능 구현. 채팅 페이지에서 사용자 인증 확인 및 채팅 목록 자동 스크롤 기능 추가. 프로필 페이지에서 사용자 정보 및 전력 소비 데이터 가져오기 기능 추가. 전체적으로 코드 리팩토링 및 최적화.
1 parent d9a7be7 commit e5ba769

File tree

15 files changed

+1311
-506
lines changed

15 files changed

+1311
-506
lines changed

src/app/(layout)/chat/[chattingId]/page.jsx

Lines changed: 113 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -6,64 +6,48 @@ import { useParams } from "next/navigation";
66
import Chatlist from "@/components/Chatlist";
77
import ChatMessages from "@/components/ChatMessages";
88
import Image from "next/image";
9+
import { useChat } from "@/contexts/ChatContext";
10+
import { continueChatWebSocket } from "@/lib/websocket";
911

1012
export default function ChatPage() {
1113
const params = useParams();
1214
const chattingId = params.chattingId;
13-
14-
const [chatData, setChatData] = useState({
15-
chattingId: "",
16-
ownerId: "",
17-
title: "",
18-
description: "",
19-
chatList: [],
20-
createdAt: 0,
21-
modifiedAt: 0,
15+
const { getCurrentChat, updateChat, setCurrentChatId } = useChat();
16+
17+
const [formData, setFormData] = useState({
18+
content: "",
2219
});
2320

24-
const [loading, setLoading] = useState(true);
21+
// 실시간 스트리밍을 위한 로컬 상태
22+
const [localChatList, setLocalChatList] = useState([]);
2523

24+
// chattingId가 바뀔 때마다 현재 채팅 설정
2625
useEffect(() => {
27-
// localStorage에 lastchattingid 저장
28-
localStorage.setItem("lastchattingid", chattingId);
26+
setCurrentChatId(chattingId);
27+
}, [chattingId, setCurrentChatId]);
2928

30-
// DB에서 채팅 데이터 조회 (실제 구현에서는 API 호출)
31-
fetchChatData(chattingId);
32-
}, [chattingId]);
29+
// 현재 채팅 데이터 가져오기
30+
const chatData = getCurrentChat();
3331

34-
const fetchChatData = async (id) => {
35-
try {
36-
setLoading(true);
37-
38-
// 실제 API 호출
39-
const response = await fetch(`/api/chat/${id}`);
40-
41-
if (!response.ok) {
42-
throw new Error("채팅을 찾을 수 없습니다");
43-
}
44-
45-
const data = await response.json();
46-
setChatData(data);
47-
} catch (error) {
48-
console.error("채팅 데이터 조회 실패:", error);
49-
// 에러 시 빈 채팅으로 설정
50-
setChatData({
51-
chattingId: id,
52-
ownerId: "",
53-
title: "채팅을 찾을 수 없습니다",
54-
description: "",
55-
chatList: [],
56-
createdAt: 0,
57-
modifiedAt: 0,
58-
});
59-
} finally {
60-
setLoading(false);
32+
// Context 데이터가 변경되면 로컬 상태 동기화
33+
useEffect(() => {
34+
if (chatData?.chatList) {
35+
setLocalChatList([...chatData.chatList]);
6136
}
62-
};
37+
}, [chatData?.chatList]);
6338

64-
const [formData, setFormData] = useState({
65-
content: "",
66-
});
39+
// 채팅 목록이 변경될 때마다 자동으로 스크롤
40+
useEffect(() => {
41+
const chatBox = document.getElementById('chat-box');
42+
if (chatBox) {
43+
setTimeout(() => {
44+
chatBox.scrollTo({
45+
top: chatBox.scrollHeight,
46+
behavior: 'smooth'
47+
});
48+
}, 100);
49+
}
50+
}, [localChatList]);
6751

6852
const handleInputChange = (e) => {
6953
const { name, value } = e.target;
@@ -80,10 +64,87 @@ export default function ChatPage() {
8064
};
8165

8266
const handleSendMessage = () => {
83-
if (formData.content.trim() === "") return;
67+
if (formData.content.trim() === "" || !chatData) return;
68+
69+
console.log("=== 메시지 전송 시작 ===");
70+
71+
const userChatElement = {
72+
sender: "USER",
73+
text: formData.content,
74+
timestamp: Math.floor(Date.now() / 1000),
75+
model: "",
76+
use_estimate: 0,
77+
llm_estimate: 0,
78+
};
79+
80+
// 1. 유저 메시지를 Context에 즉시 저장
81+
const updatedChatListWithUser = [...(chatData.chatList || []), userChatElement];
82+
updateChat(chattingId, {
83+
chatList: updatedChatListWithUser
84+
});
85+
86+
let currentAIMessage = null; // 현재 AI 메시지 추적
87+
88+
function modelNameHandler(modelName) {
89+
console.log("AI 모델 시작:", modelName);
90+
91+
// AI 메시지 박스 생성 (로컬 상태에만)
92+
currentAIMessage = {
93+
sender: "AI",
94+
text: "",
95+
timestamp: Math.floor(Date.now() / 1000),
96+
model: modelName,
97+
use_estimate: 0,
98+
llm_estimate: 0,
99+
};
100+
101+
setLocalChatList(prev => [...prev, currentAIMessage]);
102+
}
84103

85-
// TODO: 실제 메시지 전송 로직 구현
86-
console.log("메시지 전송:", formData.content);
104+
function modelResponseHandler(id, text) {
105+
// 실시간 스트리밍 (로컬 상태만 업데이트)
106+
if (currentAIMessage) {
107+
currentAIMessage.text += text;
108+
setLocalChatList(prev => {
109+
const newList = [...prev];
110+
const lastIndex = newList.length - 1;
111+
if (newList[lastIndex] && newList[lastIndex].sender === "AI") {
112+
newList[lastIndex] = { ...currentAIMessage };
113+
}
114+
return newList;
115+
});
116+
}
117+
}
118+
119+
// WebSocket 연결 설정 (응답 완료 처리 추가)
120+
const socket = continueChatWebSocket(
121+
chattingId,
122+
formData.content,
123+
document.cookie.split('; ').find(row => row.startsWith('jwtToken='))?.split('=')[1],
124+
modelNameHandler,
125+
modelResponseHandler
126+
);
127+
128+
// WebSocket 메시지 이벤트 추가 처리
129+
const originalOnMessage = socket.onmessage;
130+
socket.onmessage = (event) => {
131+
const data = JSON.parse(event.data);
132+
133+
// 기존 처리
134+
if (originalOnMessage) {
135+
originalOnMessage(event);
136+
}
137+
138+
// 응답 완료 시 Context에 저장
139+
if (data.end === "end" && currentAIMessage) {
140+
console.log("AI 응답 완료 - Context에 저장");
141+
const finalChatList = [...updatedChatListWithUser, currentAIMessage];
142+
updateChat(chattingId, {
143+
chatList: finalChatList,
144+
modifiedAt: Date.now()
145+
});
146+
}
147+
};
87148

88149
setFormData({ content: "" });
89150
const textarea = document.querySelector('textarea[name="content"]');
@@ -98,12 +159,12 @@ export default function ChatPage() {
98159
}
99160
};
100161

101-
if (loading) {
162+
if (!chatData) {
102163
return (
103164
<div className="flex flex-row h-screen">
104165
<Chatlist />
105166
<div className="flex-1 flex items-center justify-center">
106-
<div className="text-white">로딩 중...</div>
167+
<div className="text-white">채팅을 찾을 수 없습니다</div>
107168
</div>
108169
</div>
109170
);
@@ -119,7 +180,7 @@ export default function ChatPage() {
119180
id="chat-box"
120181
className="flex flex-col flex-1 overflow-y-auto min-h-0"
121182
>
122-
<ChatMessages chatList={chatData.chatList} />
183+
<ChatMessages chatList={localChatList} />
123184
</div>
124185
<div
125186
id="input-box"

0 commit comments

Comments
 (0)