코드에서 복수형에 관한 이야기 (2 Items vs 2 Boxes)

발행: (2026년 1월 5일 오후 10:20 GMT+9)
12 min read
원문: Dev.to

Source: Dev.to

번역할 텍스트를 제공해 주시면 한국어로 번역해 드리겠습니다.

소개

간단한 콘솔 애플리케이션, 즉 작은 쇼핑 카트를 만들고 있었습니다. 특별히 화려한 것은 아니었고, 입력, 계산, 그리고 포맷된 출력을 실험해 볼 기회였죠. 제가 처음 작성한 버전은 다음과 같습니다:

import java.util.Scanner;

public class Cart {
    static void cart() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter item name: ");
        String item = scanner.nextLine();

        System.out.print("Enter price for each: ");
        double price = scanner.nextDouble();

        if (price  1 
        && !"aeiou".contains("" + word.charAt(word.length() - 2))) {
        return word.substring(0, word.length() - 1) + "ies";
    }

    return word + "s";
}

몇 가지 테스트 실행

System.out.println(pluralize("box", 2));    // boxes
System.out.println(pluralize("city", 2));   // cities
System.out.println(pluralize("class", 2));  // classes
System.out.println(pluralize("apple", 2)); // apples
System.out.println(pluralize("mouse", 2));  // mouses

결과는 대부분 올바르게 나왔습니다 (boxes, cities, classes, apples). 하지만 mouse → mouses 가 눈에 띄었습니다. 불규칙 명사는 단순한 규칙만으로는 해결될 수 없으며, 새로운 예외 상황이 생길 때마다 코드가 길어지고 더 깨지기 쉬워졌습니다.

“Even numbers are hard” – 상황에 딱 맞는 밈이었습니다.

이때 나는 “완벽하게 만들고 싶다”는 호기심이 언어 자체의 한계와 부딪히고 있음을 깨달았습니다.

ICU4J 발견

해결책을 찾아보다가 국제화와 복수형 처리를 위해 실제 운영 환경에서 사용되는 Java 라이브러리인 ICU4J를 발견했습니다. 하지만 문서를 좀 더 자세히 읽어보니 ICU4J는 실제로 단어의 철자를 바꾸지는 않는다는 것을 알게 되었습니다. ICU4J는 단수형복수형을 언제 사용할지 결정합니다. 예를 들어:

You have 1 item
You have 2 items

하지만 boxboxes로, childchildren으로 자동 변환해 주지는 않습니다. ICU4J가 해결하는 것은 범주 문제이며, 단어 형태 변화 문제는 해결하지 못합니다.

유혹적인 아이디어

실망한 나는 다른 접근법을 고민했다:

그냥 AI에게 이 일을 시켜보면 어떨까?

현대 AI 모델은 언어에 뛰어나다. 그들은 다음과 같은 변화를 알고 있다:

  • boxboxes
  • classclasses
  • mousemice
  • childchildren

이론적으로 나는 API 호출을 해서 명사를 전달하고 올바른 복수를 반환받을 수 있다. 문법 규칙도, 불규칙 명사 목록도 필요 없고, 모델에게 복잡성을 맡기면 된다.

AI 아이디어가 실제로 의미가 있는 이유 (처음에는)

이 접근 방식은 어리석은 것이 아니라 실제로 강점이 있습니다. AI 모델은:

  • 불규칙 명사를 이해한다
  • 차용어와 예외 상황을 처리한다
  • 언어에 자연스럽게 적응한다
  • 내 쪽에서는 아주 적은 코드만 필요하다

작은 개인 프로젝트라면 이 아이디어는 정말 매력적입니다. 복수형 로직을 전혀 유지할 필요가 없고, 문제를 API를 통해 AI에 위임하면 되니까요.

하지만 저는 잠시 멈추어 코더가 아니라 시스템 디자이너처럼 생각하기 시작했습니다.

첫 번째 레드 플래그: 비용

복수형 변환은 가치가 낮고 빈도가 높은 작업입니다. 사용자가 장바구니에 아이템을 추가할 때마다 AI 서비스에 네트워크 요청을 보낸다면, 누적 비용(금전적 비용과 지연 시간 모두)이 편리함을 빠르게 초과하게 됩니다.

앱이 해야 할 일:

  • 네트워크 요청을 보낸다
  • 토큰 비용을 지불한다
  • 응답을 기다린다

이 비용은 금방 쌓입니다. boxesitems 중 어느 것을 출력할지 결정하기 위해 AI 추론 비용을 지불하는 것은 정당화하기 어렵습니다. 같은 작업을 로컬에서 비용 없이 처리할 수 있다면 말이죠.

작은 스크립트나 실험 단계에서는 괜찮을 수도 있지만, 규모가 커지면 비용이 매우 빠르게 증가합니다.

두 번째 레드 플래그: 지연 시간

복수형 변환은 사용자 피드백의 핵심 경로에 위치합니다. 이는 다음 상황에서 발생합니다:

  • UI를 렌더링할 때
  • 출력문을 출력할 때
  • 빠른 상호작용 중

