Kenneth Reitz - 2026년 3월
우리는 지난 15년 동안 인간이 시스템과 상호작용하는 방식에 대해 고민해 왔습니다. 시작은 HTTP 라이브러리였고 어쩌다 보니 의식 연구에 이르게 되었지만, 그 중간 지점—이 철학이 가장 솔직하게 시험받는 곳—은 바로 결혼 생활입니다.
이것은 억지로 끼워 맞춘 비유가 아닙니다. 진심으로 그렇게 생각합니다. 아내 사라(Sarah)와 내가 새벽 3시에 누가 일어나서 아들 말라카이(Malachi)를 돌볼 것인지에 대해 의견 차이를 조율할 때, 내 뇌의 일부는 이 상호작용을 API 계약(Contract)과 에러 핸들링(Error handling)의 관점에서 처리하고 있습니다. 내가 감정적으로 망가졌기 때문이 아니라(음, 꼭 그것 때문만은 아닙니다), 소프트웨어를 인간답게 만드는 원칙이 관계를 지속시키는 원칙과 동일하다는 사실을 깨달았기 때문입니다.
"인간을 위한(for humans)" 철학은 HTTP에서 시작해서 HTTP로 끝나지 않았습니다. 그것은 대부분의 시스템이 기계의 논리에 사람을 맞추도록 강요한다는 사실을 알아차린 데서 시작되었습니다. 결혼도 하나의 시스템입니다. 두 사람이 함께 구축하고, 문서 하나 없이 수십 년 동안 유지 관리해야 하는, 아름답고도 두려우며 더 이상 단순화할 수 없을 만큼 복잡한 시스템 말입니다. 세계에서 가장 인기 있는 HTTP 라이브러리를 만들면서 배운 것들을 내 인생에서 가장 중요한 관계에 적용해 본 결과는 다음과 같습니다.
합리적인 기본값 (Sensible Defaults)
Requests를 설계할 때 가장 중요한 결정은 사용자가 아무것도 지정하지 않았을 때 어떤 일이 일어나야 하는가였습니다. 즉, 기본값은 무엇이어야 할까요?
import requests
# 그냥 작동합니다.
# SSL 검증: 켜짐. 리다이렉트: 따라감.
# 인코딩: 자동 감지. 타임아웃: 합리적 수준.
# 사용자는 이 중 어느 것도 고민할 필요가 없습니다.
response = requests.get('https://example.com')
훌륭한 기본값의 마법은 문제가 생기기 전에 미리 방지한다는 점입니다. 라이브러리가 보안을 원할 것이라고 가정하기 때문에 SSL 검증을 설정할 필요가 없습니다. 라이브러리가 URL이 실제로 가리키는 곳에 도달하기를 원한다고 가정하기 때문에 리다이렉트를 수동으로 처리할 필요가 없습니다. 일반적인 상황에서는 그냥 잘 작동합니다. 소프트웨어에서 좋은 기본값은 대부분의 사용자에게 무엇이 필요한지에 대한 메인테이너의 지혜를 담고 있습니다. 결혼 생활에서 좋은 기본값은 관계를 유지하는 요소에 대한 부부의 공유된 이해를 담고 있습니다. 두 경우 모두 상황 변화에 따른 지속적인 유지 관리가 필요합니다.
결혼 생활에도 똑같은 것이 필요합니다. 공유된 기본값—대부분의 다툼이 시작되기 전에 방지해 주는 기준이 되는 가정들—이 필요합니다. 아침에 누가 무엇을 담당할지. "좀 늦을 거야"라는 말이 무엇을 의미하는지(그리고 몇 시가 되면 문자를 보내야 하는지). 식기세척기를 가득 찼을 때 돌릴지, 아니면 누군가 깨끗한 포크가 필요할 때 돌릴지. 침묵이 "화났다"는 뜻인지 아니면 "생각 중이다"라는 뜻인지 말입니다.
사라와 나는 수년간의 실패한 암묵적 협상을 통해 이 기본값들을 어렵게 정립해야 했습니다. 관계 초기, 어려운 감정을 처리하는 나의 기본값은 '철수'였습니다. 조용히 혼자 생각하고 결론을 내린 뒤 나타나는 것이었죠. 사라의 기본값은 실시간으로 대화하며 풀어가는 것이었습니다. 어느 쪽도 틀리지 않았습니다. 하지만 공유된 기본값을 설정하지 않았기에, 모든 감정적인 순간은 프로토콜 불일치(Protocol mismatch)가 되었습니다.
# 초기 시절: 프로토콜 불일치
kenneth_default = "내부적으로 처리하고 나중에 응답하기"
sarah_default = "지금 당장 대화로 풀기"
# 결과: 아내는 내가 자신을 밀어낸다고 생각하고,
# 나는 아내가 나에게 생각할 여유를 주지 않는다고 생각합니다.
# 두 해석 모두 타당하지만,
# 어느 쪽도 전체 그림은 아닙니다.
해결책은 우리 중 한 명이 상대방의 기본값을 따르는 것이 아니었습니다. 새로운 공유 기본값을 설정하는 것이었죠. 내가 "이 문제에 대해 생각할 시간이 필요해, 한 시간 뒤에 다시 얘기하자"라고 말하면, 아내는 "알았어, 기다릴게"라고 말하는 것입니다. 이 기본값에는 타임아웃(Timeout)과 콜백(Callback)이 포함되어 있습니다. 훌륭한 API 디자인이죠.
부부 사이의 대부분의 다툼은 실제 문제 때문이 아닙니다. 서로 일치하지 않는 기본값 때문입니다. 한 사람이 상대방이 동의한 적 없는 무언가를 가정하고 있기 때문이죠. 의식적으로 설정하고 정기적으로 재검토하는 좋은 기본값은 가사 생활의 버그 중 대다수를 예방해 줍니다.
명확한 계약 (Clear Contracts)
Requests는 깔끔하고 명시적인 API를 가지고 있습니다. 당신은 무엇을 얻게 될지 정확히 알 수 있습니다.
response = requests.get('https://api.example.com/data')
# 계약은 명확합니다:
# - response.status_code는 무슨 일이 일어났는지 알려줍니다.
# - response.text는 디코딩된 콘텐츠를 제공합니다.
# - response.json()은 JSON인 경우 이를 파싱합니다.
# - response.ok는 성공 여부를 알려줍니다.
# 깜짝 놀랄 일도, 숨겨진 상태도, 추측할 필요도 없습니다.
이를 urllib2와 비교해 보십시오. urllib2는 요청 객체를 생성하고, 인코딩을 수동으로 처리하고, 오프너를 연결하는 등 간단한 HTTP 호출을 하기 전에도 일종의 작은 의식을 치러야 했습니다. API는 기술적으로는 완전했을지 몰라도 인간이 읽기에는 불가능했습니다.
암묵적인 기대치는 관계에 있어서의 urllib2와 같습니다. 초기 의사소통 방식을 urllib2에 비유하는 것이 지구상에서 약 300명 정도만 절감할 수 있는 특이한 모욕이라는 점은 알고 있습니다. 하지만 이 에세이를 읽고 있다면 당신도 아마 그중 한 명일 것입니다.
"내가 화난 걸 당신이 알았어야지." 왜요? 상태 코드가 무엇이었나요? 응답 바디는 무엇이었나요? 당신이 말해주지 않았다면 나는 몰랐을 것입니다. 암묵적인 신호를 놓쳤다고 해서 나쁜 파트너가 되는 것은 아닙니다. 개발자가 GET 요청을 보내기 위한 urllib2의 12단계 과정을 이해하지 못한다고 해서 나쁜 프로그래머가 아닌 것과 마찬가지입니다. 인터페이스가 불명확했을 뿐입니다.
사실 이건 내가 사라에게 가르쳐준 게 아니라 사라가 나에게 가르쳐준 것입니다. 아내는 나보다 명시적인 의사소통에 훨씬 능숙합니다. 아마도 형성기 시절을 컴퓨터와 대화하며 보내지 않았기 때문이겠죠. 아내는 무언가 필요할 때 그것을 말합니다. 드라마틱하게 화를 내거나 요구하는 것이 아니라, 그저 명확하게 말합니다. "오늘 밤 애들 재우는 것 좀 도와줘. 나 지금 에너지가 바닥났어." 명확한 요청입니다. 명확한 파라미터입니다. 나는 무엇이 요청되었는지 정확히 알 수 있고, 내가 그것을 들어줄 수 있는지에 대해 정직하게 응답할 수 있습니다.
그 대가로 내가 지키려고 노력하는 계약은 '말하는 대로 의미하고, 의미하는 대로 말하는 것'입니다. 업무든, 정신 건강이든, 삶의 일상적인 무게든 내가 힘들 때, 아내가 나의 행동 단서로부터 내 기호를 역설계(Reverse-engineer)하기를 바라기보다 명시적으로 이름을 붙여 말합니다. "명시적인 것이 암묵적인 것보다 낫다(Explicit is better than implicit)"는 파이썬의 선(Zen of Python)에 나오는 문구일 뿐만 아니라, 훌륭한 결혼 조언이기도 합니다.
우아한 에러 핸들링 (Graceful Error Handling)
모든 시스템은 고장 납니다. 문제는 에러가 발생할지 여부가 아니라, 에러가 발생했을 때 시스템이 어떻게 처리하느냐입니다.
Requests는 유용한 정보가 담긴 깔끔한 예외(Exception)를 발생시킵니다.
try:
response = requests.get('https://example.com', timeout=5)
response.raise_for_status()
except requests.ConnectionError:
# 명확함: 연결 실패.
# 무엇이 잘못되었는지 알고 적절히 대응할 수 있습니다.
print("연결할 수 없습니다. 네트워크를 확인하세요.")
except requests.Timeout:
# 명확함: 시간이 너무 오래 걸림.
# 다른 문제, 다른 대응.
print("요청 시간이 초과되었습니다. 다시 시도하거나 타임아웃을 늘리세요.")
except requests.HTTPError as e:
# 명확함: 서버가 에러를 응답함.
# 상태 코드가 어떤 종류의 에러인지 정확히 알려줍니다.
print(f"서버 에러: {e.response.status_code}")
예외는 구체적이고 정보가 풍부하며 실행 가능합니다. 무엇이 잘못되었는지 알 수 있고, 어떻게 할지 결정하기에 충분한 정보를 얻게 됩니다. 이를 단순히 스택 트레이스(Stack trace)와 함께 충돌해 버리는 시스템과 비교해 보십시오. 콘솔에 쏟아진 가공되지 않은 패닉 바이트들은 기술적으로는 모든 정보를 담고 있을지 모르지만, 위기의 순간에 인간에게는 아무런 쓸모가 없습니다.
결혼 생활의 에러도 마찬가지입니다.
"저녁 식사 중에 당신이 휴대폰을 확인할 때 내 마음이 상해"는 잘 형식화된 예외입니다. 에러의 이름(마음 상함)을 지정하고, 트리거(저녁 식사 중 휴대폰)를 식별하며, 해결책(휴대폰 치우기)을 암시합니다. 파트너는 이 예외를 캐치(Catch)해서 우아하게 처리할 수 있습니다.
비명을 지르는 것은 스택 트레이스 덤프입니다. 고통, 좌절, 누적된 원망 등 모든 정보가 기술적으로는 그 안에 들어있지만, 압박감 속에서 파싱(Parsing)하기 불가능한 형식으로 전달됩니다. 받는 사람이 할 수 있는 유일한 선택은 일반적인 예외(Generic exception)를 잡아서 잘 되길 바라거나, 시스템 전체가 충돌해 버리는 것뿐입니다.
# 잘 형식화된 관계 에러
class RelationshipError(Exception):
def __init__(self, feeling, trigger, need):
self.feeling = feeling
self.trigger = trigger
self.need = need
super().__init__(
f"{trigger}할 때 내 기분은 {feeling}해. "
f"나에게는 {need}이 필요해."
)
# vs. 스택 트레이스 덤프
raise Exception(
"모든 게 다 잘못됐어! 당신은 내 말을 전혀 안 들어! "
"이건 2019년 그때랑 똑같아! "
"당신 어머니도 똑같이 행동하신다고!"
)
# 밤 11시에 이걸 파싱하느라 행운을 빕니다.
나도 항상 이걸 잘하는 것은 아닙니다. 조현정동장애(Schizoaffective disorder) 때문에 스트레스를 받으면 나의 에러 핸들링 능력이 저하되기도 합니다. 잘 구조화된 예외 대신 가공되지 않은 감정적 출력이 쏟아져 나와서 나조차도 그 순간에는 파싱할 수 없게 됩니다. 사라는 나의 에러 핸들링 능력이 저하되었을 때를 알아차리고, 디버깅을 시도하기 전에 시스템이 안정될 때까지 기다리는 법을 배웠습니다. 그 인내심은 내가 가지기 전까지는 필요하다는 것조차 몰랐던 사랑의 한 형태입니다. 하위 호환성 (Backwards Compatibility)
이 점은 소프트웨어와 결혼 생활 모두에서 사람들이 생각하는 것보다 훨씬 중요합니다.
Requests가 버전 1.x에서 2.x로 넘어갈 때, 우리는 인간이 할 수 있는 한 최대한 하위 호환성을 유지했습니다. 왜일까요? 사람들이 기존 API를 중심으로 자신의 삶—애플리케이션, 비즈니스, 워크플로우—을 구축했기 때문입니다. 파괴적 변경(Breaking changes)은 단순히 불편한 것이 아닙니다. 그것은 일종의 배신입니다. 당신은 인터페이스를 약속했고, 사람들은 그 약속을 믿었으며, 이제 당신은 그들이 의존하던 것이 더 이상 작동하지 않는다고 말하고 있는 것입니다. 시맨틱 버저닝(Semantic versioning)은 본질적으로 변화를 어떻게 관리할 것인가에 대한 약속입니다. 결혼 서약도 비슷합니다. 모든 것이 변하더라도 무엇이 안정적으로 유지될 것인가에 대한 시맨틱 계약입니다. 메이저 버전 업데이트가 일어날 수도 있지만, 그것은 드물어야 하며 충분히 소통되어야 합니다.
결혼도 마찬가지입니다. 파트너는 특정한 약속과 패턴을 중심으로 자신의 삶을 구축해 왔습니다. 당신이 항상 아침에 커피를 내리는 방식. 일요일은 가족의 날이라는 사실. 불편할 때라도 정직할 것이라는 믿음. 이것들은 단순한 습관이 아니라 파트너가 의존하는 API입니다.
변화가 필요할 때—사람은 성장하고 상황은 변하기 때문에 반드시 필요할 것입니다—그냥 파괴적 변경을 프로덕션에 배포해서는 안 됩니다. 먼저 지원 중단 경고(Deprecation warnings)를 보내야 합니다. "있잖아, 나 커리어 전환을 고민하고 있어. 아직 결정된 건 없지만, 그냥 내 마음속에 이런 생각이 있다는 걸 당신이 알아줬으면 좋겠어." 이것이 지원 중단 경고입니다. 파트너에게 기대치를 조정하고, 질문하고, 변화에 대비할 시간을 줍니다.
절대로 해서는 안 되는 일은 어느 날 집에 와서 직장을 그만두고 미술 학교에 등록했다고 선언하는 것입니다. 그것은 경고 없이 파괴적 변경을 프로덕션에 배포하는 것이며, 새 버전이 아무리 훌륭하더라도 예고 없는 변경으로 인한 신뢰 훼손이 모든 것을 압도하게 될 것입니다.
나는 이것을 어렵게 배웠습니다. 초기에는 업무, 지출, 정신 건강 관리 방식 등 중요한 결정을 내리고 사라에게 기정사실로 통보하곤 했습니다. 기술적으로는 그것들이 옳은 결정인 경우가 많았습니다. 하지만 과정이 틀렸습니다. 지원 중단 주기를 건너뛰었고, 그 놀라움은 변화 자체보다 더 큰 상처를 주었습니다.
인간이 읽을 수 있는 응답 (Human-Readable Responses)
Requests에서 가장 사랑받는 기능 중 하나는 응답 콘텐츠를 처리하는 방식입니다.
response = requests.get('https://api.example.com/data')
# 이런 방식이 아니라 (기술적으로는 완전하지만 가공되지 않은 바이트):
raw = response.content # b'{"name": "Kenneth", "status": "tired"}'
# 이런 방식입니다 (디코딩되고 파싱되어 인간이 바로 쓸 수 있는 형태):
data = response.json() # {'name': 'Kenneth', 'status': 'tired'}
# 또는 간단하게:
text = response.text # 이미 디코딩됨. 이미 읽을 수 있음.
라이브러리가 당신을 위해 번역 작업을 대신 해줍니다. HTTP 응답의 가공되지 않은 바이트를 가져와서 인간이 실제로 읽고 사용할 수 있는 것으로 변환합니다. 정보는 항상 가공되지 않은 응답 안에 있었지만, 그것을 인간이 읽을 수 있는 형식으로 제공하는 것이 바로 유용함을 만듭니다.
이것은 결혼 생활에서 가장 어려운 기술 중 하나입니다. 자신의 내부 경험을 파트너가 실제로 파싱할 수 있는 것으로 번역하는 일 말입니다.
나의 내부 경험은 종종 가공되지 않은 바이트—구체적인 감정으로 디코딩되지 않은 막연한 불안, 이름 없는 좌절, 전반적인 잘못된 느낌—로 도착합니다. 내가 그 가공되지 않은 응답을 사라에게 쏟아낸다면, 아내는 그것으로 아무것도 할 수 없습니다. "뭔가 잘못됐는데 뭔지 모르겠어"는 response.content와 같습니다. 기술적으로는 사실이지만 유용하지는 않습니다.
정서적 성숙의 과제는 스스로 디코더(Decoder)가 되는 법을 배우는 것입니다. 내부 경험의 가공되지 않은 바이트를 가져와서 response.text—읽을 수 있고 파트너가 다룰 수 있는 것—로 번역하는 것입니다. "내일 회의 때문에 불안해서 내가 좀 예민해진 것 같아. 퉁명스럽게 굴었다면 미안해. 당신 때문이 아니야." 이것이 디코딩된, 인간이 읽을 수 있는 응답입니다.
솔직히 사라는 나의 가공되지 않은 출력을 읽어내는 데 탁월합니다. 아내는 때때로 나 자신도 모르는 나의 내부 상태에 대한 직관을 발달시켰습니다. 마치 훌륭한 HTTP 클라이언트가 서버가 제대로 선언하지 않은 인코딩의 특이점을 처리하는 법을 배우는 것처럼 말이죠. 하지만 나는 거기에 의존하지 않으려 노력합니다. 아내가 나의 문서화되지 않은 감정 API의 전문 파서(Parser)가 될 필요는 없으니까요. 인코딩 작업은 내가 직접 해야 합니다. 아내가 나의 가공되지 않은 바이트를 기꺼이 파싱해 준다고 해서 내가 계속 그것들을 보내야 한다는 뜻은 아닙니다. 사랑은 의사소통의 게으름에 대한 핑계가 아니라, 더 열심히 노력해야 할 이유입니다.
커넥션 풀링 (Connection Pooling)
이것은 HTTP와 결혼 생활 모두에서 내가 이해하는 데 가장 오랜 시간이 걸린 개념입니다.
Requests는 Session 객체를 통해 커넥션 풀링을 사용합니다. 모든 요청마다 새로운 TCP 연결을 수립하는 대신—전체 핸드셰이크(Handshake), SSL 협상, 그 비싼 설정 과정을 매번 거치는 대신—기존 연결을 재사용합니다. 컨텍스트(Context)가 유지됩니다. 오버헤드가 제거됩니다. 매번 처음부터 시작하지 않기 때문에 통신이 효율적이 됩니다.
# 세션이 없는 경우: 모든 요청이 0에서 시작합니다.
requests.get('https://api.example.com/users') # 새로운 연결.
requests.get('https://api.example.com/posts') # 새로운 연결.
requests.get('https://api.example.com/comments') # 새로운 연결.
# 세션이 있는 경우: 컨텍스트 공유, 상태 유지.
session = requests.Session()
session.headers.update({'Authorization': 'Bearer 수년간-쌓아온-신뢰'})
session.get('https://api.example.com/users') # 연결 재사용.
session.get('https://api.example.com/posts') # 컨텍스트 공유.
session.get('https://api.example.com/comments') # 재협상 없음.
결혼은 하나의 Session 객체입니다. 핵심은 이미 핸드셰이크를 마쳤다는 것입니다. 신뢰를 구축했습니다. 공유 헤더—가치관, 가정, 내부 농담, 수년간의 공유된 컨텍스트 덕분에만 통하는 줄임말들—를 협상했습니다.
사라가 "오늘은 화요일 같은 날이네"라고 말하면 나는 그게 무슨 뜻인지 정확히 압니다. 그걸 당신에게 설명하려면 문단 하나가 필요할 것입니다. 내가 "내 뇌가 또 그 짓을 하고 있어"라고 말하면, 아내는 어떤 짓인지, 나에게 무엇이 필요한지 압니다. 그것이 커넥션 풀링입니다. 유지된 상태가 주는 효율성입니다.
실패 모드는 세션 유지를 중단할 때 발생합니다. 모든 대화를 새로운 연결로 취급하기 시작할 때—공유된 컨텍스트도, 누적된 신뢰도 없이, 매번 SSL 핸드셰이크를 처음부터 시작하는 것이죠. "당신은 왜 그렇게 생각해?"라는 질문이 "당신을 아니까 당연히 그렇게 생각하겠지"라는 이해 대신 자리 잡게 됩니다. 세션 유지를 멈춘 오래된 부부들은 지난번에 문제를 해결했을 때의 컨텍스트를 이어가지 못하기 때문에 똑같은 다툼을 반복하게 됩니다.
결혼 생활의 과업은 세션 유지 관리입니다. 피곤할 때도, 화가 날 때도, 나의 버그를 모르는 누군가와 연결을 끊고 새로 시작하는 것이 더 쉬워 보일 때조차도, 컨텍스트와 신뢰, 공유된 이해를 적극적으로 이어나가기로 선택하는 것입니다.
사랑에 적용된 '인간을 위한' 철학
내 모든 작업에 흐르는 재귀적 루프(Recursive loop)—코드가 마음을 형성하고, 프로그래머가 코드를 형성하며, 따라서 프로그래머가 집단 의식을 형성한다는 생각—에는 친밀한 결론이 뒤따릅니다. 내가 시스템을 설계하는 방식이 관계를 생각하는 방식을 형성하고, 내가 관계를 경험하는 방식이 시스템을 설계하는 방식을 형성한다는 것입니다. 사라는 내 코드를 읽지 않습니다. 풀 리퀘스트를 열어본 적도, 스택 트레이스를 디버깅해 본 적도 없습니다. 하지만 아내는 내가 경험한 최고의 인터페이스입니다. 아내가 단순하기 때문이 아니라(아내는 단순함과는 거리가 아주 멉니다), 정직하기 때문입니다. 아내의 API는 명확하고, 수년간의 명시적인 의사소통을 통해 잘 문서화되어 있으며, 에러 메시지는 내가 듣고 싶지 않을 때조차 내가 알아야 할 것을 항상 알려줍니다.
영적 수행으로서의 프로그래밍에 대해 생각하다 보면, 결혼이야말로 가장 까다로운 영적 수행일지도 모른다는 사실을 깨닫습니다. 결혼은 프로그래머로서 쌓아온 모든 기술—복잡한 시스템에 대한 인내심, 나의 현실 모델이 틀렸을 때의 겸손함, 피곤할 때도 깔끔한 코드를 작성하려는 규율—을 요구하며, 그것들을 내가 유지 관리할 시스템 중 가장 중요한 시스템에 적용하게 합니다. 말라카이가 우리의 상호작용을 지켜보고 있습니다. 세 살인 아이는 이미 우리로부터 기본값을 배우고 있습니다. 사람들이 갈등을 어떻게 다루는지. 누군가 "미안해"라고 말하고 진심으로 사과하는 모습은 어떤지. 사랑이 연기되는 것인지 아니면 실천되는 것인지 말입니다. 우리는 단지 우리 자신의 시스템을 유지 관리하는 것이 아닙니다. 우리 아들이 평생 동안 포크(Fork)하고 수정해 나갈 초기 코드베이스를 작성하고 있는 것입니다.
이것이 가장 개인적인 차원에서의 재귀적 루프입니다. 내가 사라를 대하는 방식에 담긴 가치관이 말라카이가 정상이라고 받아들이는 가치관이 됩니다. 우리가 보여주는 기본값이 아이의 기본값이 됩니다. 아이가 목격하는 에러 핸들링 패턴이 관계를 탐색하는 아이의 첫 번째 템플릿이 됩니다.
부담 갖지 마세요. (No pressure.)
여전히 배우고 있는 것들
솔직하게 고백할 것이 있습니다. 나는 인간적인 파트너가 되는 것보다 인간적인 API를 설계하는 데 더 능숙합니다. 옆에서 자고 있는 사람보다 HTTP를 위한 깔끔한 인터페이스를 작성하는 것이 더 쉽습니다. HTTP는 당신의 응답 시간에 대해 감정을 품지 않고, 프로토콜은 당신이 2021년에 자신의 생일을 잊어버린 것을 기억하지 않기 때문입니다.
"인간을 위한" 철학은 소프트웨어에서와 마찬가지로 결혼 생활에서도 지향점입니다. 버그가 있다는 것을 알면서도 최선의 버전을 출시하는 것입니다. 반복해서 개선하기로 약속하는 것입니다. 퇴보(Regression)를 일으키지 않으려 노력하는 것입니다. 에러 로그—한숨, 침묵, 분명 괜찮지 않은데 "괜찮아"라고 말하는 것—를 읽고, 방어적인 태도 대신 인내심을 가지고 디버깅하는 것입니다.
어떤 날의 나는 합리적인 기본값과 우아한 에러 핸들링을 갖춘, 깔끔하고 문서화가 잘 된 API입니다. 또 어떤 날의 나는 urllib2입니다. 기술적으로는 작동하지만 상호작용하는 데 너무 많은 오버헤드가 필요해서 주변의 모든 사람을 지치게 만듭니다. 사라는 두 버전의 나 모두와 함께해 줍니다. 그것은 단순한 하위 호환성이 아닙니다. 그것은 은혜(Grace)입니다. 은혜란, 상대방의 현재 API 버전이 마땅히 받아야 할 대우보다 더 나은 대우를 해주는 것입니다. 당신이 사랑에 빠졌던 버전을 기억하고, 다음에 올 버전을 믿기 때문입니다.
작업은 계속됩니다. 시스템은 결코 완성되지 않습니다. 내가 할 수 있는 최선은 세션을 유지하고, 기본값을 정직하게 지키고, 나의 가공되지 않은 바이트를 아내가 읽을 수 있는 것으로 계속 번역하며, 우리가 함께 구축한 계약을 계속 존중하는 것입니다. 그것이 기술적으로 요구되기 때문이 아니라, 아내가 내가 설계할 모든 인터페이스 너머에 있는 인간이기 때문입니다.
그리고 아내는 언제나 그 자리에 있었습니다.
이 에세이는 API 설계 원칙을 관계의 지혜로 탐구하며, HTTP 라이브러리에서 시작된 "인간을 위한" 철학을 우리가 타인과 함께 구축하는 가장 친밀한 시스템에 연결합니다. 이 글은 영적 수행으로서의 프로그래밍, 재귀적 루프, 그리고 이 모든 작업의 토대가 되는 가족 생활의 주제들을 확장합니다. 기술적 설계에서 의식 연구에 이르는 더 넓은 궤적에 대해서는 HTTP에서 의식으로를 참조하세요.