컴포넌트는 종종 서로 다른 조건에서 서로 다른 요소들을 보여줘야할 필요가 있어요. 리액트에서는 if
문이나 &&
, 그리고 ? :
연산자와 같은 자바스크립트 문법을 사용하여 JSX를 조건적으로 렌더링할 수 있어요.
이 페이지에서는
- 어떻게 조건에 맞춰 서로 다른 JSX를 반환하는지
- 어떻게 조건적으로 JSX 조각을 포함하거나 제외하는지
- 리액트 코드베이스에서 마주하게 될 흔한 조건부 구문 단축
를 알아볼 거예요.
Conditionally returning JSX | 조건부로 JSX 반환하기
여러개의 Item
들을 렌더링하는 PackingList
컴포넌트가 있고 이미 쌌는지 아니면 아직 싸지 않았는지를 표시할 수 있다고 가정해볼게요.
몇몇 Item
컴포넌트는 false
가 아니라 true
로 설정된 isPacked
prop을 갖고 있다는 점에 주목하세요. 만약 isPacked={true}
라면 이미 싼 아이템들에 체크 표시(✔)를 추가하고 싶을 거예요.
아래와 같이 if
/else
구문으로 이렇게 작성할 수 있어요.
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
만약 isPacked
prop이 true
라면 이 코드는 다른 JSX 트리를 반환할 거예요. 이 변화로 어떤 아이템들에는 체크 표시가 떠요.
두 경우에서 무엇이 반환되는지를 수정하여 결과가 어떻게 변하는지를 보세요.
자바스크립트의 if
와 return
구문을 사용하여 분기 로직을 만드는 방법에 주목하세요. 리액트에서는 (조건과 같은) 흐름 제어를 자바스크립트로 할 수 있어요.
Conditionally returning nothing with null
| null
을 사용하여 조건부로 아무것도 반환하지 않기
어떤 경우에는 아무것도 렌더링하고 싶지 않을 수 있어요. 예를 들어, 더 이상 이미 가방에 싼 아이템은 보고 싶지 않다고 생각해보세요. 컴포넌트는 무언가를 반환해야만 해요. 이 경우에는 null
을 반환하면 돼요.
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;
만약isPacked
가 참이라면 컴포넌트는 null
, 즉 아무것도 반환하지 않아요. 만약 거짓이라면 렌더링할 JSX를 반환해요.
실제로 컴포넌트에서 null
을 반환하는 것은 흔하지 않아요. 컴포넌트를 렌더링하려는 개발자를 놀래킬지도 모르기 때문이에요. 보통은 부모 컴포넌트의 JSX안에서 컴포넌트를 조건부로 포함시키거나 제외하는 방식을 사용해요. 어떻게 하는지를 알아보도록 해요!
Conditionally including JSX | 조건부로 JSX 포함하기
이전 예시에서는 컴포넌트가 반환할 트리를 제어했어요. 렌더링한 결과에서 중복되는 구문을 이미 발견했을 거예요.
<li className="item">{name} ✔</li>
는 아래와 비슷해요.
<li className="item">{name}</li>
조건절에 적혀있는 이 두 분기는 모두 <li className="item">...</li>
를 반환해요.
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
이렇게 코드가 중복되는 것이 해로운 것은 아니지만 코드를 유지보수하기 더 어렵게 만들어요. className
을 바꾸게 된다면 어떨까요? 코드의 두 부분을 전부 바꾸어야해요. 이러한 상황에서는 코드를 조금 더 중복배제 원칙(DRY)에 따르기 조건부로 작은 JSX를 포함시킬 수 있어요.
Conditional (ternary) operator (? :
) | 조건 (삼항) 연산자 (? :
)
자바스크립트는 조건적인 표현을 작성하기 위한 간결한 구문을 갖고 있어요. 바로 조건부 연산자 혹은 "삼항 연산자"라고 불리는 구문이에요.
아래와 같은 코드 대신
if (isPacked) {
return <li className="item">{name} ✔</li>;
}
return <li className="item">{name}</li>;
이렇게 작성할 수 있어요.
return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);
이 구문은 "만약 isPacked
가 참이라면(?
) name + ' ✔'
를 렌더링하고, 그렇지 않다면 (:
) name
을 렌더링하세요."라고 읽을 수 있어요.
이 두 예제가 완벽하게 동일한가요?
만약 객체 지향 프로그래밍 바탕의 코딩에서 넘어왔다면 위의 두 예제가 미묘하게 다르다고 생각할 거예요. 둘 중 하나는 두 개의 다른 <li>
인스턴스를 생성하기 떄문이에요. 하지만 JSX 엘리먼트는 "인스턴스"가 아니에요. 그 어떤 내부적인 상태를 갖고 있지도 않고 실제 DOM 노드도 아니기 떄문이에요. 이것들은 청사진처럼 그저 가벼운 표현법이에요. 따라 위의 두 예시들은 사실 완전히 동일해요. 상태 유지하고 재설정하기에서 어떻게 이와 같이 작동하는지를 자세히 설명하고 있어요.
이제 줄을 치기 위한 <del>
과 같이 또 다른 HTML 태그에서 짐 싸기를 완료한 아이템을 감싸고 싶다고 가정할게요. 여러분은 새로운 줄과 괄호를 추가하여 각각의 경우에서 쉽게 JSX를 조금 더 중첩할 수 있어요.
이런 스타일은 단순한 조건에서는 잘 동작하지만 적당히 사용하세요. 만약 컴포넌트가 너무 많은 중첩된 조건부 마크업으로 더럽다면 자식 컴포넌트로 추출하여 코드를 정리하는 것을 고려해보세요. 리액트에서 마크업은 코드의 일부이기 떄문에 복잡한 표현식을 줄이기 위해 변수나 함수와 같은 도구를 사용할 수 있어요.
Logical AND operator (&&
)
언젠가 마주하게 될 또 다른 흔한 단축 구문은 자바스크립트 논리 연산자 AND (&&
)에요. 리액트 컴포넌트 내부에서 조건이 참일 면 어떤 JSX를 렌더링하고 싶을 때 또는 아무것도 렌더링 하고 싶지 않을 때 사용돼요. &&
를 사용하면 조건적부로 isPacked
가 true
일 때만 체크 표시를 렌더링할 수 있어요.
return (
<li className="item">
{name} {isPacked && '✔'}
</li>
);
이 코드는 "만약 isPacked
가 참이면(&&
) 체크 표시를 렌더링하고 그렇지 않다면 아무것도 렌더링 하지 마세요."라고 읽을 수 있어요.
아래에서 이 동작을 확인해보세요.
자바스크립트 &&
표현식은 좌항(조건)이 true
일 떄 우항(여기서는 체크 표시)의 값을 반환해요. 하지만 만약 조건이 false
라면 전체 표현식은 false
가 돼요. 리액트는 JSX 트리에서 false
를 null
이나 undefined
와 같은 "구멍"으로 인식하고 그 자리에 아무것도 렌더링하지 않아요.
함정&&
의 좌항에 숫자를 넣지 마세요.
조건을 테스트하기 위해서 자바스크립트는 자동적으로 좌항을 불리안으로 변환해요. 그러나 만약 좌항이0
이라면 전체 표현식은 값(0
)을 갖고 리액트는 아무것도 렌더링하지 않는 대신 행복하게0
을 렌더링할 거예요.
흔히 하는 실수 중 하나는messageCount && <p>New messages</p>
와 같은 코드를 작성하는 거예요. 이 코드에서는messageCount
가0
일 때 아무것도 렌더링하지 않을 것이라고 쉽게 예상할 수 있지만 실제로는0
자체를 렌더링해요!
이를 수정하기 위해messageCount > 0 && <p>New messages</p>
와 같이 좌항을 불리안 타입으로 만드세요.
Conditionally assigning JSX to a variable | 조건부로 변수에 JSX 할당하기
단축 구문이 기본 코드 작성을 방해한다면 if
문과 변수를 사용해보세요. let
으로 정의된 변수에 재할당하여 화면에 띄우길 원하는 기본 콘텐츠인 이름을 제공받은 채로 프로그램을 시작할 수 있어요.
let itemContent = name;
isPacked
가 true
라면 itemContent
에 JSX 표현식을 재할당하려면 if
문을 사용하세요.
if (isPacked) {
itemContent = name + " ✔";
}
중괄호는 "자바스크립트로의 창문"을 열어줘요. 이전에 계산된 표현식을 JSX 내부에 중첩하여 반환된 JSX 트리 안에 중괄호를 사용하여 변수를 넣으세요.
<li className="item">
{itemContent}
</li>
이런 스타일은 더 장황하지만 더 유연하기도 해요. 아래에서 동작을 확인하세요.
이전과 같이 텍스트 뿐만 아니라 임의의 JSX도 넣을 수 있어요.
만약 자바스크립트에 친숙하지 않다면 이러한 스타일의 변화가 처음엔 버거울 거예요. 하지만 이런 구문을 배우면 리액트 컴포넌트 뿐만 아니라 그 어떤 자바스크립트 코드를 읽거나 쓸 때 도움이 될거예요. 처음에는 선호하는 것을 하나 골라보세요. 그리고나서 만약 다른 것들이 어떻게 동작하는지를 잊어버렸을 때 이 문서를 다시 참조하세요.
Reacp | 요약
- 리액트에서는 자바스크립트로 분기 로직을 제어해요.
if
문을 사용하여 조건부로 JSX 표현식을 반환할 수 있어요.- JSX를 조건부로 변수에 저장할 수 있고 중괄호를 사용하여 다른 JSX에 이 변수를 포함시킬 수 있어요.
- JSX에서
{cond ? <A /> : <B />}
은 "만약cond
가 참이라면,<A />
를 렌더링하고 그렇지 않다면 `를 렌더링하세요."를 의미해요. - JSX에서
{cond && <A />}
은 "만약cond
가 참이라면,<A />
를 렌더링하고 그렇지 않다면 아무것도 렌더링하지 마세요."를 의미해요. - 단축 구문은 흔하게 사용되지만 기본적인
if
문을 좋아한다면 굳이 사용할 필요는 없어요.
Challenges | 도전 과제
1. ? :
를 사용하여 불완전한 아이템에는 아이콘 보여주기
조건부 연산자(cond ? a : b
)를 사용하여 isPacked
가 true
가 아니라면 ❌를 렌더링하세요.
2. &&
로 아이템의 중요도 나타내기
이 예시에서 각각의 Item
은 숫자형식의 importance
prop을 받아요. &&
연산자를 사용하여 "(Importance: X)"를 기울임체로 렌더링하세요. 단, 중요도가 0이 아닌 아이템들에만 렌더링해야해요. 아이템 목록은 아래와 같은 형식으로 보여져야해요.
- Spacing suit (Importance: 9)
- Helmet with a golden leaf
- Photo of Tam (Importance: 6)
잊지 말고 두 라벨 사이에 공백을 추가하세요!
이렇게 하면 알맞게 동작해요.
importance
가 0
일 때 0
이 결과로 렌더링 되지 않도록 importance && ...
이 아니라 importance > 0 && ...
라고 작성한 것에 주목하세요.
이 답안에서 두 개의 분리된 조건은 이름과 중요도 라벨 사이에 공백을 추가하기 위해 사용되었어요. 공백을 만들기 위한 다른 방법으로는 importance > 0 && <> <i>...</i></>
처럼 Fragement을 사용하거나 importance > 0 && <i> ...</i>
처럼 <i>
안에 바로 공백을 추가할 수 있어요.
3. ? :
로 작성된 코드를 if
와 변수로 리팩토링하기
이 Drink
컴포넌트는 name
prop이 "tea"
인지 "coffe"
인지에 따라 다른 정보를 보여주기 위해 일련의 ? :
을 사용해요. 문제는 각 음료에 대한 정보가 다중 조건을 통해 뿌려진다는 점이에요. 이 코드를 세 개의 ? :
조건문을 사용하는 대신 하나의 if
문을 사용하여 리팩토링하세요.
if
를 사용하여 코드를 리팩토링 했다면 코드를 단순화하기 위한 추가적인 아이디어가 있나요?
정답 보기
여러가지 방법이 있지만 하나의 방법을 소개할게요.
여기서 각 음료에 대한 정보는 다중 조건으로 펼쳐져 있는 대신 함께 묶여있어요. 이러면 나중에 음료를 더 쉽게 추가할 수 있어요.
정보를 객체 안으로 옮겨서 조건을 함께 제거하는 다른 방법도 있어요.
'리액트 공식문서 | React Docs > Learn > Learn React' 카테고리의 다른 글
[Describing the UI] Keeping Components Pure | 컴포넌트를 순수하게 유지하기 (0) | 2024.02.14 |
---|---|
[Describing the UI] Rendering Lists | 리스트 렌더링하기 (0) | 2024.02.14 |
[Describing the UI] Passing Props to a Component | 컴포넌트에 props 전달하기 (2) | 2024.02.13 |
[Describing the UI] JavaScript in JSX with Curly Braces | 중괄호로 JSX에 자바스크립트 넣기 (0) | 2024.02.13 |
[Describing the UI] Writing Markup with JSX | JSX로 마크업 작성하기 (1) | 2024.02.10 |