문제 : 같은 퀴즈 세션에 대해서만 답변, 결과가 업데이트 되던 문제

문제 원인:
현재 백엔드에서 가져오는 id 값은 퀴즈 세션의 id값이 아닌 존재하지 않은 값이기 때문에 나오는 디폴트 값인 1이었습니다.
백엔드 구조
post(self, request):
# Debug
print(request.data)
content = llm.content
chain = llm.quizz_chain(content)
response = chain.invoke(request.data)
response_dict = json.loads(response)
quiz = Quiz.objects.create(
title=response_dict["title"],
description=response_dict["description"],
)
for question_data in response_dict["questions"]:
question = Question.objects.create(
quiz=quiz,
number=question_data["id"],
content=question_data["content"],
answer_type=question_data["answer_type"],
)
for choice_data in question_data["choices"]:
Choice.objects.create(
question=question,
number=choice_data["id"],
content=choice_data["content"],
is_correct=choice_data["is_correct"],
)
print(quiz.id, response_dict["questions"])
return Response(
{"detail": "문제가 생성되었습니다.", "id": response_dict["id"], "questions": response_dict["questions"]},
status=status.HTTP_200_OK,
)
즉, 백엔드 측에서 보내주는 id 값이 전체 퀴즈 세션의 id로 오해했기 때문에 발생했던 문제였습니다.
id를 실제 생성된 quiz의 id로 재설정해줘야 했습니다.
그 후 해당 id로 GET요청을 보내 안전하게 해당하는 퀴즈 세션의 정보를 가져올 수 있도록 수정했습니다. (id로 조회한 온전한 퀴즈 세션에 대한 정보 받아오기)
백엔드 측 변경사항
변경 전
return Response(
{"detail": "문제가 생성되었습니다.", "id": response_dict["id"], "questions": response_dict["questions"]},
status=status.HTTP_200_OK,
)
변경 후
return Response(
{"detail": "문제가 생성되었습니다.", "id": quiz.id, "questions": response_dict["questions"]},
status=status.HTTP_200_OK,
)
프론트 측 변경사항
백엔드에서 값을 id가 아닌 number로 그 고유성을 유지하고 있다.
이를 무시하고 quiz.id나 choice.id 를 통해 POST, GET 요청을 날렸기 때문에 일부 요청의 경우 (특히나 보기 문항이 많은 4지선다 문제) 에서 다르게 채점되는 상황이 발생했었다.
때문에 프론트 측에서도 id가 아닌 number로 그 통일성을 유지해준다.
<FormQuizContainer>
{Array.isArray(selectedQuestions) &&
selectedQuestions.map((quiz) => (
<FormQuizCardContainer key={quiz.number}>
<TitleContainer>
Q{quiz.number}. {quiz.content}
</TitleContainer>
<QuizContentContainer>
{quiz.answer_type === "ox" ? (
<Option2Container>
{quiz.choices.map((choice) => (
<Option2Button
key={choice.number}
className={selectedOptions[quiz.number] === choice.number ? "selected" : ""}
onClick={() => handleSelectOption(quiz.number, choice.number)}
>
{choice.content}
</Option2Button>
))}
</Option2Container>
) : (
<OptionContainer>
{quiz.choices.map((choice) => (
<OptionButton
key={choice.number}
className={selectedOptions[quiz.number] === choice.number ? "selected" : ""}
onClick={() => handleSelectOption(quiz.number, choice.number)}
>
{choice.content}
</OptionButton>
))}
</OptionContainer>
)}
</QuizContentContainer>
</FormQuizCardContainer>
))}
문제 : 네비게이션 바에서 프론트 측에서 화면 변환 시 상태 상속 안되던 문제
<Button onClick={() => navigate("/chats/form")}>
const [selectedCategory, setSelectedCategory] = useState(null);
const [selectedTitle, setSelectedTitle] = useState(null);
const [selectedTitleIndex, setSelectedTitleIndex] = useState(null);
해결 : state로 상속되어야 하는 값들을 넘겨줌, 받은 화면 측에서는 useLocation을 이용해 navigation에서 넘어온 state를 가져올 수 있게 됨
<Button
onClick={() =>
navigate("/chats/form", {
state: {
selectedCategory: selectedCategory,
selectedTitle: selectedTitle,
selectedTitleIndex: selectedTitleIndex,
},
})
}
>
const [selectedCategory, setSelectedCategory] = useState(
location.state?.selectedCategory || null
);
const [selectedTitle, setSelectedTitle] = useState(
location.state?.selectedTitle || null
);
const [selectedTitleIndex, setSelectedTitleIndex] = useState(location.state?.selectedTitleIndex || null);
더 생각해볼 사항 : dom을 통해 가져온 값은 수명이 어느까지인가?
A.
DOM을 통해 가져온 값은 캐시값인가?에 대한 질문에 대해 해석하자면, 브라우저에서 useLocation을 사용하여 받은 값들이 실제로는 캐시된 값이냐는 것에 대한 궁금증인 것 같습니다.
답변:
useLocation으로 가져오는 값은 캐시된 값이 아니라 **상태(state)**입니다.
React Router의 navigate 메서드를 사용해서 state를 넘겨주면, 그 상태는 해당 페이지에서만 유효합니다. 즉, 페이지가 리로딩되거나 새로 고침될 때는 상태가 초기화되며, location.state는 더 이상 접근할 수 없습니다.
따라서 useLocation으로 받은 값은 브라우저 캐시와 관련이 없고, 오직 React Router의 상태 관리에 의해 관리됩니다.
상태(state) vs 캐시:
상태 (State): navigate를 통해 페이지 이동 시 state를 전달하면, 해당 페이지에서만 상태를 사용할 수 있고, 새로 고침이나 다른 라우팅으로 페이지를 나가면 사라집니다.
캐시 (Cache): 브라우저 캐시는 페이지를 새로 고침할 때 리소스를 빠르게 불러오기 위한 저장소입니다. 예를 들어, 이미지나 데이터 파일이 캐시되며, 이러한 데이터는 브라우저에 의해 자동으로 관리되고 저장됩니다.
따라서 useLocation은 캐시가 아니라, 페이지 간 이동 시 전달된 동적 데이터라고 이해하시면 됩니다.