아무것도 하지 않을 거라면, 적어도 올바르게 아무것도 하지 않는 방법
(devblogs.microsoft.com)- 특정 플랫폼이나 은퇴 상태 때문에 실제 기능을 제공할 수 없어도, 기존 앱이 깨지지 않으려면 문서화된 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 동작은 계약과 일관돼야 함
- 기존 코드가 이미 처리할 수 있는 반환값과 상태를 사용하는 것이 중요함
댓글과 토론
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이 아님을 한 번 확인하라고 지시했음
Hacker News 의견들
-
오류를 삼키는 방식으로 배웠고, 좋지 않은 관행이라고 봄
Xbox에서 출력할 수 없다는 실제 문제를 해결하지 못할 뿐 아니라, 소프트웨어가 얼마나 망가졌는지 숨겨서 버그 발견과 테스트를 훨씬 어렵게 만듦
Go의panic은 런타임에서 남용하거나 복구하라고 만든 게 아니라, 테스트 시점에 프로그래머가 잘못했다는 사이렌을 크게 울려 주는 도구라서 좋음
시스템 안의 행위자들이 자기 결함이나 오류를 적극적으로 숨기면, 원인을 찾아내고 고치는 일이 기하급수적으로 어려워짐- 오류 설계는 맥락에 따라 달라짐
내가 다루는 B2B, 마이크로서비스, API 중심 시스템에서는 명세 밖 요청은 빠르게 실패시키는 게 맞음
하지만 Windows는 호환성을 위해 엄청나게 뒤로 굽혀 왔고, SimCity처럼 망가진 유명 소프트웨어를 메모리 패치까지 해가며 살린 사례도 있음: https://arstechnica.com/gadgets/2022/10/windows-95-went-the-...
사용자가 시스템 코드를 고칠 수 없는 데스크톱 환경에서는 많은 경우 정확성보다 최종 사용자 경험이 더 중요함
BSOD가 왜 났는지는 중요하지 않고, 나쁜 소프트웨어나 하드웨어 때문에 Microsoft 평판이 나빠진다는 걸 Microsoft가 배운 셈임
개인적으로는 잘못된 입력이나 조건에서 빠르게 실패하거나 중단하는 설계를 선호하지만, 이 환경에서는 이런 접근의 가치도 이해됨
중요한 건 맥락이지, 어느 한쪽을 교조적으로 적용하는 게 아님
예를 들어 원자로나 초단타 매매 설계에 Chen의 접근을 가져가면 안 되고, 게임 엔진에는 훌륭한 접근일 수 있음 - 새 플랫폼용 대체 런타임을 설계할 때는 무엇을 오류로 볼지 스스로 정하는 게 핵심임
런타임 구성요소를 “무해하게 비활성”으로 둘지 정하는 문제는, 구현이panic을 낼지 말지보다 앞서는 설계 결정임
이 경우 “Xbox에서 출력한다”의 의미를 정하는 건 Microsoft의 몫임
오류로 정의할 수도 있고, 이론적으로는 나중에 지원 가능하지만 지금은 실제 수행 방법이 없는 기능으로 정의할 수도 있음
USB 프린터를 꽂고, GB Printer를 지원하던 Gameboy 게임의 확장 포트 같은 “게임”이 출력 방법을 알고 있다면 이론상 Xbox에서도 출력할 수 있음
Xbox 게임이 출력을 시도하는 일이 반드시 본질적인 오류는 아니며, 오류로 정의하는 것도 애플리케이션 이식성 같은 트레이드오프를 가진 선택일 뿐임
Xbox처럼 선택 가능한 프린터가 없는 선택 화면을 띄울 수도 있고, API가 출력했다고 거짓말하게 만들 수도 있고, 실제 출력을 지원할 수도 있음
“Xbox에서 출력”의 의미를 오류로 정의한 뒤에야, 그 오류가 던져지지 않고 삼켜지는지가 구현이나 디버깅 문제가 됨 - 이건 오류를 삼키는 것이 아니라, Linux식 표현으로는 사용자 공간을 깨지 않는 것에 가까움
가능한 처리는 두 가지임: 기계에 프린터가 절대 없으니 오류를 내거나, 기계에 프린터가 절대 없으니 빈 프린터 목록을 반환하는 것
둘 다 타당하지만, 사용자 공간을 깨지 않는 건 하나뿐임 - 글을 읽어 보면 개발자 경험보다 사용자 경험을 더 이야기하고 있음
“사이렌을 크게 울리는 것”은 테스터나 개발자에게는 좋지만 최종 사용자에게는 별로임
최종 사용자 입장에서는 오류를 삼키는 쪽이 앱이 죽는 것보다 낫다 - 인터넷 연결이 실패했을 때 수십 년째 그저 실패했다는 메시지만 뜨는 게 짜증남
무엇이 실패했는지 알 수 없음: 내 컴퓨터의 소프트웨어, 하드웨어, 이더넷 케이블이나 Wi-Fi, 스위치, 라우터, 케이블 모뎀, 집까지 오는 인터넷 케이블, ISP, 접속하려는 원격 시스템 중 어디인지 전혀 개선되지 않았음
- 오류 설계는 맥락에 따라 달라짐
-
부정적으로 반응하는 건 예상되지만, 이런 지저분한 일이 바로 Word ’97 문서나 30년 전 MS-DOS용으로 컴파일된 게임을 클릭했을 때 기대한 대로 열리는 이유임
하위 호환성은 항상 messy하고, 불완전하게 하거나 아예 하지 않거나 둘 중 하나임- Microsoft에 대해 그런 후렴을 자주 듣지만, 게임에서는 운이 좋지 않았음
결국 GOG를 쓰게 되고, GOG도 결국 환경을 가상화함
예를 들어 원본 Sim City를 Windows 11에 설치해 성공할 사람은 없을 것 같음 - Word ’97에서 작성한 파일은 25년 전에도 서로 다른 두 컴퓨터에서 정확히 기대한 대로 열리지 않았음
서식은 설치된 프린터 드라이버에 의존했음
반면 35년 전 LaTeX 파일은 지금도 잘 됨 - 1997년 파일이라도 운이 좋아야 하고, 어떤 오피스 앱에서 열어도 그냥 잘못 보일 가능성이 큼
Word는 같은 컴퓨터와 같은 버전에서 다시 열어도 서식이 바뀌지 않는다고 보장할 수 없었고, 그래서 TeX를 배우게 됨
게임도 Microsoft가 GFWL을 종료하면서 수많은 게임을 망가뜨렸음
원본 Dark Souls는 Steam에 재출시되기 전까지 플레이할 수 없어서 해적판을 써야 했음 - 최신 64비트 Windows에서는 MS-DOS 소프트웨어가 동작하지 않음
“지원되지 않음” 대화상자가 뜨고, dosbox를 다운로드할 수는 있지만 그건 “정확히 기대한 대로”는 아님 - 이 말이 정말이면 좋겠지만, 어린 시절 보관해 둔 게임들을 실행시키느라 엄청 고생했음
거의 매번 포기하거나 GOG에서 다시 샀고, 사실상 호환성 문제를 정리해 둔 작업에 돈을 낸 셈임
- Microsoft에 대해 그런 후렴을 자주 듣지만, 게임에서는 운이 좋지 않았음
-
실제로는 존재할 수 있는 것처럼 UI가 암시하지만 지금은 없다고 나오는 장치 UI만큼 답답한 게 없음
결국 시간을 들여서야 그 장치들이 지원되지 않고, 그 화면은 누군가 만든 목업일 뿐이었다는 걸 알아내야 함- 그래도 앱이 그냥 죽는 것보다는 덜 답답할 것임
앱이 출력 미지원 상황을 대비하지 않았는데 출력이 예외를 던지면, 앱은 아마 그대로 죽음
출력 미지원을 대비한 앱이라면 명시적 API로 출력 지원 여부를 먼저 확인하고, 지원되지 않으면 출력 UI를 보여주지 않아야 함
글은 그런 앱이 아니라, 먼저 확인하지 않는 앱을 어떻게 처리할지에 대한 이야기임
버그는 앱에 있지만, 좋은 플랫폼은 나쁜 앱도 그냥 죽게 두기보다 최대한 동작하게 만들려고 해야 함 - 여기서는 Microsoft가 아니라 소프트웨어 작성자가 프린터 상황을 처리하지 않은 책임이 클 수 있음
Microsoft의 역할은 소프트웨어 제공자가 프린터를 고려하지 않았다고 해서 앱이 죽지 않게 하는 데 있음
- 그래도 앱이 그냥 죽는 것보다는 덜 답답할 것임
-
앱이 출력하려고 할 때 사용자에게 프린터를 선택하라고 하고 빈 목록을 보여주는 동작이라니, Microsoft가 30년 동안 배우지 못한 듯함: https://www.reddit.com/r/hacking/comments/djvzd/windows_nt_l...
-
글에서 제안한 구체적 방향, 즉 사용자가 고통받기 전에 구성요소가 고통받아야 한다는 말은 맞지만, 프레이밍은 매우 거슬림
“API가 아무 일도 하지 않게 만들어야 할 때가 있다”, “출력 함수가NotSupportedException을 던지는 건 틀렸다”는 식은 절대 일반 조언이 아님
이건 형편없는 클라이언트를 지원하기 위한 해킹이고, 가끔 필요하긴 하지만 정상적이거나 일반화할 수 있는 조언은 아님
이런 표현에는 Microsoft 개발자로서의 고통을 내면화한 흔적이 드러남- 형편없는 클라이언트가 아니라, 당신이 이 변경을 결정하기 전에 작성된 클라이언트임
클라이언트가 바뀌지 않았는데 API가 그것을 깨뜨린다면, 형편없는 건 클라이언트가 아니라 API임 - 소프트웨어 플랫폼이 소수 이상의 개발자에게 채택됐다면 형편없는 앱도 생기게 마련이고, 그러면 이런 일을 해야 함
널리 채택되고 하위 호환성을 진지하게 여기는 모든 플랫폼에는 완전히 정상적이고 일반화 가능한 일임
Windows가 대표적 사례지만 Linux 커널 ABI, glibc, 웹 플랫폼, Java 등에서도 같은 일이 벌어짐 - 기존 클라이언트가 이미 쓰고 있는 API를 구현해야 할 때가 있음
시간을 되돌려 클라이언트를 다시 컴파일하거나 다시 작성할 수는 없음
클라이언트가 이미NotSupportedException을 검사하고 있다면 그걸 반환해야 하지만, 그렇지 않다면 다른 접근이 필요함 - Windows 팀에 있으면서 그런 태도를 보였다면, 내가 관리자라면 해고했을지도 모름
여기는 Windows임
사용자가 의존하는 애플리케이션을 깨뜨리면 안 됨
“형편없거나” 잘못 동작하는 클라이언트 앱이 있으면, 기대한 대로 동작하게 만들기 위해 필요한 우회책, shim, 호환성 해킹을 모두 써야 함
SimCity가 동작하도록 특수한 메모리 관리 코드를 넣어야 하더라도 마찬가지임 - 그 “형편없는 클라이언트”는 오래전에 폐업한 회사가 작성했을 수 있음
당신의 고객은 그 클라이언트에 의존하고 있고, 당신이 바꾼 것 때문에 멈추면 당신을 탓할 것임
- 형편없는 클라이언트가 아니라, 당신이 이 변경을 결정하기 전에 작성된 클라이언트임
-
여기서는 모두 “아무것도 안 하기”와 “오류 처리”에 매달리지만, 글이 모든 문제를 삼키고 kumbaya를 부르자는 게 아니라는 설명을 잘 못한 듯함
실제 맥락은 바뀌지 않을 소프트웨어를 위한 에뮬레이션과 호환성이고, 대부분의 상황과는 매우 다름
Microsoft 스스로도 둘의 경계를 자주 흐려서 더 헷갈리지만, 여기서 말하는 건 일반적인 오류 처리가 아님
에뮬레이션은 본질적으로 거짓말을 하는 일임
Xbox에는 실제로 프린터를 붙일 방법이 없고, Linux에서 Windows 게임을 돌리고 있으며, 가짜 iPhone은 사실 AWS의 ARM 서버일 수 있음
거짓말을 할 거라면 설득력 있게 해야 하고, 그래야 기존 애플리케이션이 계속 동작함
Microsoft가 기존 Windows 앱을 Xbox로 포팅할 수 있다고 말할 때 Windows 앱에는 출력할 수 있다는 약속이 있었으니, Xbox는 그 일이 가능해 보이도록 거짓말해야 함
반면 프로그램이 use-after-free를 하고 있는데 버그가 없는 척 조용히 우회한다면 그건 올바른 처리가 아님
기존 use-after-free까지 새 플랫폼에서 버그 단위로 호환되리라고 약속한 사람은 없기 때문임- 글 어디에도 바뀌지 않을 소프트웨어를 위해 에뮬레이션을 한다는 맥락은 없음
그런 해석이 원하는 입장을 지지하니까 가정한 것일 뿐임
실제로 글의 내용은 내가 내일 Xbox용 프로그램을 작성하고 출력하려 할 때도 그대로 적용됨
이 동작이 오래되고 유지보수되지 않는 소프트웨어에만 해당한다고 구분하는 내용은 없음
- 글 어디에도 바뀌지 않을 소프트웨어를 위해 에뮬레이션을 한다는 맥락은 없음
-
이 접근은 좋기도 하고 싫기도 함
본능적으로는 악의적 준수로 문제를 다루는 걸 좋아하지 않음
반면 출력이 망가져 있더라도 더 많은 사용자가 더 많은 소프트웨어를 플랫폼에서 실행하게 만드는 게 목표라면 좋은 판단이라는 데는 완전히 동의함 -
이 댓글 흐름은 이상했음
Microsoft가 하는 일이라면 뭐든 싫어하는 사람이 분명히 있음
블로그의 핵심은 앱(UWP)을 XBOX로 가져오는 과정을 마찰 없이 만드는 것임
재컴파일도, 지저분한ifdef도, 추가 작업도 없이 앱이 “그냥 동작”하게 하고, 그다음 개발자가 앱을 XBOX 플랫폼에 맞게 조정하면 됨
중요한 건 개발자가 아무 노력 없이 앱을 XBOX로 가져올 수 있었다는 점이고, 이는 플랫폼과 개발자 모두에게 좋음
사용자에게는 프린터 목록이 비어 있으니 출력할 수 없다는 명확한 신호가 됨
무엇보다 앱이 죽거나 “문제가 발생했습니다. 나중에 다시 시도하세요” 같은 최악의 오류를 보여주지 않음
그 메시지가 더 나은 사용자 경험은 아님
개발자가 앱을 다시 컴파일해 더 설명적인 메시지를 넣을 수는 있지만, 그러면 다시 원점으로 돌아감- 이 스레드의 95%는 글을 이해하지 못한 것 같음
예를 들어 오류를 삼킨다는 비난은 핵심이 전혀 아님
- 이 스레드의 95%는 글을 이해하지 못한 것 같음
-
이 글을 비판하는 쪽이 놓치는 핵심은, 여기에는 예외를 던져야 할 예외적 상황이 없다는 점임
이 장치에는 프린터가 연결되어 있지 않고, 이 경우에는 정의상 그렇기 때문에 앱은 그 상황을 깔끔하게 처리해야지 죽으면 안 됨
노트북이 프린터에 접근할 수 없다고 해서 예외를 던지지는 않을 것임- 널리 쓰이는 비Microsoft 제품이 프린터 가용성을 잘못 처리하는 현대적 사례를 원한다면 gnome-control-center가 있음
설정에서 프린터를 추가한 뒤 설치 중에 “Color Profiles” 탭으로 넘어가면, 타이밍이 맞을 때 gnome-control-center가 죽음
자세히 보면 사용 가능한 프린터를 열거하려고 했는데, 프린터가 있어야 한다는 건 알지만 아직 정보가 존재하지 않아 그대로 죽는 것임
다행히 GNOME이 프린터 설치를 끝낼 때까지 몇 초 기다렸다가 설정을 다시 열면 됨
그래도 다양한 배경의 최종 사용자가 데스크톱을 제대로 쓰게 해주는 핵심 앱이라면 이상적인 세계에서는 절대 죽지 않아야 함
경계 조건을 생각하는 건 어렵고, 경계 조건 처리 자체에도 또 다른 경계 조건이 있음을 상상하는 건 더 어려움
맞든 틀리든, 적어도 글쓴이는 “나쁜 앱이니 Wayland를 지원하도록 다시 작성해야 한다”보다 더 깊게 생각하고 있음
- 널리 쓰이는 비Microsoft 제품이 프린터 가용성을 잘못 처리하는 현대적 사례를 원한다면 gnome-control-center가 있음
-
한때 브라우저가 HTML 코드에 오류가 있어도 최선을 다해 페이지를 표시하는 게 훌륭한 전략으로 여겨졌음
작성자의 의도를 최대한 추측해서 진행하고, 오류는 나쁘며 사용자는 오류를 원하지 않는다는 식이었음
그 경험에서 배웠다고 생각했는데, 아닌 모양임- 브라우저는 여전히 그 전략을 따름
엄격한 검증으로 대체하려던 XHTML 시도는 실패했고, 대신 성공한 HTML5는 돌아가서 가능한 모든 잘못된 시퀀스를 어떻게 해석해야 하는지 명시적으로 정의해 브라우저들이 최소한 일관되게 동작하도록 만들었음 - 브라우저가 입력에 관대했던 덕분에 현대 웹이 가능해졌음
초기 브라우저가 처음 보는 태그를 만나자마자 오류를 표시했다면, 새 브라우저 기능은 태어나자마자 질식했을 것임 Hello와World!를 입력해 보면 우리가 얻은 지혜 덕분에 이제 오류가 뜨는지 알 수 있음
그런데 여전히 잘 렌더링된다면, 아직 배울 게 많다는 뜻이거나 특정 종류의 오류는 우아하게 처리하고 예외적 상황에서는 죽는 방식에도 의미가 있다는 뜻일 수 있음- 지난 20년간 소프트웨어의 발전은 LLM을 제외하면 별로 훌륭하지 않았고, LLM도 검열로 망쳐졌음
1999년으로 시간 이동해도 크게 아쉬울 게 없을 것 같음 - 우리가 무엇을 배웠다고 생각했는지 궁금함
- 브라우저는 여전히 그 전략을 따름