- 특정 플랫폼이나 은퇴 상태 때문에 실제 기능을 제공할 수 없어도, 기존 앱이 깨지지 않으려면 문서화된 API 계약 안에서 “아무것도 하지 않는” 동작을 설계해야 함
- Xbox처럼 인쇄 인프라가 없는 환경에서는
NotSupportedException보다 프린터가 0개인 성공 응답이 PC 기준으로 작성된 앱에 더 안전함 - 이런 방식은 inert API로, API 표면과 명세는 유지하되 실제로 유용한 작업은 하지 않게 만드는 설계임
- 은퇴하는 위젯 API에서
CreateWidget이 성공하면서nullptr을 반환하면 호출자가 모순된 상태를 겪으므로, 문서화된ERROR_CANCELLED실패 경로가 더 일관됨 - 올바른 inert API는 기능만 사라지게 하고, 기존 코드가 이미 대비한 실패 경로를 사용해 예외·잘못된 핸들·크래시를 줄임
기능이 없어도 API 계약은 남아 있음
- API가 아무 일도 하지 않게 만들어야 하는 경우가 있지만, 그 무동작도 기존 코드와 문서화된 동작에 맞아야 함
- 잘못 설계된 무동작은 예외, 모순된 반환값, 유효하지 않은 상태를 만들어 앱 크래시나 불필요한 사용자 오류로 이어질 수 있음
Xbox에서 인쇄 API를 무력화하는 방식
- Windows에는 광범위한 인쇄 인프라가 있지만 Xbox에는 해당 인프라가 없음
- Xbox에서 앱이 인쇄를 시도할 때 인쇄 함수가
NotSupportedException을 던지면 문제가 커질 수 있음- Xbox에 설치된 앱은 주로 PC에서 테스트됐을 가능성이 큼
- PC에서는 인쇄가 항상 가능하므로, 처리되지 않은 예외가 앱 크래시로 이어질 수 있음
- 예외를 잡더라도 사용자는 “지원팀에 incident code를 제공하라” 같은 오류 메시지를 볼 수 있음
- 더 나은 설계는 인쇄 함수가 성공하되 설치된 프린터가 없음을 보고하는 것임
- 앱은 프린터 선택 UI를 띄우고 빈 목록을 표시함
- 사용자는 프린터가 없다는 사실을 보고 인쇄 요청을 취소할 수 있음
- 프린터 설치를 도와주려는 앱에는 설치 함수가 즉시 반환하면서 사용자가 작업을 취소함을 뜻하는 결과 코드를 줄 수 있음
inert API의 조건
- 이런 “아무것도 하지 않는” 동작을 inert라고 부름
- inert API는 API 표면이 그대로 존재하고 명세에 맞게 동작하지만, 실제로는 아무 유용한 작업도 하지 않음
- 핵심은 문서와 일관되면서 기존 코드에 문제를 만들 가능성이 가장 낮은 방식으로 아무것도 하지 않는 것임
- 인쇄 API에는 인쇄 자체가 가능한지 확인하는 함수를 추가할 수도 있음
- 앱은 이 함수를 사용해 인쇄를 전혀 지원하지 않는 시스템에서 Print 버튼을 숨길 수 있음
- 단순히 인쇄가 가능하다고 가정하는 앱도 “프린터가 없고 설치 시도도 효과가 없는 시스템”처럼 동작하게 됨
은퇴하는 위젯 API에서 피해야 할 설계
- 은퇴 대상 API에는 위젯 핸들을 만드는 함수, 위젯 핸들을 받는 함수, 위젯 핸들을 닫는 함수가 있음
- 초기 제안은
CreateWidget이S_OK를 반환하면서*widget = nullptr을 설정하는 방식이었음- 호출은 성공했지만 유효한 핸들을 받지 못하는 상태가 됨
- 실제 테스트 코드 중에는 반환값이 아니라 핸들이
null인지로 성공 여부를 판단하는 코드가 있었음
EnableWidget이 “잘못된 핸들”을 반환하는 설계도 호출자를 혼란스럽게 함- 앱은
CreateWidget성공 후 받은 핸들을EnableWidget에 전달함 - API는 그 핸들이 유효하지 않다고 응답함
- 호출자는 “위젯을 요청했고 받았는데, 다시 보여주니 위젯이 아니라고 하는” 모순된 상태를 겪게 됨
- 앱은
문서화된 실패 경로로 고친 설계
- 기존 문서에는 사용자가 위젯 생성을 취소했다는 의미의
ERROR_CANCELLED반환값이 있음 - 앱은 이미 외부 조건 때문에 위젯이 생성되지 않을 가능성을 다뤄야 하므로, 위젯 생성이 항상 사용자 취소로 실패하게 만들 수 있음
- 수정된 설계의 흐름은 단순함
CreateWidget은*widget = nullptr로 두고HRESULT_FROM_WIN32(ERROR_CANCELLED)를 반환함- 위젯 생성이 항상 실패하므로 유효한 위젯 핸들은 존재하지 않음
GetWidgetAliases,EnableWidget,Close는 핸들이 유효하지 않다는E_HANDLE을 반환함
- 이 방식에서는 위젯이 없으므로 더미 alias를 만들 필요도 없음
- 유효한 위젯이 존재하지 않기 때문에 앱이 정상적으로 alias를 요청할 수 있는 경우도 없음
데스크톱 API를 다른 환경으로 가져갈 때의 기준
- 데스크톱에서는 인쇄 API가 항상 존재했고, “프린터 목록을 가져오는” 함수는 예외를 던지지 않도록 문서화돼 있음
- 이 API를 Xbox로 가져갈 때 기존 데스크톱 앱이 계속 실행되게 하려면, “Xbox에는 프린터가 없다”는 사실을 정직하게 반환하는 inert 동작이 맞음
- “프린터가 몇 개 있는가?”라는 질문에 예외를 던지는 것은 문서화된 API 계약과 맞지 않음
- 기존 API를 은퇴시킬 때도 같은 원칙이 적용됨
- 유용한 작업은 하지 않더라도 API 동작은 계약과 일관돼야 함
- 기존 코드가 이미 처리할 수 있는 반환값과 상태를 사용하는 것이 중요함