Conditional Rendering조건부 렌더링

Your components will often need to display different things depending on different conditions. In React, you can conditionally render JSX using JavaScript syntax like if statements, &&, and ? : operators. 컴포넌트는 서로 다른 조건에 따라 다른 것을 보여줘야 하는 경우가 자주 발생합니다. React에서는 if 문, &&, ? : 연산자 같은 JavaScript 문법을 사용해 조건부로 JSX를 렌더링할 수 있습니다.

You will learn학습 내용

  • How to return different JSX depending on a condition
  • How to conditionally include or exclude a piece of JSX
  • Common conditional syntax shortcuts you’ll encounter in React codebases
  • 조건에 따라 다른 JSX를 반환하는 방법
  • 일부 JSX를 조건부로 포함하거나 제외하는 방법
  • React 코드베이스에서 흔히 접할 수 있는 조건부 구문 단축 표현

Conditionally returning JSX조건부로 반환하는 JSX

Let’s say you have a PackingList component rendering several Items, which can be marked as packed or not: 상품이 포장되었는지 여부를 표시할 수 있는 여러 개의 Item을 렌더링하는 PackingList 컴포넌트가 있다고 가정해봅시다:

function Item({ name, isPacked }) {
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Notice that some of the Item components have their isPacked prop set to true instead of false. You want to add a checkmark (✔) to packed items if isPacked={true}. 일부 Item 컴포넌트의 isPacked prop이 false가 아닌 true로 설정되어 있는 것을 확인할 수 있습니다. isPacked={true}인 경우, 패킹된 아이템에 체크 표시(✔)를 추가하고 싶을 것입니다.

You can write this as an if/else statement like so: 이를 다음과 같이 if/else으로 작성할 수 있습니다:

if (isPacked) {
return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

If the isPacked prop is true, this code returns a different JSX tree. With this change, some of the items get a checkmark at the end: isPacked prop이 true이면 이 코드는 다른 JSX 트리를 반환합니다. 이렇게 변경하면 일부 항목의 마지막에 체크 표시가 나타납니다:

function Item({ name, isPacked }) {
  if (isPacked) {
    return <li className="item">{name}</li>;
  }
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Try editing what gets returned in either case, and see how the result changes! 두 경우 모두 반환되는 내용을 편집해보고 결과가 어떻게 달라지는지 확인해 보세요!

Notice how you’re creating branching logic with JavaScript’s if and return statements. In React, control flow (like conditions) is handled by JavaScript. JavaScript의 ifreturn 문으로 분기 로직을 어떻게 생성하는지 주목하세요. React에서 조건과 같은 제어 흐름은 JavaScript로 처리됩니다.

Conditionally returning nothing with nullnull을 사용해 조건부로 아무것도 반환하지 않기

In some situations, you won’t want to render anything at all. For example, say you don’t want to show packed items at all. A component must return something. In this case, you can return null: 어떤 상황에서는 아무것도 렌더링하고 싶지 않을 수도 있습니다. 예를 들어, 포장된 아이템을 전혀 표시하고 싶지 않다고 가정해 보겠습니다. 컴포넌트는 무언가를 반환해야 합니다. 이 경우 null을 반환하면 됩니다:

if (isPacked) {
return null;
}
return <li className="item">{name}</li>;

If isPacked is true, the component will return nothing, null. Otherwise, it will return JSX to render. isPacked가 참이면 컴포넌트는 아무것도 반환하지 않고 null을 반환합니다. 그렇지 않으면 렌더링할 JSX를 반환합니다.

function Item({ name, isPacked }) {
  if (isPacked) {
    return null;
  }
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

In practice, returning null from a component isn’t common because it might surprise a developer trying to render it. More often, you would conditionally include or exclude the component in the parent component’s JSX. Here’s how to do that! 실제로 컴포넌트에서 null을 반환하는 것은 렌더링하려는 개발자를 놀라게 할 수 있기 때문에 일반적이지 않습니다. 부모 컴포넌트의 JSX에 컴포넌트를 조건부로 포함하거나 제외하는 경우가 더 많습니다. 이를 수행하는 방법은 다음과 같습니다!

Conditionally including JSX 조건을 포함한 JSX

In the previous example, you controlled which (if any!) JSX tree would be returned by the component. You may already have noticed some duplication in the render output: 이전 예제에서는 컴포넌트가 반환할 JSX 트리(있는 경우!)를 제어했습니다. 렌더링 출력에서 이미 일부 중복을 발견했을 수 있습니다:

<li className="item">{name}</li>

is very similar to 이는 아래와 매우 유사합니다.

<li className="item">{name}</li>

Both of the conditional branches return <li className="item">...</li>: 두 조건부 브랜치 모두 <li className="item">...</li>를 반환합니다:

if (isPacked) {
return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

While this duplication isn’t harmful, it could make your code harder to maintain. What if you want to change the className? You’d have to do it in two places in your code! In such a situation, you could conditionally include a little JSX to make your code more DRY. 이러한 중복은 해롭지는 않지만 코드를 유지 관리하기 어렵게 만들 수 있습니다. className을 변경하려면 어떻게 해야 할까요? 코드의 두 곳에서 변경해야 할 것입니다! 이런 상황에서는 조건부로 약간의 JSX를 포함시켜 코드를 더 DRY하게(덜 반복적이게) 만들 수 있습니다.

Conditional (ternary) operator (? :)조건(삼항) 연산자(? :)

JavaScript has a compact syntax for writing a conditional expression — the conditional operator or “ternary operator”. JavaScript에는 조건 연산자 또는 “삼항 연산자”라는 조건식 작성을 위한 간결한 구문이 있습니다.

Instead of this: 아래 대신에:

if (isPacked) {
return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

You can write this: 이렇게 쓸 수 있습니다:

return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);

You can read it as “if isPacked is true, then (?) render name + ' ✔', otherwise (:) render name. isPacked가 참이면 (?) name + ' ✔'를 렌더링하고, 그렇지 않으면 (:) name을 렌더링하라” 라고 읽을 수 있습니다.

Deep Dive | 심층 탐구

Are these two examples fully equivalent?이 두 예제는 완전히 동일할까요?

If you’re coming from an object-oriented programming background, you might assume that the two examples above are subtly different because one of them may create two different “instances” of <li>. But JSX elements aren’t “instances” because they don’t hold any internal state and aren’t real DOM nodes. They’re lightweight descriptions, like blueprints. So these two examples, in fact, are completely equivalent. Preserving and Resetting State goes into detail about how this works. 객체 지향 프로그래밍에 익숙하다면, 위의 두 예제 중 하나가 <li>의 서로 다른 두 “인스턴스”를 생성할 수 있기 때문에 미묘하게 다르다고 생각할 수 있습니다. 하지만 JSX 요소는 내부 state를 보유하지 않고 실제 DOM 노드가 아니기 때문에 “인스턴스”가 아닙니다. 이는 청사진과 같은 가벼운 설명입니다. 이 두 예제는 사실 완전히 동등합니다. state 보존 및 재설정에서 작동 방식에 대해 자세히 설명합니다.

Now let’s say you want to wrap the completed item’s text into another HTML tag, like <del> to strike it out. You can add even more newlines and parentheses so that it’s easier to nest more JSX in each of the cases: 이제 완성된 항목의 텍스트를 <del>과 같은 다른 HTML 태그로 감싸서 줄을 긋고 싶다고 가정해 봅시다. 더 많은 개행과 괄호를 추가하여 각 대소문자를 더 쉽게 중첩할 수 있습니다:

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {isPacked ? (
        <del>
          {name + ' ✔'}
        </del>
      ) : (
        name
      )}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

This style works well for simple conditions, but use it in moderation. If your components get messy with too much nested conditional markup, consider extracting child components to clean things up. In React, markup is a part of your code, so you can use tools like variables and functions to tidy up complex expressions. 이 스타일은 간단한 조건에 적합하지만 적당히 사용하세요. 중첩된 조건 마크업이 너무 많아 컴포넌트가 지저분해지면 자식 컴포넌트를 추출하여 정리하는 것을 고려하세요. React에서 마크업은 코드의 일부이므로 변수나 함수와 같은 도구를 사용해 복잡한 표현식을 정리할 수 있습니다.

Logical AND operator (&&)논리 AND 연산자(&&)

Another common shortcut you’ll encounter is the JavaScript logical AND (&&) operator. Inside React components, it often comes up when you want to render some JSX when the condition is true, or render nothing otherwise. With &&, you could conditionally render the checkmark only if isPacked is true: 또 다른 일반적인 단축표현으로 JavaScript AND(&&) 논리 연산자가 있습니다. React 컴포넌트 내에서 조건이 참일 때 일부 JSX를 렌더링하거나 그렇지 않으면 아무것도 렌더링하지 않으려 할 때 자주 사용됩니다. &&를 사용하면 isPackedtrue일 때만 조건부로 체크 표시를 렌더링할 수 있습니다:

return (
<li className="item">
{name} {isPacked && '✔'}
</li>
);

You can read this as “if isPacked, then (&&) render the checkmark, otherwise, render nothing”. 이는 “만약 isPacked이면 (&&) 체크 표시를 렌더링하고, 그렇지 않으면 아무것도 렌더링하지 않습니다” 로 읽을 수 있습니다.

Here it is in action: 아래는 실제로 작동하는 모습입니다:

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✔'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

A JavaScript && expression returns the value of its right side (in our case, the checkmark) if the left side (our condition) is true. But if the condition is false, the whole expression becomes false. React considers false as a “hole” in the JSX tree, just like null or undefined, and doesn’t render anything in its place. JavaScript && 표현식은 왼쪽(조건)이 true이면 오른쪽(이 경우 체크 표시)의 값을 반환합니다. 하지만 조건이 false이면 표현식 전체가 false가 됩니다. React는 falsenull이나 undefined와 마찬가지로 JSX 트리상의 “구멍”으로 간주하고, 그 자리에 아무것도 렌더링하지 않습니다.

Pitfall | 함정

Don’t put numbers on the left side of &&. &&의 왼쪽에 숫자를 넣지 마세요.

To test the condition, JavaScript converts the left side to a boolean automatically. However, if the left side is 0, then the whole expression gets that value (0), and React will happily render 0 rather than nothing. 조건을 테스트하기 위해, JavaScript는 왼쪽을 자동으로 불리언으로 변환합니다. 그러나 왼쪽이 0이면 전체 표현식이 해당 값(0)을 가져오고, React는 기꺼이 빈 값 대신 0을 렌더링합니다.

For example, a common mistake is to write code like messageCount && <p>New messages</p>. It’s easy to assume that it renders nothing when messageCount is 0, but it really renders the 0 itself! 예를 들어, 흔히 하는 실수 중 하나는 messageCount && <p>New messages</p>와 같은 코드를 작성하는 것입니다. messageCount0일 때 아무것도 렌더링하지 않는다고 생각하기 쉽지만, 실제로는 0 자체를 렌더링합니다!

To fix it, make the left side a boolean: messageCount > 0 && <p>New messages</p>. 이 문제를 해결하려면 왼쪽을 불리언으로 만들면 됩니다: messageCount > 0 && <p>New messages</p>

Extra Comment

!!messageCount && <p>New messages</p>도 됩니다. - @정재남

어떤 변수 앞의 NOT 논리 연산자 !는 바로 뒤따르는 변수가 true로 변환할 수 있는 값인 경우(truthy)에는 false를, false로 변환할 수 있는 값인 경우(falsy)에는 true를 반환합니다.

NOT 논리 연산자 !를 두 번 연속으로 작성하면(Double NOT !!) 이중부정이 되어, truthy 값은 true를, falsy 값은 false를 반환합니다.

val판정!val!!valval판정!val!!val
0falsytruefalse0 이외의 모든 숫자truthyfalsetrue
빈 문자열""falsytruefalse비어있지 않은 문자열truthyfalsetrue
nullfalsytruefalseSymbol()truthyfalsetrue
undefinedfalsytruefalse모든 참조형truthyfalsetrue

따라서 숫자형인 messageCount0이 아닌 경우 !!messageCounttrue가 되어 뒤의 <p>New messages</p>를 렌더링하고, 반대로 0인 경우에는 !!messageCountfalse가 되므로 아무것도 렌더링하지 않습니다.

Conditionally assigning JSX to a variable변수에 조건부로 JSX 할당하기

When the shortcuts get in the way of writing plain code, try using an if statement and a variable. You can reassign variables defined with let, so start by providing the default content you want to display, the name: 단축키가 일반 코드를 작성하는 데 방해가 된다면 if 문과 변수를 사용해 보세요. let으로 정의된 변수는 재할당할 수 있으므로, 표시할 기본 콘텐츠인 이름을 지정하는 것부터 시작하세요:

let itemContent = name;

Use an if statement to reassign a JSX expression to itemContent if isPacked is true: if 문을 사용하여 isPackedtrue면 JSX 표현식을 itemContent에 재할당합니다:

if (isPacked) {
itemContent = name + " ✔";
}

Curly braces open the “window into JavaScript”. Embed the variable with curly braces in the returned JSX tree, nesting the previously calculated expression inside of JSX: 중괄호는 “JavaScript로의 창”을 엽니다. 중괄호로 변수를 반환된 JSX 트리에 삽입하여 이전에 계산된 표현식을 JSX 안에 중첩시킵니다:

<li className="item">
{itemContent}
</li>

This style is the most verbose, but it’s also the most flexible. Here it is in action: 이 스타일은 가장 장황하지만 가장 유연하기도 합니다. 실제로 사용해보겠습니다:

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = name + " ✔";
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Like before, this works not only for text, but for arbitrary JSX too: 이전과 마찬가지로 텍스트뿐만 아니라 임의의 JSX에서도 작동합니다:

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = (
      <del>
        {name + " ✔"}
      </del>
    );
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

If you’re not familiar with JavaScript, this variety of styles might seem overwhelming at first. However, learning them will help you read and write any JavaScript code — and not just React components! Pick the one you prefer for a start, and then consult this reference again if you forget how the other ones work. JavaScript에 익숙하지 않다면 처음에는 이 다양한 스타일이 압도적으로 보일 수 있습니다. 하지만 이 스타일들을 익히면 React 컴포넌트뿐 아니라 모든 JavaScript 코드를 읽고 작성하는 데 도움이 됩니다! 우선 선호하는 스타일을 선택한 다음, 다른 스타일이 어떻게 작동하는지 잊어버렸다면 이 레퍼런스를 다시 참조하세요.

Recap요약

  • In React, you control branching logic with JavaScript.
  • You can return a JSX expression conditionally with an if statement.
  • You can conditionally save some JSX to a variable and then include it inside other JSX by using the curly braces.
  • In JSX, {cond ? <A /> : <B />} means “if cond, render <A />, otherwise <B />.
  • In JSX, {cond && <A />} means “if cond, render <A />, otherwise nothing”.
  • The shortcuts are common, but you don’t have to use them if you prefer plain if.
  • React에서는 JavaScript로 분기 로직을 제어합니다.
  • if문으로 조건부로 JSX 표현식을 반환할 수 있습니다.
  • 중괄호를 사용하여 일부 JSX를 변수에 조건부로 저장한 다음 다른 JSX 안에 포함할 수 있습니다.
  • JSX에서 {cond ? <A /> : <B />}cond가 있으면 <A />를 렌더링하고, 그렇지 않으면 <B />를 렌더링하라” 를 의미합니다.
  • JSX에서 {cond && <A />}cond가 있으면 <A />를 렌더링하고, 그렇지 않으면 아무것도 렌더링하지 말라” 를 의미합니다.
  • 이 단축용법은 흔히 쓰이지만, 만약 if를 선호한다면 굳이 사용하지 않아도 됩니다.

Challenge 1 of 3: Show an icon for incomplete items with ? :? :로 미완료 항목 아이콘 표시하기

Use the conditional operator (cond ? a : b) to render a ❌ if isPacked isn’t true. 조건 연산자(cond ? a : b)를 사용하여 isPackedtrue가 아닌 경우 ❌를 렌더링하세요.

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✔'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}