JavaScript에서 !! (이중 부정 연산자)를 사용하는 이유
!!란 무엇인가
!!는 JavaScript의 별도 연산자가 아니라, 논리 NOT 연산자(!)를 두 번 연속 사용한 것이다. 어떤 값이든 Boolean 타입으로 명시적 변환하는 관용적 패턴이다.
!!value
// 동일한 동작
Boolean(value)
동작 원리
두 단계로 나뉜다.
const name = "hello"
!name // 1단계: truthy → false
!!name // 2단계: false → true
- 첫 번째
!— 값을 Boolean으로 변환한 뒤 반전 - 두 번째
!— 다시 반전하여 원래 의미의 Boolean 값으로 복원
Falsy와 Truthy 값 정리
JavaScript에서 falsy로 평가되는 값은 7가지뿐이다.
!!false // false
!!0 // false
!!-0 // false
!!0n // false (BigInt)
!!"" // false
!!null // false
!!undefined // false
!!NaN // false
이 외의 모든 값은 truthy다.
!!1 // true
!!"hello" // true
!![] // true (빈 배열도 truthy)
!!{} // true (빈 객체도 truthy)
!!-1 // true
!!" " // true (공백 문자열도 truthy)
왜 사용하는가
1. 타입을 Boolean으로 확정
API 응답이나 변수의 타입이 불확실할 때, 확실한 true/false로 변환한다.
function isLoggedIn(user) {
return !!user // user 객체가 있으면 true, null/undefined면 false
}
return user로 하면 객체 자체가 반환되지만, return !!user는 반드시 Boolean이 반환된다.
2. 조건 저장
조건 결과를 변수에 저장할 때 원본 값이 아닌 Boolean으로 저장한다.
const hasItems = !!list.length
const isValid = !!inputValue.trim()
const isEnabled = !!config?.feature?.enabled
3. 비교 연산에서 의도 명확화
// 의도가 불분명
if (array.length) { ... }
// Boolean임을 명시
if (!!array.length) { ... }
// 가장 명확한 방식
if (array.length > 0) { ... }
4. React 등에서 렌더링 방지
React에서 0은 falsy지만 화면에 렌더링된다. !!로 Boolean 변환하면 이를 방지할 수 있다.
// 문제: items가 빈 배열이면 0이 화면에 출력됨
{items.length && <List items={items} />}
// 해결: Boolean으로 변환
{!!items.length && <List items={items} />}
!! vs Boolean()
둘은 결과가 동일하다.
!!value === Boolean(value) // 항상 true
비교 항목!!Boolean()가독성익숙한 사람에게 간결의도가 명확길이짧다길다성능미미한 차이미미한 차이
팀 컨벤션에 따라 선택하면 된다.
실무 사용 예시
// 환경변수 존재 여부
const isProduction = !!process.env.PRODUCTION
// 옵셔널 체이닝과 함께
const hasPermission = !!user?.roles?.includes('admin')
// 필터링
const activeUsers = users.filter(u => !!u.lastLoginAt)
// TypeScript에서 타입 가드와 함께
const validItems = items.filter((item): item is Item => !!item)
정리
!!는 어떤 값이든 Boolean으로 변환하는 패턴이다Boolean()함수와 동일한 결과를 더 짧게 쓴 것이다- 값의 존재 여부를
true/false로 확정할 때 사용한다 - 빈 배열
[]과 빈 객체{}는 truthy라는 점에 주의한다