Python의 None, 이제 sentinel로 모호함을 끝내다

Much Ado About None: Sentinel Values in Python

Python에서 None은 '없음', '미설정', '에러' 등 여러 의미로 남용되어 혼란을 일으킨다. 캐시가 키 없음과 None 값을 구분하지 못하거나, timeout=None이 '타임아웃 없음'인지 '현재 값 유지'인지 애매한 경우가 대표적이다. sentinel 값은 유효한 값의 영역 밖에 있어 이런 충돌을 원천적으로 막는다. Python은 이미 Ellipsis, NotImplemented 같은 내장 sentinel을 활용해 왔고, Pydantic 2.14의 MISSING도 실험 단계를 벗어났다. PEP 661이 지연 끝에 승인되면서 Python 3.15부터 sentinel이 내장 함수로 제공되며, 타입 체커도 None처럼 타입 좁히기를 지원한다. 저자는 None의 모호성을 인지하고, 라이브러리가 제공하는 sentinel을 우선 사용하며, 기존 object()나 Enum 핵을 새 내장 sentinel로 대체할 것을 권한다.

sentinel 값은 유효한 값의 영역 밖에 위치한 가드 역할을 함으로써 실제 값과 절대 충돌하지 않도록 이 문제를 해결한다.
  1. shepherdjerred

    나는 sentinel 값을 정말 싫어한다. AI가 생성한 코드에서는 더더욱, 특히나 더.

    1. 날짜에 값이 없으면 0이나 빈 문자열, None을 반환하지 마라. discriminated union을 쓰고 도메인을 엄격하게 모델링하라.

    2. 데이터 모델이 None/undefined를 값으로 허용한다면, 그건 비즈니스 모델에도 그대로 반영되어야 한다. 예를 들어

    3. 중간 로딩이나 처리 상태가 있을 수 있다는 이유만으로 `name` 필드를 `string | undefined`로 만들지 마라. 그건 `Loaded<string>` 같은 걸로 모델링하는 게 낫다. 여기서 Loaded는 Result나 Optional 타입 같은 거다(이상적으로는 더 엄격하게 정의된).

    내가 TypeScript에서 수년간 해온 방식인데, 이제 AI 덕분에 멋진 패키지로 나왔다: https://github.com/shepherdjerred/monorepo/blob/main/package...

  2. pwdisswordfishq

    optional monad를 도입하지 않으려고 이렇게까지 고생하다니.

  3. lpghatguy

    Lua를 많이 쓰던 시절, 나는 None sentinel 값을 쓰는 걸 아주 좋아했다(Lua에서는 부재를 나타낼 때 'nil'을 쓴다). 그리고 Pydantic의 MISSING과 비슷한 많은 것들에 유용했다.

    이 구분은 내가 생각하기에 JavaScript의 실제로 편리한 점이고, 'null'과 'undefined'를 구분하는 것도 비슷한 이유로 때때로 유용하다.

  4. RantyDave

    "간단한 캐시는 없는 키와 None으로 매핑되는 키 모두에 대해 None을 반환한다."

    아니, KeyError를 반환한다. 적어도 그래야 한다.

  5. chowells

    좋다. Python 관용구와 호환성을 유지하면서 더 잘할 방법은 떠오르지 않는다.

이 날의 다른 글

2026-10-31