Java decrementExact() 설명: 정수 오버플로 버그 방지

발행: (2025년 12월 2일 오후 11:38 GMT+9)
5 min read
원문: Dev.to

Source: Dev.to

Math.decrementExact() 은 정확히 무엇인가요?

Math.decrementExact() 은 Java의 Math (및 StrictMath) 클래스에 있는 정적 메서드로, 정수 오버플로우가 발생하지 않을 때만 주어진 숫자에서 1을 빼줍니다.
감소 연산이 오버플로우를 일으키면 메서드는 ArithmeticException을 발생시킵니다.

// For int values
public static int decrementExact(int a)

// For long values
public static long decrementExact(long a)

연산이 안전하면 메서드는 a - 1을 반환합니다.

핵심 차이점: 안전이 먼저

표준 감소 (조용한 오버플로우)

int dangerousCounter = Integer.MIN_VALUE; // -2147483648
System.out.println("Before: " + dangerousCounter);
dangerousCounter--; // silently overflows
System.out.println("After: " + dangerousCounter);

출력

Before: -2147483648
After: 2147483647   // overflow wrapped around

decrementExact 사용 (명시적 예외)

int safeCounter = Integer.MIN_VALUE;
System.out.println("Before: " + safeCounter);
safeCounter = Math.decrementExact(safeCounter); // throws
System.out.println("After: " + safeCounter);   // never reached

결과

Before: -2147483648
Exception in thread "main" java.lang.ArithmeticException: integer overflow

예외가 빠르게 실패하도록 강제함으로써 버그를 개발 단계에서 눈에 띄게 합니다.

더 깊이 파고들기: 실생활에 적용 가능한 코드 예제

예제 1: 클래식 카운트다운 타이머

public class SessionTimer {
    public static void main(String[] args) {
        int secondsUntilLogout = 1; // start at 1 second

        System.out.println("Session ending in " + secondsUntilLogout + " seconds...");

        // Decrement to 0
        secondsUntilLogout = Math.decrementExact(secondsUntilLogout);
        System.out.println("Session ending in " + secondsUntilLogout + " seconds...");

        // Attempt to go below zero – throws
        secondsUntilLogout = Math.decrementExact(secondsUntilLogout);
    }
}

출력

Session ending in 1 seconds...
Session ending in 0 seconds...
Exception in thread "main" java.lang.ArithmeticException: integer overflow

예제 2: 재고 관리

public class InventoryManager {

    public static void updateStockSafely(int currentStock, int quantitySold) {
        for (int i = 0; i < quantitySold; i++) {
            currentStock = Math.decrementExact(currentStock);
        }
        System.out.println("Remaining stock (safe): " + currentStock);
    }

    public static void main(String[] args) {
        int stock = 5;
        int sold = 10; // trying to sell more than we have

        updateStockSafely(stock, sold); // throws an exception
    }
}

currentStock이 0 이하로 떨어질 때 decrementExact이 예외를 발생시켜, 눈에 보이지 않는 음수 재고를 방지합니다.

팁: 루프를 돌기 전에 quantitySold <= currentStock을 검증하세요; decrementExact은 최후의 안전망 역할을 합니다.

실제 사용 사례: 실제로 어디에 쓸 수 있을까?

  • 금융 애플리케이션 – 잔액이 음수에서 거대한 양수로 래핑되는 것을 방지합니다.
  • 게임 개발 – 플레이어 체력, 탄약, 혹은 목숨을 언더플로우 버그로부터 보호합니다.
  • 임베디드·제어 시스템 – 안전이 중요한 하드웨어에서 카운터가 조용히 오버플로우되지 않도록 보장합니다.
  • 자원 관리 – 풀 크기, 메모리 블록, 파일 핸들 등을 명시적인 오버플로우 감지와 함께 추적합니다.

모범 사례와 피해야 할 함정

  • 남용하지 말 것 – 오버플로우가 절대 일어나지 않을 100 % 확신이 있는 경우(예: 10부터 0까지 카운트다운)에는 단순 --를 사용해도 됩니다. 추가 검사는 미세한 오버헤드를 발생시킵니다.
  • 예외 처리 준비 – 메서드가 예외를 던질 수 있으므로, 필요에 따라 try‑catch 블록으로 감싸서 정상적인 복구를 할 수 있게 하세요.
try {
    criticalCounter = Math.decrementExact(criticalCounter);
} catch (ArithmeticException e) {
    System.err.println("Counter underflow detected! Taking corrective action.");
    // Example recovery actions:
    // - reset the counter
    // - log the incident
    // - notify an administrator
    criticalCounter = 0;
}

관련 메서드

  • Math.incrementExact(int a) / Math.incrementExact(long a) – 증가 시 오버플로우가 발생하면 예외를 던집니다.
  • Math.addExact(int a, int b) / Math.addExact(long a, long b) – 더하기 연산에서 오버플로우가 발생하면 예외를 던집니다.
  • Math.subtractExact(int a, int b) / Math.subtractExact(long a, long b) – 빼기 연산에서 오버플로우가 발생하면 예외를 던집니다.
Back to Blog

관련 글

더 보기 »

모뎀의 복수

첫 번째 연결 1994년 겨울, 홍콩의 작은 아파트에서, 14세 소년이 US Robotics Sportster 14,400 Fax Modem을 연결했다.