2P by GN⁺ | ★ favorite | 댓글 2개

API가 아무것도 하지 않을 때, 올바르게 아무것도 하기

  • API가 아무것도 하지 않아야 할 때, 그것이 올바른 방식으로 아무것도 하지 않도록 하는 것이 중요함.
  • 예를 들어, 윈도우에는 방대한 인쇄 인프라가 있지만, Xbox에는 그런 인프라가 없음.
  • Xbox에서 앱이 인쇄를 시도할 때 NotSupportedException을 던지는 것은 잘못된 방식임.
  • 앱이 PC에서 주로 테스트되었기 때문에 Xbox에서 실행될 때 예외 처리가 되지 않고 앱이 충돌할 수 있음.
  • Xbox에서 인쇄 기능을 "지원"하는 더 나은 설계는 인쇄 함수가 성공하되 설치된 프린터가 없다고 보고하는 것임.
  • 사용자가 인쇄를 시도하면 프린터 선택을 요청하지만 목록이 비어 있어 사용자는 "프린터가 없구나"라고 깨닫고 인쇄 요청을 취소함.
  • 프린터 설치를 시도하는 앱을 위해 프린터 설치 함수는 "사용자가 작업을 취소했다"는 결과 코드와 함께 즉시 반환할 수 있음.
  • 인쇄 기능이 완벽하게 지원되는 것처럼 행동하지만 실제로는 프린터가 없는 것처럼 행동하는 것이 목표임.
  • 인쇄가 전혀 작동하지 않는 시스템에서는 인쇄 버튼을 UI에서 숨기기 위해 인쇄 가능 여부를 확인하는 함수를 추가할 수 있음.
  • 이러한 행동을 "무효(inert)"라고 부름.
  • API 표면은 여전히 존재하고 명세에 따라 기능하지만 실제로는 아무것도 하지 않음.
  • 중요한 것은 문서화된 방식과 일관되게 아무것도 하지 않아 기존 코드와의 문제를 최소화하는 것임.

API 비활성화 예시

  • 위젯 핸들을 생성하는 다양한 함수, 위젯 핸들을 받는 함수, 위젯 핸들을 닫는 함수를 포함하는 API를 비활성화하는 예시가 있음.
  • 팀은 처음에 CreateWidget이 성공하지만 null 포인터를 반환하도록 하여 API를 비활성화하는 것을 제안함.
  • 그러나 이 방식은 앱이 혼란스러워 할 수 있음. "호출은 성공했지만 유효한 핸들을 받지 못했다고?"
  • EnableWidget이 "잘못된 핸들"을 반환하는 것도 혼란을 야기할 수 있음.
  • 기존 문서에서 위젯 생성이 사용자에 의해 취소되었다는 것을 의미하는 ERROR_CANCELLED라는 반환값을 찾아냄.
  • 따라서 앱이 위젯을 생성하려고 할 때마다 "아니요, 사용자가 취소했다"고 말하는 것이 가능함.

GN⁺의 의견

  • 이 글에서 가장 중요한 것은 API가 아무것도 하지 않을 때, 그것이 사용자 경험을 해치지 않고 기존 코드와의 호환성을 유지하는 방식으로 아무것도 하지 않아야 한다는 점임.
  • 이러한 접근 방식은 개발자들에게 API 설계의 중요성을 강조하며, 사용자 친화적인 소프트웨어 경험을 제공하는 데 기여함.
  • 이 글은 소프트웨어 엔지니어링의 세심한 측면을 보여주며, 예상치 못한 환경에서도 앱이 우아하게 실패할 수 있는 방법을 탐구하는 흥미로운 사례를 제공함.

댓글과 토론