AI 호출은 다음을 초래합니다:

  • 네트워크 지연
  • 타임아웃 위험
  • 재시도 로직
  • 여러분이 제어할 수 없는 실패 모드(예: 500 오류)

단순히 문장을 출력하는 작업이 외부 서비스의 가용성에 의존하게 되는 것은 명백히 잘못된 설계처럼 느껴집니다.

세 번째 레드 플래그: 비결정성

이것이 가장 큰 우려 사항이었습니다. 언어는 유연하고 AI도 그 유연성을 반영합니다. 예를 들어:

  • cactuscacti
  • cactuscactuses

두 형태 모두 맞지만, 애플리케이션이 다음과 같이 출력한다면:

You bought 2 cacti

그리고 나중에:

You bought 2 cactuses

일관성이 깨집니다. “가끔은 맞는” 답변은 항상 일관된 간단한 답변보다 더 나쁜 경우가 많습니다.

네 번째 레드 플래그: 제어와 안전성

AI를 이용해 단어를 복수형으로 만들려면 사용자 입력을 외부 서비스에 보내야 합니다. 이는 여러 질문을 야기합니다:

  • 아이템 이름에 민감한 정보가 포함돼 있다면?
  • 이 데이터가 디바이스에만 남아야 한다면?
  • API 동작이 바뀐다면 어떻게 될까?

그 순간, 단순 콘솔 프로그램이 다음에 얽히게 됩니다:

  • 네트워크 접근
  • API 키
  • 개인정보 고려 사항

결국 그림이 명확해졌습니다: 복수형 변환을 위해 AI를 사용하는 것은 어려운 언어 문제를 해결하지만, 비용, 지연 시간, 일관성 부족, 의존성 등을 초래하고 완벽한 결과를 보장하지도 못합니다.

실용적인 절충

프로그램의 실제 목표가 무엇인지 스스로에게 물어볼 필요가 있었다:

  • 구매한 항목 수 표시
  • 총 비용 표시

제품 이름을 복수형으로 정확히 표기하는 것은 중요하지 않았다.

그때 깨달았다—내가 사용하는 거의 모든 앱이 같은 방식을 사용한다. 쇼핑 사이트, 알림 시스템, 대시보드 등은 임의의 명사를 복수형으로 만들려고 하지 않는다. 대신 안전하고 제어된 명사를 사용한다:

You bought 2 items
You have 5 notifications
Your cart contains 3 products

예외 상황을 처리할 필요가 없기 때문에 예측 가능하고 안전하며 확장성이 좋다. 또한 나중에 애플리케이션을 다른 언어로 번역할 때도 완벽하게 작동한다.

최종 코드 스니펫

다음은 이 반성을 거친 후 원래 쇼핑‑카트 코드가 어떻게 발전했는지 보여줍니다:

double total = price * quantity;

String message = quantity == 1 ? "item" : "items";

System.out.printf(
    "You bought %d %s. Your grand total is KES %.2f.%n",
    quantity, message, total
);

출력

You bought 1 item. Your grand total is KES 100.00.
You bought 2 items. Your grand total is KES 200.00.

경우의 수가 없고, 불규칙 명사의 사전도 없으며, 깨지기 쉬운 규칙도 없습니다. 이 접근 방식은 대규모 프로덕션 시스템이 정확히 사용하는 방식입니다.

배운 교훈

  • 호기심은 중요합니다. 코드를 개선하려는 시도는 프로그래밍, 언어, 그리고 트레이드‑오프에 대해 많은 것을 가르쳐 줍니다.
  • 언어는 복잡합니다; 간단한 복수형 처리조차도 수십 개의 엣지 케이스를 가질 수 있습니다.
  • 운영 코드에서는 단순성, 정확성, 일관성을 중시합니다.
  • ICU4J를 적절한 상황에서 사용하는 것은 도움이 되며, 모든 명사의 철자를 정확히 맞추기 위해서가 아니라 복수형을 인식하는 메시지에 사용해야 합니다.
  • 제어된 어휘를 선택하는 것이 유리합니다: 안전하고, 예측 가능하며, 유지 보수가 쉽습니다.

생각

appleapples에서 시작해 왜 앱에서 2 boxes가 거의 표시되지 않는지를 이해하는 과정은 단순히 복수형에 대한 교훈을 넘어섭니다. 이는 인간 언어가 협조하지 않을 때에도 신뢰성 있게 동작하는 소프트웨어 시스템을 설계하는 교훈입니다.

때때로 가장 간단한 해결책—예를 들어 2 items를 표시하는 것—이 가장 우아합니다.

Back to Blog

관련 글

더 보기 »

내 TicketDesk 시스템

소개: 프로그래밍 입문 모듈을 위해 Java로 TicketDesk 시스템을 만들었습니다. 이 시스템은 다음을 수행할 수 있습니다: - 티켓 추적 - 로그인 정보 추적 - 역할 기반 인증 제공