서버 조회·업무 계산·상태별 UI를 하나의 페이지로 통합합니다.
서버에서 병렬로 데이터를 읽고 화면에 필요한 DTO와 파생값을 만든 뒤 상태별 UI를 렌더합니다. 클라이언트 JavaScript가 필요 없는 부분은 서버에 유지합니다.
실제 배포에서는 데이터 계층, 권한 정책, 관측, 캐시 무효화와 오류 경계를 별도 모듈로 분리합니다.
목록이 커지면 안정적인 정렬과 cursor pagination을 사용하고 전체 원본을 브라우저로 보내지 않습니다.
페이지 파일 하나에 DB 쿼리, 권한, 변환, UI 세부 구현을 모두 누적하지 마세요.
로컬 프로젝트에서 확인해보세요마감 임박 강좌 표시와 빈 목록 상태를 추가하세요.
async function getUser() {
return { id: 1, name: "민수" };
}
async function getCourses() {
return [
{ id: "next", title: "Next.js", done: 12, total: 18 },
{ id: "react", title: "React", done: 18, total: 18 },
];
}
export default async function Page() {
const [user, courses] = await Promise.all([getUser(), getCourses()]);
const completed = courses.filter((c) => c.done === c.total).length;
return (
<main>
<h1>{user.name}님의 대시보드</h1>
<p>
완료 {completed}/{courses.length}
</p>
<ul>
{courses.map((c) => (
<li key={c.id}>
<b>{c.title}</b> {c.done}/{c.total}
</li>
))}
</ul>
</main>
);
}