Skip to content

[Week5] 희연 - rendering#8

Open
heeyyeon wants to merge 1 commit intomainfrom
week5/heeyeon/rendering
Open

[Week5] 희연 - rendering#8
heeyyeon wants to merge 1 commit intomainfrom
week5/heeyeon/rendering

Conversation

@heeyyeon
Copy link
Collaborator

@heeyyeon heeyyeon commented Jun 2, 2025

Describe your changes

💬 파일 구조입니다.

week5/
├── hy-rendering/
  ├── src/
    ├── app/
    │   ├── page.tsx               # 전체 페이지 - 서버 컴포넌트
    │   ├── server-only/           # 서버 컴포넌트 전용 폴더
    │   │   └── server-info.tsx     # 서버 시간 표시용 컴포넌트
    │   ├── client-only/           # 클라이언트 컴포넌트 전용 폴더
    │   │   └── counter.tsx        # 상태 변화와 상호작용
    │   └── mixed/                 # 서버 + 클라이언트 컴포넌트 조합 예시
    │       ├── mixed-page.tsx      # 서버 컴포넌트 페이지
    │       └── like-button.tsx     # 클라이언트용 버튼
    └── lib/
        ├── post-data.ts           # 게시글 데이터
        └── server-time.ts          # 서버 전용 로직 (현재 시간 반환)

📝 실습 코드

//counter.tsx

`'use client';

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>클릭 수: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}`
//server-info.tsx

import { getCurrentTime } from '../../lib/server-time';

export default async function ServerInfo() {
  const time = getCurrentTime();
  return <p>서버 시간: {time}</p>;
}

//mixed-page.tsx

import { getPost } from '../../lib/post-data';
import PostCard from './post-card';

export default async function Page() {
  const post = await getPost();

  return (
    <div className="p-6">
      <h1 className="text-xl font-bold mb-4">🧠 서버 + 클라이언트 컴포넌트 조합</h1>
      <PostCard title={post.title} initialLikes={post.likes} />
    </div>
  );
}
//post-card.tsx

'use client';

import { useState } from 'react';

export default function PostCard({
  title,
  initialLikes,
}: {
  title: string;
  initialLikes: number;
}) {
  const [likes, setLikes] = useState(initialLikes);

  return (
    <div className="border p-4 rounded shadow">
      <h2 className="text-xl font-semibold mb-2">{title}</h2>
      <p>좋아요 ❤️ {likes}개</p>
      <button
        className="mt-2 px-3 py-1 bg-blue-500 text-white rounded"
        onClick={() => setLikes(likes + 1)}
      >
        좋아요 누르기
      </button>
    </div>
  );
}
// page.tsx

import ServerInfo from './server-only/server-info';
import Counter from './client-only/counter';
import MixedPage from './mixed/mixed-page';

export default function Page() {
  return (
    <main className="text-2xl font-bold p-[2rem]">
      <h1>🔍 Server vs Client Component 알아보기</h1>
      <hr />

      <section className="text-xl font-bold mt-[2rem]">
        <h2>🖥 1. 서버 컴포넌트</h2>
        <ServerInfo />
      </section>

      <section className="text-xl font-bold mt-[2rem]">
        <h2>🖱 2. 클라이언트 컴포넌트</h2>
        <Counter />
      </section>

      <section className="text-xl font-bold mt-[2rem]">
        <h2>💡 3. 서버+클라이언트 컴포넌트</h2>
        <MixedPage />
      </section>
    </main>
  );
}

// post-data.ts

export async function getPost() {
  return {
    id: 1,
    title: '게시글 제목입니당',
    likes: 10,
  };
}
// server-time.ts

export function getCurrentTime() {
  return new Date().toLocaleString();
}

@heeyyeon heeyyeon self-assigned this Jun 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant