sayu.day

비트 연산과 비트마스크 실전 활용

비트 연산은 정수를 이진수 단위로 다뤄 집합 연산이나 상태 압축을 빠르게 처리할 수 있게 해줍니다. 이 글에서는 기본 연산자의 의미를 표로 정리하고, 비트마스크로 집합을 다루는 실전 패턴과 실무 활용 사례를 예제 코드로 살펴봅니다.

연산자 요약

연산자 의미 예시 (a=10, b=6)
& 둘 다 1이면 1 (AND) 10 & 6 = 2
| 하나라도 1이면 1 (OR) 10 | 6 = 14
^ 다르면 1 (XOR) 10 ^ 6 = 12
~ 비트 반전 (NOT) ~10 = -11 (2의 보수)
<< 왼쪽 시프트 10 << 1 = 20
>> 부호 유지 오른쪽 시프트 10 >> 1 = 5
>>> 0 채움 오른쪽 시프트 -1 >>> 1 = 2147483647 (JS)

비트마스크 기본 패턴

아래 예시는 정수 mask가 집합 역할을 한다는 가정입니다.

i번째 원소 존재 확인

const exists = (mask & (1 << i)) !== 0;

i번째 원소 추가

mask = mask | (1 << i);

i번째 원소 제거

mask = mask & ~(1 << i);

i번째 원소 토글

mask = mask ^ (1 << i);

공집합/전체집합

const empty = 0;
const full = (1 << n) - 1; // n개 원소를 모두 포함

최하위 1비트 추출

const lowestBit = mask & -mask;

최하위 1비트 제거

mask = mask & (mask - 1);

부분집합 순회

특정 집합(setMask)의 모든 부분집합을 순회할 때는 다음 패턴을 사용합니다.

for (int sub = setMask; ; sub = (sub - 1) & setMask) {
  // sub 사용
  if (sub == 0) break;
}

실무에서 자주 쓰는 지점

  • 권한 플래그 관리(READ, WRITE, ADMIN)를 비트 단위로 저장.
  • 그래프/DP 문제에서 부분집합 상태 압축.
  • 네트워크/프로토콜 파싱 시 헤더 플래그 추출.

주의사항

  • 언어별 정수 비트폭(int32, int64)이 다르면 결과가 달라질 수 있습니다.
  • 음수와 >>, >>> 동작 차이를 반드시 확인해야 합니다.
  • 가독성이 급격히 떨어질 수 있으므로 상수 이름을 강제하는 것이 안전합니다.

정리

비트 연산은 빠르지만, 성능보다 중요한 것은 "의도 명확성"입니다. 매직 넘버 대신 상수와 헬퍼 함수를 써서 유지보수성을 확보하는 것이 실무 기준입니다.