앱을 만들다 보면 조건이 늘 “좋은 형태”로만 들어오지 않습니다. 서버는 실패 상태를 부정 플래그로 내려주고, OS 권한은 기본적으로 거부/미결정 상태가 섞여 있으며, 외부 SDK는 isInvalid처럼 부정형 상태를 그대로 제공합니다. 이런 상태에서 조건식을 억지로 긍정 논리로만 유지하려고 하면 NOT NOT 같은 이중 부정이 늘고 괄호가 복잡해지면서, 작은 실수 하나가 화면 진입 오류나 권한 우회 같은 문제로 이어질 수 있습니다. 드모르간의 법칙은 이런 복잡한 조건을 “동치인 형태로 안전하게 변환”해 주기 때문에, 실패 조건을 먼저 걸러내는 구조와 잘 맞고 코드 가독성과 안정성을 동시에 끌어올립니다.
드모르간의 법칙
드모르간의 핵심은 NOT이 괄호 바깥에서 전체 조건을 덮을 때, AND와 OR이 서로 바뀌고 각 항목에 NOT이 분배된다는 점입니다.
NOT(A AND B)는 (NOT A) OR (NOT B)와 같습니다.
NOT(A OR B)는 (NOT A) AND (NOT B)와 같습니다.
이 규칙을 알고 있으면 “성공 조건”을 “실패 조건”으로 바꾸거나, 이미 존재하는 부정형 플래그를 그대로 살려서 조건식을 정리할 때 매우 유용합니다.
로그인과 권한 체크
화면 진입 조건은 대개 “로그인 상태이고 권한이 유효할 때만 통과”입니다. 하지만 구현 방식은 보통 그 반대로 가는 경우가 많습니다. 즉, 통과 조건을 길게 나열하기보다 실패 조건을 먼저 감지해 즉시 리턴하는 방식이 안전하고 읽기 쉽기 때문입니다.
이때 자주 등장하는 형태가 NOT(로그인 AND 권한유효)입니다. 드모르간을 적용하면 (NOT 로그인) OR (NOT 권한유효)로 바뀌고, 자연어로도 “로그인이 아니거나 권한이 없으면 막는다”가 되어 의도가 바로 보입니다. 이 구조는 에러 처리 분기에도 바로 연결돼서, 로그인 문제면 로그인 화면으로 보내고 권한 문제면 권한 요청 UX를 보여주는 식의 설계가 깔끔해집니다.
네트워크 동기화는 실패 조건
동기화 로직은 “네트워크 연결됨 AND 서버 정상”일 때만 수행하는 것이 원칙입니다. 그런데 실제로 중요한 건 성공이 아니라 실패를 어떻게 다루느냐입니다. 오프라인이면 로컬 캐시를 쓰고, 서버 장애면 재시도 큐에 적재하고, 타임아웃이면 백오프를 걸어야 하는 등 실패 정책이 훨씬 다양합니다.
그래서 조건을 NOT(연결됨 AND 서버정상) 형태로 먼저 잡고, 드모르간으로 “연결이 끊겼거나 서버가 비정상이면 동기화 스킵”으로 풀어 쓰면, 실패 정책을 붙이기가 훨씬 쉬워집니다. 특히 백그라운드 동기화처럼 사용자가 직접 보지 않는 영역일수록 이 방식이 안정적입니다.
푸시 알림은 토글과 OS 권한이 엇갈릴 때 문제
푸시 알림은 앱 내부 토글과 OS 권한이 둘 다 맞아야 실제로 동작합니다. 사용자는 앱에서 알림을 켰는데 OS에서 권한을 꺼둔 상태가 흔하고, 반대로 OS는 허용인데 앱 토글이 꺼진 상태도 자주 생깁니다.
이런 경우 “토글 ON AND 권한 허용”만으로는 부족하고, 실제로는 “불가능한 상태를 먼저 감지”하는 것이 UX가 좋습니다. NOT(토글ON AND 권한허용)을 드모르간으로 풀면 “토글이 꺼져 있거나 권한이 없으면 설정 유도”로 정리되고, 어떤 상태에서 어떤 안내를 해야 하는지 명확해집니다. 플랫폼마다 권한 상태가 세분화되어 있어도(미결정/거부/제한 등) 실패 조건 중심으로 두면 분기가 안정적으로 유지됩니다.
결제/구독
인앱결제나 구독은 “구매 가능 조건”을 늘리는 것보다 “구매 불가 조건”을 놓치지 않는 것이 더 중요합니다. 스토어 연결, 상품 정보 로딩, 국가/연령 제한, 계정 상태, 네트워크 등 변수가 많기 때문입니다.
따라서 구매 버튼을 활성화하는 것보다, 먼저 NOT(스토어정상 AND 상품로딩완료 AND 제한통과)를 체크해 비활성화하고 사유를 보여주는 설계를 자주 사용합니다. 드모르간으로 풀면 “스토어가 불안정하거나 상품 로딩이 덜 됐거나 제한에 걸리면 비활성화”가 되어, 비활성화 이유를 사용자에게 명확히 안내하는 UX까지 자연스럽게 연결됩니다.
폼 검증에서 NOT이 섞이면 버그
회원가입, 결제 정보, 주소 입력 같은 폼에서는 “모든 항목이 유효할 때만 제출 가능”이 기본입니다. 그런데 항목이 늘어나고, 특정 항목은 선택이고, 특정 항목은 조건부 필수로 바뀌면 조건식이 빠르게 복잡해집니다.
이때 NOT(모든 항목 유효)을 그대로 두면, 괄호와 NOT이 뒤엉켜서 한 항목을 빠뜨리거나 AND/OR 하나를 잘못 넣는 실수가 흔해집니다. 드모르간으로 “어떤 항목이든 유효하지 않으면 비활성화”로 바꾸면, 각 검증 함수를 OR로 연결하는 방식으로 구조가 단순해지고 변경에도 강해집니다. “첫 번째 오류 항목으로 스크롤/포커스 이동” 같은 기능도 실패 조건이 명확할수록 구현이 쉬워집니다.
로딩/빈 상태 화면 분기에서 흰 화면
앱에서 사용자 불만이 큰 문제 중 하나가 로딩이 끝난 것처럼 보이는데 아무것도 안 나오는 상태입니다. 보통 “데이터 있음 OR 로딩 중” 같은 조건이 어색하게 섞일 때 이런 문제가 생깁니다.
UI 분기는 상호배타적으로 설계하는 것이 좋고, 빈 상태 화면은 “보이면 안 되는 조건”이 더 중요할 때가 많습니다. 예를 들어 빈 상태를 숨겨야 하는 조건을 NOT 형태로 묶어 두었다면, 드모르간으로 “로딩 중이거나 데이터가 있으면 빈 상태 숨김”처럼 풀어 쓰면 충돌이 줄어듭니다. 재현이 어렵고 사용자 환경에서만 터지는 문제일수록 조건식의 명료함이 곧 품질입니다.
Feature Flag/A-B 테스트
A/B 테스트는 보통 “플래그 ON AND 대상자”일 때만 노출되어야 합니다. 그런데 대상자 조건은 국가, OS, 앱 버전, 계정 유형, 신규/기존 여부 등으로 계속 늘어납니다.
이때 노출 조건을 복잡하게 유지하기보다, 노출하지 말아야 하는 조건을 NOT(플래그ON AND 대상자)로 두고 드모르간으로 “플래그가 꺼져 있거나 대상자가 아니면 숨김”으로 만들면, 기본값이 숨김이 되어 위험이 줄어듭니다. AND 하나를 OR로 잘못 넣어 전 사용자에게 노출되는 사고도 이 구조에서 줄어드는 편입니다.
부정형 플래그
현업 코드에는 isInvalid, isDisabled, noPermission, notAvailable 같은 부정형 네이밍이 이미 널리 퍼져 있는 경우가 많습니다. 이를 전부 긍정형으로 바꾸는 것은 리스크가 큰 작업이 될 수 있습니다.
드모르간은 이런 상황에서 “부정형 플래그를 억지로 뒤집지 않고”도 조건식을 읽기 쉽게 바꿀 수 있게 해줍니다. 실패 조건을 부정 플래그 중심으로 OR로 묶으면, 로깅과 에러 메시지 매핑도 쉬워지고, 무엇 때문에 실패했는지가 구조적으로 드러납니다.