Hacker News 의견
  • "에러를 삼키는 것"에 대한 의견:

    • 에러를 숨기는 것은 좋지 않은 관행임.
    • 문제를 해결하지 않고 소프트웨어의 결함을 숨김으로써 버그 발견과 테스팅을 더 어렵게 만듦.
    • Go 언어의 panic은 테스팅 시 프로그래머의 실수를 크게 알리는 좋은 방법임.
    • 시스템 내의 액터들이 자신의 결함을 숨기려고 하면 문제를 파악하고 해결하는 것이 훨씬 어려워짐.
  • 역호환성에 대한 의견:

    • 역호환성은 언제나 지저분한 작업이며, 완벽하지 않으면 아예 하지 않는 것 사이의 선택임.
    • Word '97이나 MS-DOS용 게임 파일을 클릭하면 오늘날 컴퓨터에서도 예상대로 열리는 것은 이러한 이유 때문임.
  • UI 디자인에 대한 불만:

    • 존재할 수도 있는 장치를 제안하는 UI는 매우 답답함.
    • 실제로 지원되지 않는 장치를 발견하는 데 시간을 낭비하게 됨.
  • Microsoft의 학습 부족에 대한 지적:

    • Microsoft는 30년이 지나도 여전히 같은 실수를 반복하고 있음.
    • 앱이 프린터를 찾으려 할 때 빈 목록을 보여주는 것은 이전의 문제를 반복하는 것임.
  • Xbox의 프린팅 미지원에 대한 의견:

    • Xbox가 프린팅을 지원하지 않는 것은 Microsoft가 그렇게 정의했기 때문임.
    • 하드웨어적으로는 다른 Windows 기기와 프린팅 능력이 동일함.
    • 이러한 "해결책"은 Microsoft의 비합리적인 결정으로 인한 문제임.
  • API 사용에 대한 조언:

    • 사용자보다 컴포넌트가 먼저 문제를 겪어야 한다는 것은 맞지만, 저자의 표현 방식에는 동의할 수 없음.
    • 프린팅 함수가 NotSupported­Exception을 던지는 것이 잘못된 것은 아님.
    • 저자가 설명하는 것은 불량한 클라이언트를 지원하기 위한 해킹임.
  • "악의적인 순응"에 대한 감정:

    • 문제를 다루는 방식에 대해 좋아하면서도 싫어함.
    • 그러나 플랫폼에서 더 많은 사용자가 더 많은 소프트웨어를 실행할 수 있게 하는 것이 목표라면 이 방법이 좋음.
  • 보안에 대한 긍정적인 의견:

    • API 호출을 올바르게 무시하는 것은 프로그램이 더 해로운 행동을 하는 것을 방지함.
  • 브라우저 전략에 대한 회고:

    • HTML 코드에 오류가 있어도 최선을 다해 페이지를 표시하려는 전략이 한때는 좋은 전략으로 여겨짐.
    • 사용자는 오류를 원하지 않으며, 이러한 경험에서 배웠어야 함.
  • 예외 처리에 대한 비판자들의 오해:

    • 예외를 던질 필요가 없는 상황에서 비판자들이 놓치고 있는 점이 있음.
    • 장치(프린터)가 연결되어 있지 않은 경우 앱은 그 상황을 깔끔하게 처리해야 하며, 충돌해서는 안 됨.
