-
Notifications
You must be signed in to change notification settings - Fork 2
Refactor/next cache rsc #116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: refactor/frontend-structure
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,49 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { CourseDetail } from '@/types/api/academic'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { cache } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
interface IAcademicDetailProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
semesterGrades: Array<{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
year: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
semester: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
earnedCredits: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
attemptedCredits: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
semesterGpa: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
classRank?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
totalStudents?: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
courses: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
major: CourseDetail[]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
liberal: CourseDetail[]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const getAcademicDetail = cache(async (year: number, semester: number) : Promise<IAcademicDetailProps> => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.log('🔥 실제 fetch 발생! [getAcademicDetail]'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// const cookieStore = await cookies(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// const token = cookieStore.getAll(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const abtoken = process.env.TEST_TOKEN; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const token = process.env.TEST_TOKEN2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const res = await fetch(`http://localhost:3000/api/get-academic/${year}/${semester}`, { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cache: 'force-cache', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
credentials: 'include', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'Cookie': `${abtoken}; ${token}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
next: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
revalidate: 60 * 60 * 24, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tags: [`academic-detail-${year}-${semester}`], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const result = await res.json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
semesterGrades: result.semesterGrades, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
courses: result.courses, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+40
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 불필요한 공백 라인 정리 필요 코드의 가독성을 높이기 위해 불필요한 공백 라인을 정리해주세요. const result = await res.json();
-
-
-
return {
semesterGrades: result.semesterGrades,
courses: result.courses,
}; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 데이터 페칭 구현이 로컬 환경에 의존하고 있습니다. API 엔드포인트가 하드코딩된 다음과 같이 수정하는 것을 권장합니다: - const abtoken = process.env.TEST_TOKEN;
- const token = process.env.TEST_TOKEN2;
- const res = await fetch(`http://localhost:3000/api/get-academic/${year}/${semester}`, {
+ // 상대 경로 또는 환경 변수를 사용하여 API 엔드포인트 설정
+ const res = await fetch(`/api/get-academic/${year}/${semester}`, {
cache: 'force-cache',
credentials: 'include',
- headers: {
- 'Cookie': `${abtoken}; ${token}`,
- },
next: {
revalidate: 60 * 60 * 24,
tags: [`academic-detail-${year}-${semester}`],
},
}); 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,25 @@ | ||||||||||||||||||||||||||||||||||
import { cache } from 'react'; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
interface Semester { | ||||||||||||||||||||||||||||||||||
year: number; | ||||||||||||||||||||||||||||||||||
semester: number; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
export const getSemesters = cache(async () : Promise<Semester[]> => { | ||||||||||||||||||||||||||||||||||
const abtoken = process.env.TEST_TOKEN; | ||||||||||||||||||||||||||||||||||
const token = process.env.TEST_TOKEN2; | ||||||||||||||||||||||||||||||||||
console.log('🔥 실제 fetch 발생! [getSemesters]'); | ||||||||||||||||||||||||||||||||||
Comment on lines
+9
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 환경 변수 사용 방식 검토 필요 개발 목적으로 보이는 - const abtoken = process.env.TEST_TOKEN;
- const token = process.env.TEST_TOKEN2;
- console.log('🔥 실제 fetch 발생! [getSemesters]');
+ const authToken = process.env.AUTH_TOKEN;
+ const sessionToken = process.env.SESSION_TOKEN; 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
const res = await fetch(`http://localhost:3000/api/get-semesters`, { | ||||||||||||||||||||||||||||||||||
cache: 'force-cache', | ||||||||||||||||||||||||||||||||||
headers: { | ||||||||||||||||||||||||||||||||||
'Cookie': `${abtoken}; ${token}`, | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
credentials: 'include', | ||||||||||||||||||||||||||||||||||
next: { tags: ['semesters'], revalidate: 60 * 60 * 24 } | ||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||
Comment on lines
+14
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 하드코딩된 URL 및 캐싱 전략 재검토 필요 로컬호스트 URL이 하드코딩되어 있어 운영 환경에서 문제가 될 수 있습니다. 상대 경로나 환경 변수를 사용하는 것이 더 적절합니다. 또한 - const res = await fetch(`http://localhost:3000/api/get-semesters`, {
+ const res = await fetch(`/api/get-semesters`, { 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
if (!res.ok) {throw new Error('Failed to fetch');} | ||||||||||||||||||||||||||||||||||
return res.json(); | ||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||
Comment on lines
+23
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 오류 처리 개선 필요 현재 오류 처리는 기본적인 메시지만 제공합니다. 사용자에게 더 명확한 오류 메시지를 제공하고, 가능하다면 오류 상황에 맞는 구체적인 처리 로직을 추가하는 것이 좋습니다. - if (!res.ok) {throw new Error('Failed to fetch');}
+ if (!res.ok) {
+ const errorText = await res.text().catch(() => 'Unknown error');
+ throw new Error(`학기 정보를 가져오는데 실패했습니다: ${res.status} ${errorText}`);
+ } 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,42 @@ | ||||||||||||||||||||||||||||||||||
import AcademicSummaryCard from "../../../../components/AcademicSummaryCard/AcademicSummaryCard"; | ||||||||||||||||||||||||||||||||||
import SectionCourses from "./SectionCourses/SectionCourses"; | ||||||||||||||||||||||||||||||||||
import type { CourseDetail } from "@/types/api/academic"; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
interface AcademicDetailProps { | ||||||||||||||||||||||||||||||||||
semesterGrades: Array<{ | ||||||||||||||||||||||||||||||||||
year: number; | ||||||||||||||||||||||||||||||||||
semester: string; | ||||||||||||||||||||||||||||||||||
earnedCredits: number; | ||||||||||||||||||||||||||||||||||
attemptedCredits: number; | ||||||||||||||||||||||||||||||||||
semesterGpa: number; | ||||||||||||||||||||||||||||||||||
classRank?: number; | ||||||||||||||||||||||||||||||||||
totalStudents?: number; | ||||||||||||||||||||||||||||||||||
}>; | ||||||||||||||||||||||||||||||||||
courses: { | ||||||||||||||||||||||||||||||||||
major: CourseDetail[]; | ||||||||||||||||||||||||||||||||||
liberal: CourseDetail[]; | ||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
export default function AcademicDetailContent({data}: {data: AcademicDetailProps}) { | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
console.log('data',data); | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 프로덕션 코드에서 디버깅 콘솔 로그 제거 필요 디버깅을 위한 콘솔 로그는 프로덕션 코드에서 제거해야 합니다. - console.log('data',data); 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||
<> | ||||||||||||||||||||||||||||||||||
{/* 학기 성적 요약 */} | ||||||||||||||||||||||||||||||||||
<AcademicSummaryCard | ||||||||||||||||||||||||||||||||||
earnedCredits={data.semesterGrades[0].earnedCredits} | ||||||||||||||||||||||||||||||||||
gpa={data.semesterGrades[0].semesterGpa} | ||||||||||||||||||||||||||||||||||
classRank={data.semesterGrades[0].classRank} | ||||||||||||||||||||||||||||||||||
totalStudents={data.semesterGrades[0].totalStudents} | ||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||
Comment on lines
+27
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 예외 처리 필요
+ {data.semesterGrades?.length > 0 ? (
<AcademicSummaryCard
earnedCredits={data.semesterGrades[0].earnedCredits}
gpa={data.semesterGrades[0].semesterGpa}
classRank={data.semesterGrades[0].classRank}
totalStudents={data.semesterGrades[0].totalStudents}
/>
+ ) : (
+ <div>학기 성적 정보가 없습니다.</div>
+ )} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
<div className="gap-24"></div> | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 자식 요소가 없는 JSX 요소는 self-closing 태그로 사용 자식 요소가 없는 div 요소는 self-closing 태그로 사용하는 것이 권장됩니다. - <div className="gap-24"></div>
+ <div className="gap-24" /> 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Biome (1.9.4)[error] 33-34: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing. Unsafe fix: Use a SelfClosingElement instead (lint/style/useSelfClosingElements) |
||||||||||||||||||||||||||||||||||
{/* 전공 과목 목록 */} | ||||||||||||||||||||||||||||||||||
<SectionCourses title="전공" courses={data.courses.major} /> | ||||||||||||||||||||||||||||||||||
{/* 교양 과목 목록 */} | ||||||||||||||||||||||||||||||||||
<div className="gap-24"></div> | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 자식 요소가 없는 JSX 요소는 self-closing 태그로 사용 자식 요소가 없는 div 요소는 self-closing 태그로 사용하는 것이 권장됩니다. - <div className="gap-24"></div>
+ <div className="gap-24" /> 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||
<SectionCourses title="교양" courses={data.courses.liberal} /> | ||||||||||||||||||||||||||||||||||
</> | ||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
'use client' | ||
|
||
import { TopNavigation } from "@/components/ui/TopNavigation"; | ||
import { useInternalRouter } from "@/hooks/useInternalRouter"; | ||
|
||
export default function NavBar() { | ||
const router = useInternalRouter(); | ||
return ( | ||
<TopNavigation.Preset title="학기별 세부 성적" type="back" onNavigationClick={() => router.back()} /> | ||
) | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,6 +1,5 @@ | ||||||
'use client'; | ||||||
|
||||||
import { useEffect, useState } from 'react'; | ||||||
import { ROUTES } from '@/constants/routes'; | ||||||
import { useInternalRouter } from '@/hooks/useInternalRouter'; | ||||||
import styles from './SemesterSlider.module.scss'; | ||||||
|
@@ -13,42 +12,15 @@ interface Semester { | |||||
interface SemesterSliderProps { | ||||||
currentYear: number; | ||||||
currentSemester: number; | ||||||
semesters: Semester[]; | ||||||
} | ||||||
|
||||||
export default function SemesterSlider({ currentYear, currentSemester }: SemesterSliderProps) { | ||||||
export default function SemesterSlider({ currentYear, currentSemester , semesters}: SemesterSliderProps) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 컴포넌트 서명이 업데이트되었지만 포맷이 개선될 수 있습니다. 함수 서명에서 -export default function SemesterSlider({ currentYear, currentSemester , semesters}: SemesterSliderProps) {
+export default function SemesterSlider({ currentYear, currentSemester, semesters }: SemesterSliderProps) { 📝 Committable suggestion
Suggested change
|
||||||
const router = useInternalRouter(); | ||||||
const [semesters, setSemesters] = useState<Semester[]>([]); | ||||||
const [isLoading, setIsLoading] = useState(true); | ||||||
|
||||||
useEffect(() => { | ||||||
const fetchSemesters = async () => { | ||||||
try { | ||||||
const response = await fetch('/api/get-semesters', { | ||||||
next: { | ||||||
revalidate: 3600, // 1시간마다 재검증 | ||||||
}, | ||||||
}); | ||||||
if (!response.ok) { | ||||||
throw new Error('Failed to fetch semesters'); | ||||||
} | ||||||
const data = await response.json(); | ||||||
setSemesters(data); | ||||||
} catch (error) { | ||||||
console.error('Error fetching semesters:', error); | ||||||
} finally { | ||||||
setIsLoading(false); | ||||||
} | ||||||
}; | ||||||
|
||||||
fetchSemesters(); | ||||||
}, []); | ||||||
|
||||||
if (isLoading) { | ||||||
return null; | ||||||
} | ||||||
|
||||||
const handleSemesterClick = (year: number, semester: number) => { | ||||||
router.replace(ROUTES.ACADEMIC_DETAIL, { year, semester }); | ||||||
router.replace(ROUTES.ACADEMIC_DETAIL, { params: [year, semester] }); | ||||||
}; | ||||||
|
||||||
const getSemesterLabel = (semester: number): string => { | ||||||
|
@@ -66,6 +38,7 @@ export default function SemesterSlider({ currentYear, currentSemester }: Semeste | |||||
} | ||||||
}; | ||||||
|
||||||
|
||||||
return ( | ||||||
<div className={styles.sliderContainer}> | ||||||
{semesters.map(sem => ( | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,14 @@ | ||||||||||||||||||||||||||||||||||||||
export const fetchCache = 'auto' | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
import NavBar from './components/NavBar'; | ||||||||||||||||||||||||||||||||||||||
import styles from './layout.module.scss'; | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
export default function GraduationProgressLayout({ children }: { children: React.ReactNode }) { | ||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||
<div className={styles.container}> | ||||||||||||||||||||||||||||||||||||||
<NavBar /> | ||||||||||||||||||||||||||||||||||||||
<div className={styles.content}>{children}</div> | ||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||
Comment on lines
+6
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) 컴포넌트 이름과 기능 간의 불일치가 있습니다. 컴포넌트 이름은 -export default function GraduationProgressLayout({ children }: { children: React.ReactNode }) {
+export default function AcademicDetailLayout({ children }: { children: React.ReactNode }) { 📝 Committable suggestion
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,27 @@ | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
import { Suspense } from 'react'; | ||||||||||||||||||||||||||||||||||
import AcademicDetailContent from './components/AcademicDetailContent'; | ||||||||||||||||||||||||||||||||||
import { getSemesters } from './apis/getSemesters'; | ||||||||||||||||||||||||||||||||||
import { getAcademicDetail } from './apis/getAcademicDetail'; | ||||||||||||||||||||||||||||||||||
import SemesterSlider from './components/SemesterSlider'; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
export const fetchCache = 'force-cache'; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
export default async function AcademicDetailPage({params}: {params: Promise<{year: number, semester: number}>}) { | ||||||||||||||||||||||||||||||||||
const {year, semester} = await params; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
const [semesters, data] = await Promise.all([ | ||||||||||||||||||||||||||||||||||
getSemesters(), | ||||||||||||||||||||||||||||||||||
getAcademicDetail(year, semester), | ||||||||||||||||||||||||||||||||||
]); | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||
<Suspense fallback={<div></div>}> | ||||||||||||||||||||||||||||||||||
<div className="gap-8"></div> | ||||||||||||||||||||||||||||||||||
<SemesterSlider currentYear={year} currentSemester={semester} semesters={semesters} /> | ||||||||||||||||||||||||||||||||||
<div className="gap-20"></div> | ||||||||||||||||||||||||||||||||||
<AcademicDetailContent data={data} /> | ||||||||||||||||||||||||||||||||||
Comment on lines
+19
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 빈 div 요소 개선 필요 비어있는 div 요소가 간격을 위해 사용되고 있습니다. 하지만 이는 시맨틱하지 않고, 스타일링을 위한 요소 생성은 좋은 방법이 아닙니다. 마진이나 패딩을 사용하거나, 전용 스페이서 컴포넌트를 만드는 것이 더 나은 방법입니다. 또한 정적 분석 도구에서 지적한 대로 자식 요소가 없는 JSX 요소는 자체 닫힘 태그로 표시해야 합니다. - <div className="gap-8"></div>
+ <div className="gap-8" />
<SemesterSlider currentYear={year} currentSemester={semester} semesters={semesters} />
- <div className="gap-20"></div>
+ <div className="gap-20" /> 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Biome (1.9.4)[error] 19-19: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing. Unsafe fix: Use a SelfClosingElement instead (lint/style/useSelfClosingElements) [error] 20-20: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing. Unsafe fix: Use a SelfClosingElement instead (lint/style/useSelfClosingElements) [error] 22-22: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing. Unsafe fix: Use a SelfClosingElement instead (lint/style/useSelfClosingElements) |
||||||||||||||||||||||||||||||||||
</Suspense> | ||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||
Comment on lines
+18
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick (assertive) Suspense 사용이 적절합니다. Suspense를 사용하여 로딩 상태를 처리하는 방식은 적절합니다. 다만, 현재 fallback은 비어 있는데, 사용자 경험을 향상시키기 위해 로딩 인디케이터나 스켈레톤 UI를 추가하는 것을 고려해보세요. - <Suspense fallback={<div></div>}>
+ <Suspense fallback={<div className="p-4 text-center">학업 정보를 불러오는 중...</div>}> 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Biome (1.9.4)[error] 19-19: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing. Unsafe fix: Use a SelfClosingElement instead (lint/style/useSelfClosingElements) [error] 20-20: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing. Unsafe fix: Use a SelfClosingElement instead (lint/style/useSelfClosingElements) [error] 22-22: JSX elements without children should be marked as self-closing. In JSX, it is valid for any element to be self-closing. Unsafe fix: Use a SelfClosingElement instead (lint/style/useSelfClosingElements) |
||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,6 @@ import { NextResponse } from 'next/server'; | |
import { createClient } from '@/lib/supabase/server'; | ||
import type { Database } from '@/types/supabase'; | ||
|
||
export const dynamic = 'force-dynamic'; | ||
|
||
type CourseAreaType = Database['public']['Enums']['course_area_type']; | ||
|
||
|
@@ -82,13 +81,10 @@ function getCourseCategory(areaType: CourseAreaType): 'major' | 'liberal' { | |
return 'liberal'; | ||
} | ||
|
||
export async function GET( | ||
request: NextRequest, | ||
props: { params: Promise<{ year: string; semester: string }> } | ||
) { | ||
export async function GET(request: NextRequest, props: { params: Promise<{ year: string; semester: string }> }) { | ||
const params = await props.params; | ||
try { | ||
const supabase = createClient(); | ||
const supabase = await createClient(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Supabase 클라이언트 비동기 초기화 수정
이 수정은 중요한 버그를 해결하며, Supabase 클라이언트가 완전히 초기화된 후에 사용되도록 보장합니다. |
||
|
||
// 인증된 사용자 확인 | ||
const { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
불필요한 코드 제거 필요
디버깅용 콘솔 로그와 주석 처리된 코드는 프로덕션 환경에서 제거하는 것이 좋습니다.
📝 Committable suggestion