스파르타코딩클럽/과제

[supabase realtime을 이용한 채팅 구현하기] 채팅 ui 모달

myinfo7091 2024. 12. 23. 23:00

Parallel Routes

Parallel Routes는 Next.js 13(App Router)에서 병렬적으로 여러 UI를 렌더링하는 기능이다. URL 상태를 기반으로 모달과 페이지 콘텐츠를 분리하면서도 독립적으로 관리할 수 있다.

 

 

채팅 UI 구현을 위한 Parallel Routes 구성

app/
  layout.tsx              // 전체 레이아웃
  page.tsx                // 기본 페이지 (대화 목록)
  @chat/                  // 병렬 라우트
    layout.tsx            // 채팅 모달 레이아웃
    [userId]/page.tsx     // 특정 사용자와의 채팅 모달

 

1. 기본 레이아웃 (app/layout.tsx)

import { ReactNode } from "react";

type RootLayoutProps = {
  children: ReactNode;
  chat: ReactNode;
};

export default function RootLayout({ children, chat }: RootLayoutProps) {
  return (
    <html lang="en">
      <body>
        <main style={{ display: "flex", flexDirection: "row" }}>
          {/* 기본 콘텐츠 (대화 목록 등) */}
          <div style={{ flex: 1 }}>{children}</div>

          {/* 병렬 라우트: 채팅 모달 */}
          {chat}
        </main>
      </body>
    </html>
  );
}

 

 

2. 기본 페이지: 대화 목록 (app/page.tsx)

import Link from "next/link";

type ChatRoom = {
  id: string;
  name: string;
};

export default function ChatList() {
  // 예시 데이터: 실제로는 Supabase 또는 API에서 가져와야 합니다.
  const chatRooms: ChatRoom[] = [
    { id: "mentor1", name: "멘토 1" },
    { id: "mentor2", name: "멘토 2" },
  ];

  return (
    <div>
      <h1>대화 목록</h1>
      <ul>
        {chatRooms.map((room) => (
          <li key={room.id}>
            {/* 특정 채팅방으로 이동하는 링크 */}
            <Link href={`/chat/${room.id}`}>
              <a>{room.name}</a>
            </Link>
          </li>
        ))}
      </ul>
    </div>
  );
}

 

 

3. 병렬 라우트 레이아웃: 채팅 모달 (app/@chat/layout.tsx)

import { ReactNode } from "react";

type ChatLayoutProps = {
  children: ReactNode;
};

export default function ChatLayout({ children }: ChatLayoutProps) {
  return (
    <div
      style={{
        position: "fixed",
        top: 0,
        right: 0,
        width: "400px",
        height: "100%",
        backgroundColor: "#fff",
        borderLeft: "1px solid #ddd",
        boxShadow: "0 0 10px rgba(0,0,0,0.1)",
      }}
    >
      {children}
    </div>
  );
}