ReactReact 기초강의 10개 중 5번째난이도 기초

조건부 렌더링과 리스트 — 동적 UI 패턴

발행 읽는 시간 약 1 분

  • React
  • 조건부렌더링
  • 리스트
  • map
  • key

강의 소개

조건에 따라 다른 UI를 보여주고, 배열 데이터를 리스트로 렌더링하는 패턴을 배웁니다. key prop의 중요성과 성능 최적화도 이해합니다.

조건부 렌더링#

TSX
function UserBadge({ isAdmin, isPremium }: { isAdmin: boolean; isPremium: boolean }) {
    // 1. if/else (렌더 밖)
    if (isAdmin) {
        return <span className="badge-admin">관리자</span>;
    }

    // 2. 삼항 연산자
    return (
        <span className={isPremium ? "badge-premium" : "badge-free"}>
            {isPremium ? "프리미엄" : "무료"}
        </span>
    );
}

&& 단축 평가#

TSX
function Notification({ count, message }: { count: number; message?: string }) {
    return (
        <div>
            {/* count > 0일 때만 렌더링 */}
            {count > 0 && <span className="badge">{count}</span>}

            {/* 주의: 0은 렌더링됨! */}
            {/* ❌ */ count && <span>{count}</span>}
            {/* ✅ */ count > 0 && <span>{count}</span>}

            {/* 메시지가 있을 때만 */}
            {message && <p>{message}</p>}
        </div>
    );
}

nullish 합체와 옵셔널 체이닝#

TSX
function Profile({ user }: { user?: { name: string; bio?: string } }) {
    return (
        <div>
            <h2>{user?.name ?? "익명"}</h2>
            <p>{user?.bio ?? "소개글이 없습니다."}</p>
        </div>
    );
}

복잡한 조건 처리#

TSX
type LoadState = "idle" | "loading" | "success" | "error";

function DataView({ state, data, error }: {
    state: LoadState;
    data: string[] | null;
    error: string | null;
}) {
    // switch나 객체 맵으로 처리
    const content = {
        idle: <p>조회 버튼을 눌러주세요.</p>,
        loading: <Spinner />,
        success: <DataList items={data ?? []} />,
        error: <ErrorMessage message={error ?? "알 수 없는 오류"} />,
    }[state];

    return <div className="container">{content}</div>;
}

리스트 렌더링#

TSX
interface Product {
    id: string;
    name: string;
    price: number;
    inStock: boolean;
}

function ProductList({ products }: { products: Product[] }) {
    if (products.length === 0) {
        return <p>상품이 없습니다.</p>;
    }

    return (
        <ul>
            {products.map(product => (
                <li key={product.id}>           {/* key 필수! */}
                    <span>{product.name}</span>
                    <span>{product.price.toLocaleString()}원</span>
                    {!product.inStock && <span>품절</span>}
                </li>
            ))}
        </ul>
    );
}

key의 중요성#

Diagram · Mermaid
  • key는 React가 리스트 항목을 추적하는 고유 식별자
  • 배열 인덱스를 key로 쓰면 삭제/정렬 시 버그 발생
  • 데이터의 고유 ID 사용 권장
TSX
// ❌ 인덱스를 key로 사용
items.map((item, index) => <li key={index}>{item}</li>)

// ✅ 고유 ID를 key로 사용
items.map(item => <li key={item.id}>{item.name}</li>)

리스트 필터/정렬#

TSX
function FilteredList({ items }: { items: Product[] }) {
    const [filter, setFilter] = useState<"all" | "inStock">("all");
    const [sortBy, setSortBy] = useState<"name" | "price">("name");

    const displayed = items
        .filter(item => filter === "all" || item.inStock)
        .sort((a, b) => {
            if (sortBy === "name") return a.name.localeCompare(b.name);
            return a.price - b.price;
        });

    return (
        <div>
            <select onChange={e => setFilter(e.target.value as "all" | "inStock")}>
                <option value="all">전체</option>
                <option value="inStock">재고 있음</option>
            </select>
            <ul>
                {displayed.map(item => (
                    <li key={item.id}>{item.name} — {item.price}원</li>
                ))}
            </ul>
        </div>
    );
}

중첩 리스트#

TSX
interface Category {
    id: string;
    name: string;
    items: Product[];
}

function CategoryList({ categories }: { categories: Category[] }) {
    return (
        <div>
            {categories.map(category => (
                <section key={category.id}>
                    <h2>{category.name}</h2>
                    <ul>
                        {category.items.map(item => (
                            <li key={item.id}>{item.name}</li>
                        ))}
                    </ul>
                </section>
            ))}
        </div>
    );
}

정리#

패턴사용 시점
if/else완전히 다른 컴포넌트 반환
삼항 연산자두 가지 중 하나
&&조건부 표시/숨김
??null/undefined 대체값
.map()배열 → JSX 변환
key리스트 항목 고유 식별

다음 편에서는 useRef와 useMemo — DOM 참조와 성능 최적화를 배웁니다.

Follow · Ask · Work

이 글이 도움이 됐다면

짧은 작업 기록과 데모는 인스타그램에 올립니다. 만들고 싶은 것이 있다면 프로젝트 의뢰나 협업 제안도 편하게 보내 주세요.

글쓴이

파란여우

직접 만든 AI 앱·제품의 개발·배포를 공개하는 실전형 테크 크리에이터

파란여우 소개 Instagram @bluefox._.hi

이어서 보기

만들고 싶은 것이 있다면 프로젝트 의뢰로 알려 주세요.