부정 조건문 피하기
목차
코드를 읽을 때 가장 자주 발생하는 "작은 지연" 중 하나가 부정 조건문이에요.
!if(isOutOfStock) 같은 표현은 문법적으로 간단하지만, 우리 뇌는 이를 이해하기 위해 한 단계 더 거쳐야 해요.
isOutOfStock→ “품절”!isOutOfStock→ “품절이 아니다”- 결국 머릿속에서 → “재고가 있다”로 재해석
이 변환 과정이 누적되면 코드 읽는 속도가 느려지고 실수 가능성도 높아져요. 특히 이중 부정까지 있으면 의도 파악이 훨씬 어려워져요.
이 글에서는 부정 조건문과 이중 부정의 문제점과 해결 방법을 정리했어요.
부정 조건문이 인지 부하를 높이는 이유
부정 조건은 "의미 반전"이 기본 동작이에요.
코드를 읽는 사람은 조건을 만나는 순간, 다음 과정을 거치게 되죠.
- 변수 이름이 뜻하는 상태를 먼저 이해하고
!가 붙었음을 인지한 뒤- 최종 의미를 다시 긍정형으로 바꿔 해석
이 과정은 코드의 의도를 즉시 파악하는 흐름을 방해해요.
팀 단위로 유지보수하는 코드에서는 이런 작은 방해 요소가 쌓이면서 "이해 비용"이 점점 커져요.
"품절이 아니다"를 읽고 멈칫하는 순간
다음은 상품 재고에 따라 구매 버튼을 보여주는 컴포넌트 예시예요.
function CheckoutButton({ product }) {
const isOutOfStock = product.stock === 0;
if (!isOutOfStock) {
return <Button onClick={handleCheckout}>구매하기</Button>;
}
return <Button disabled>품절</Button>;
}!isOutOfStock는 결국 "재고가 있다면"을 뜻하지만, 그 의미가 코드에 바로 드러나지 않아요.
읽는 사람은 !를 만나는 순간 잠깐 멈추고, 머릿속에서 조건을 뒤집어야 해요.
이제 이 코드를 어떻게 개선할 수 있는지 구체적으로 살펴보도록 할게요.
개선 방법 1: 긍정 조건으로 바꾸기
가장 효과적인 방법은 의도를 긍정형으로 표현하는 것이에요.
function CheckoutButton({ product }) {
const isAvailable = product.stock > 0;
if (isAvailable) {
return <Button onClick={handleCheckout}>구매하기</Button>;
}
return <Button disabled>품절</Button>;
}isAvailable은 "구매 가능"이라는 의미를 즉시 전달해요.
조건을 해석할 필요 없이 문맥이 바로 이해되기 때문에 읽는 속도가 빨라져요.
개선 방법 2: Early Return으로 예외를 먼저 처리하기
UI 로직에서는 "정상 케이스"보다 "예외 케이스"가 더 복잡한 경우가 많아요.
예외를 먼저 반환하면 그 아래 코드는 자연스럽게 메인 플로우가 돼요.
function CheckoutButton({ product }) {
const isOutOfStock = product.stock === 0;
if (isOutOfStock) {
return <Button disabled>품절</Button>;
}
return <Button onClick={handleCheckout}>구매하기</Button>;
}이 패턴의 장점은 명확해요.
- "품절이면 종료" → 더 이상 머릿속에 조건을 들고 있을 필요가 없어요.
- 이후 코드는 "당연히 구매 가능한 상태"로 읽혀요.
실무에서 자주 등장하는 부정 조건 패턴
사례 1: 버튼 활성화 상태
disabled는 기본적으로 "비활성"을 뜻하기 때문에, 여기에 부정이 한 번 더 들어가기 쉬워요.
❌ 이중 부정 - 읽기 불편함
function SubmitButton({ form }) {
const isInvalid = !form.email || !form.password;
return (
<Button disabled={!isInvalid}>
{/* "유효하지 않지 않다"? */}
제출
</Button>
);
}✅ 긍정 변수명 - 읽기 편함
function SubmitButton({ form }) {
const isValid = form.email && form.password;
return (
<Button disabled={!isValid}>
{/* "유효하다"를 부정 → disabled */}
제출
</Button>
);
}핵심은 한 축만 부정으로 만드는 것이에요.
isValid는 긍정disabled는 "비활성"이므로!isValid로 한 번만 반전
이 정도는 읽는 사람이 바로 이해할 수 있어요.
사례 2: 권한 체크
❌ 이중 부정 - 읽기 불편함
function AdminPanel() {
const user = useUser();
if (!user.isNotAdmin) {
// "관리자가 아닌게 아니다"? 헷갈려요
return <AdminDashboard />;
}
return <AccessDenied />;
}✅ 긍정 조건 및 긍정 변수명 - 읽기 편함
function AdminPanel() {
const user = useUser();
if (user.isAdmin) {
// "관리자다" - 바로 이해됨
return <AdminDashboard />;
}
return <AccessDenied />;
}권한 같은 도메인에서는 특히 변수명을 긍정형으로 유지하는 게 좋아요. isAdmin, canEdit, hasPermission처럼 "행동으로 바로 이어지는" 단어가 안전해요.
사례 3: 로딩 상태
로딩 UI는 조건 분기가 자주 발생하는데, 부정 조건을 사용하면 흐름이 끊길 수 있어요.
❌ 부정 조건 - 읽기 불편함
function ProductList() {
const { data, isLoading } = useProducts();
if (!isLoading) {
// "로딩 중이 아니다" - 이중 부정 느낌
return <List items={data} />;
}
return <Spinner />;
}✅ Early Return - 읽기 편함
function ProductList() {
const { data, isLoading } = useProducts();
if (isLoading) {
return <Spinner />;
}
return <List items={data} />;
}특히 정상 케이스가 길어질수록 early return의 가치가 커져요.
부정 조건을 사용해도 괜찮을 때
부정 조건이 항상 나쁜 건 아니에요. 예를 들어 null / undefined 가드는 부정 형태가 더 자연스러워요.
function OrderButton({ user, product }) {
if (!user) {
return <LoginButton />;
}
if (!product) {
return <NotFound />;
}
return <Button onClick={handleCheckout}>주문하기</Button>;
}이 경우 "없으면 종료"라는 패턴이 명확하기 때문에 부정 조건이 오히려 더 깔끔해요.
부정 조건의 목적이 가드(guard)라면 괜찮다고 볼 수 있어요.
이중 부정은 반드시 피하기
이중 부정은 읽는 사람에게 퍼즐을 던지는 것과 같아요. 그리고 그 퍼즐은 유지보수에 최악이에요.
❌ 이중 부정 - 헷갈림
if (!isNotActive) {
// "활성화되지 않지 않았다" → "활성화되었다"?
}
if (!product.isNotAvailable) {
// "구매 불가능하지 않다" → "구매 가능하다"?
}
if (!user.disabled !== false) {
// 삼중 부정?! 이해 불가
}✅ 긍정 조건 - 명확함
if (isActive) {
// "활성화되었다" - 바로 이해됨
}
if (product.isAvailable) {
// "구매 가능하다" - 바로 이해됨
}
if (user.enabled) {
// "활성화되었다" - 바로 이해됨
}마무리
부정 조건문을 피하는 이유는 단순히 "보기 좋으라고"가 아니에요. 코드를 읽는 사람이 멈추지 않게 만드는 것, 그게 핵심이에요.
- 변수명은 가능한 한 긍정형으로
- 예외 케이스는 Early Return으로 먼저 정리
isNot~네이밍과 이중 부정은 최대한 피하기- 단,
null/undefined가드처럼 "없으면 종료" 패턴은 부정이 더 자연스러울 수 있음
좋은 코드는 "논리적으로 맞는 코드"가 아니라, 다른 사람이 가장 빠르게 이해할 수 있는 코드라고 생각해요.