Lobste.rs 의견들
  • 여기서 말하는 건 인쇄 기능들이 인쇄가 완전히 지원되는 것처럼 일관되게 동작하지만, 이상하게도 실제로 인쇄할 프린터는 절대 없다는 뜻인데, 이러면 많은 게 설명됨
    농담은 제쳐두고, 이런 과도하게 방어적인 프로그래밍과 사용자 경험에는 동의하지 않음. 이렇게 하면 소프트웨어가 이유도 모른 채 제 역할을 하지 않고, 왜 그런지 알아낼 방법도 없어짐. 앱은 오류를 잡아서 가능하면 사용자 친화적인 메시지를 만들고, 아니면 원래 오류 메시지라도 사용자에게 보여줘야 함. 백그라운드 작업이면 오류 로그가 있어야 함
    이 글이 앱 개발자가 아니라 API 개발자의 관점에서 쓰였다는 점은 인정함. 그러니 API 오류를 문서화하고, 호출하는 쪽에서 조치할 수 있는 오류 메시지를 제공해야 함
    또 접근 권한이 없다는 이유로 UI에서 버튼을 숨기는 것도 싫음. 공간이 허락한다면 버튼을 보여주되 비활성화하고, 사용자가 마우스를 올렸을 때 어떻게 활성화할 수 있는지 알려주는 메시지를 제공하는 편이 낫다고 봄
    • 이 글은 단순한 API 개발자가 아니라 Windows API 개발자의 관점이라는 점도 감안해야 함. Windows API는 버전이 바뀌어도 호환성을 깨지 않아야 한다는 게 Microsoft의 오랜 입장임
    • 이건 전형적인 포스텔의 법칙 / 견고성 원칙 논의임. 이제는 견고성 원칙이 낡았고, HTML이나 제대로 된 파서를 작성하기 어려운 거대한 프로토콜·파일 형식 같은 괴물들을 낳았다는 걸 다들 알고 있음
      전반적으로는 정확성을 요구하는 편이 낫다. 다만 기존 사용자가 10억 명이라면, 가능한 한 깨뜨리지 않는 게 매우 현명하고, 사용자 입장에서는 그냥 동작하므로 시스템 차원의 실제 가치도 생김. 결국 태도는 빨리 실패하되, 많이 실패하게 만들지는 말라가 되어야 함
    • 이 경우에는 기존 API 중 하나가 문서화된 오류를 갖고 있지 않아서, 애초에 오류 처리가 없을 가능성이 큼. 기존 소프트웨어를 모두 깨고 싶지 않다면 선의의 거짓말을 해야 함
      이건 API보다는 ABI 안정성에 가까움. Windows에서는 15년 전에 빌드된 소프트웨어도 가능한 한 새 운영체제에서 계속 동작해야 함. 함수 시그니처를 바꿀 수 없으니, 더 이상 의미가 없는 API도 계속 돌아가게 하려면 선의의 거짓말을 해야 함
      예를 들어 API는 아직도 Active Desktop이 존재하는 척함. 대안은 오래된 기존 소프트웨어를 대거 깨뜨리는 것이기 때문임
    • 정말로 동의함. 어떤 이유로 내 화면에는 안 보이지만, 옆에서 설명하는 사람이나 튜토리얼에는 보이는 버튼을 찾느라 헤매는 것만큼 답답한 일이 없음
      그 기능이 사라진 건지, 그사이에 다른 화면으로 묻힌 건지 알 수 없게 됨
    • 앱이 오류를 잡고 사용자에게 보여줘야 하는 건 맞음.
      하지만 앱이 그렇게 하지 않으면, 그 앱을 쓰는 사람들은 Windows를 탓함. 앱이 아니라 Windows를 탓하고, 심지어 앱이 충돌해도 마찬가지임
      그래서 Microsoft가 우회책을 만드는 것임. 인쇄 작업이 그냥 사라지게 두는 편이 훨씬 쉽고, 그러면 사용자가 잠깐 생각하다가 “아 맞다, 프린터가 없지”라고 받아들이게 됨
  • 프린터 설치 함수가 즉시 반환하면서 결과 코드로 사용자가 작업을 취소함을 돌려줄 수 있다면, 애플리케이션 지원 입장에서는 인쇄 API가 처음부터 예외를 던지는 것보다 훨씬 다루기 나쁜 원치 않는 동작으로 이어질 가능성이 거의 확실함
  • 요즘 AI 보조 프로그래밍을 많이 하는데, 에이전트가 null 여부를 확인하는 if 검사를 자주 넣는 걸 봄. 그런 걸 볼 때마다 이 글이 떠오름
    그래서 에이전트에게 null 검사를 반복하지 말고 무해한 함수를 쓰게 하며, 선언 시점에 값이 절대 null이 아님을 한 번 확인하라고 지시했음