마스터리의 숨은 계약: 복잡성을 흡수해야 하는 이유
Source: Dev.to
며칠 전, 누군가가 내 오픈소스 프로젝트 중 하나에 댓글을 남겼다.
그 사람은 내 CLI 도구—3D 프린트 품질 검사기인 Printsight—를 써봤고, 조명이 고르지 않은 프린트에서 잘못된 결함을 표시한다는 것을 발견했다. 그래서 전처리 단계로 CLAHE(대조도 균등화 알고리즘)를 추가하자고 제안했다.
좋은 제안이다. 실용적이고 구체적이며, 바로 원하는 피드백이다.
하지만 내가 진짜로 무슨 말을 하는지 이해하는 데는 시간이 좀 걸렸다.
그 사람이 CLAHE를 추가해 달라는 것이 아니라, “내 환경에서는 네 도구가 제대로 동작하지 않으니, 작동하게 해 줘”라는 뜻이었다.
내 첫 번째 직감은 기술적으로는 맞았다: 독립적인 CLAHE 스크립트를 만들고, README에 “예외 상황에 대비한 최후의 수단”이라고 문서화한다. 핵심 파이프라인은 깔끔하게 유지한다.
이는 아키텍처 순수성을 중시하는 엔지니어의 본능이었다.
하지만 그 방법은 옳지 않았다.
독립 스크립트는 부담을 사용자에게 전가한다. 이제 사용자는 다음을 알아야 한다.
- CLAHE가 무엇인지
- 언제 사용해야 하는지
- 어떤 파라미터를 설정해야 하는지
- Printsight를 실행하기 전에 반드시 실행해야 한다는 것
이것을 나는 “복잡성을 외부에 내보낸다”라고 부른다—문제를 해결한 것이 아니라, 조절용 손잡이를 추가하고 문서화만 한 셈이다.
올바른 해결책은 그 복잡성을 핵심 파이프라인에 흡수하는 것이다: 조명 상태를 자동으로 감지하고, 필요할 때만 CLAHE를 적용하며, 이미지마다 임계값을 조정한다. 사용자는printsight photo.jpg만 입력하면 된다. 바로 동작한다.
이것은 간단한 엔지니어링 교훈이지만, 훨씬 큰 주제로 이어진다.
무언가를 만들 때—코드, 문서, 응답, 결정—그것을 소비하는 사람이 있다.
그리고 무언가를 소비할 때는, 그것을 만든 사람이 있었다.
겉보기엔 당연해 보이지만, 그 함의는 그렇지 않다.
생산자의 역할은 복잡성을 흡수해 소비자가 부담을 갖지 않게 하는 것이다. 연구, 시행착오, 엣지 케이스 등을 모두 해결해 두었기 때문에 결과물이 깔끔하게 전달된다.
소비자의 역할은 침묵 속에 고통받지 않는 것이다. 벽에 부딪혔을 때, 복잡성을 흡수할 수 있는 사람에게 넘겨라. 실패가 아니라, 노동 분업을 존중하는 행동이다.
대부분은 한쪽은 제대로 하고 다른 쪽은 놓치는 경우가 많다.
구체적인 엔지니어링 결정을 통해 이 생각을 추적해 본 결과, 코드 작성이든 새로운 분야 학습이든 일상 협업이든 적용할 수 있는 세 가지 원칙을 정리했다:- 노출하는 모든 손잡이는 답변을 회피한 질문이다.
- “대부분의 경우에 동작한다”는 기본값은 당신이 내린 판단이다.
이것이 곧바로 수준을 낮춘다는 뜻은 아니다. 오히려 소비자가 실제로 필요로 하는 것을 파악하고, 정확히 그만큼만 제공하는—더도 덜도 아닌—노력이다.
Printsight의 경우, 핵심 파이프라인을 재설계해 조명 조건을 자동 감지하고, 적응형 전처리를 적용해 하나의 신뢰할 수 있는 점수를 반환하도록 했다.--clahe플래그도, “예외 상황”이라는 README 섹션도 없었다.
글을 쓸 때는 서론‑본론‑결론 순서와 훅, 쉬운 어휘가 필요하다—학문적 복잡성을 흡수했기 때문에 독자는 고민할 필요가 없다.
API 설계에서는 좋은 기본값을 제공해 사용자가 한 번의 호출만으로 올바른 답을 얻을 수 있게 한다.
내부적으로 애쓰지 말라. 독자적으로 10분 정도 노력했는데도 벽에 부딪혔다면, 혼자서 배울 수 있는 한계에 도달한 것이다. 다음 단계는 같은 작업을 또 30분 하는 것이 아니라, 알고 있는 사람에게 묻는 것이다. 소비자의 기술은 언제 문제를 넘겨줄지 아는 것이다.
거만해지지 말라. 튜토리얼을 한 번 따라 했다고 시스템을 완전히 이해한 것이 아니다. 설명할 수 있다고 해서 예측할 수 있는 것도 아니다. 숙달 단계는 실제로 존재한다—대부분은 1단계(동작한다)에서 멈추고 끝났다고 생각한다. 자신의 맹점을 인식하고 문제를 넘겨받는 소비자는 방어적인 사람보다 더 빠르게 성장한다.
당신은 절대 생산자만이거나 소비자만이 아니다. 같은 하루 안에 함수 호출을 만들고 API를 사용하고, 슬랙 메시지를 작성하고 디자인 문서를 읽고, 책 챕터를 쓰고 연구 논문을 읽을 수도 있다.
따라서 어느 한쪽 책임을 포기할 수 없다. 생산할 때는 미래의 소비자를 위해 복잡성을 흡수해야 하고, 소비할 때는 미래의 생산자에게 자신이 감당하지 못하는 복잡성을 넘겨야 한다.
이 순환은 양쪽이 서로를 존중할 때만 유지된다.
이 패턴이 친숙하게 느껴지는 이유가 있다.
LLM은 무엇을 할까? 모호하고, 잡음이 섞이며, 명확히 정의되지 않은 질문—수백 토큰에 달하는 애매함—을 받아 일관된 답변으로 압축한다. 사용자는 텍스트만 본다. 트랜스포머 레이어, 어텐션 헤드, KV 캐시, 1000억 개 파라미터가 그 문장을 만들었다는 사실은 보지 못한다.
이것이 바로 “복잡성을 스스로에게 맡기라”는 행위가 행성 규모로 일어나는 모습이다.
차이점은 AI가 모두를 위해 동시에 해준다는 점이고, 우리는 이를 자연스럽게 받아들인다. 하지만 동료가 같은 일을—복잡성을 흡수해 상호작용을 마찰 없이 만든다—했을 때는 거의 눈치채지 못한다. 우리는 눈여겨봐야 한다.
이 원칙은 AI에만 국한되지 않는다. 오늘 당신이 하는 모든 상호작용에 적용된다.
메시지를 보내기 전, 코드를 커밋하기 전, 대화를 마무리하기 전 스스로에게 물어라:- 여기서 내가 복잡성을 흡수했는가, 아니면 상대에게 넘겼는가?
그리고 문제 앞에서 또 한 시간을 허비하기 전에 스스로에게 물어라:- 이것이 내가 흡수해야 할 복잡성인가, 아니면 넘겨야 할 문제인가?
이 두 질문을 꾸준히 던지는 습관이 가장 큰 레버를 제공할 것이다. 답을 알려 주지는 않지만, 스스로를 어떻게 위치시킬지 알려 준다. 학습이든 구축이든, 위치가 전부다.