dev.to

Frameworks Are Institutional Memory

프레임워크는 기관의 기억(Institutional Memory)이다 — 추상화가 담고 있는 경험의 가치

1980년대 BBS 시절 플로피 디스크에 비밀번호를 평문으로 저장했던 경험에서 출발해, 성숙한 프레임워크가 '타이핑 절약'이 아니라 다른 사람이 이미 겪은 결정·엣지 케이스·취약점의 기록이라는 논지를 펴는 에세이입니다. 통제(control)에는 항상 책임(responsibility)이 따라붙고, 팀의 주의력은 유한한 '복잡성 예산'이라는 것이 핵심입니다. 최근 코딩 에이전트가 비밀번호 재설정 기능을 5분 만에 만들었지만 재설정 토큰이 재사용 가능했다는 일화로, AI가 해피 패스는 재현해도 불변조건(invariant)은 잃어버릴 수 있다는 문제를 제기합니다.

본문

저자는 1980년대 BBS(전자게시판 시스템)를 운영하던 시절의 이야기로 글을 시작합니다. 당시에는 하드 드라이브가 비싸서 애플리케이션 데이터를 플로피 디스크에 두는 것이 자연스러웠고, 사용자 비밀번호도 'KEN|swordfish' 같은 형태로 평문 저장했습니다. 운영자가 모든 비밀번호를 읽을 수 있다는 문제가 드러나자 치환 암호 같은 자체 변환을 적용했지만, 그 해결책은 또 다른 질문을 낳았습니다. 변환이 가역적이고, 같은 비밀번호는 같은 저장값을 만들고, 파일이 유출되면 전원이 노출되며, 사용자들은 그 비밀번호를 다른 곳에서도 재사용했습니다. 이후 수십 년간 '비밀번호 저장'에는 해싱, 솔트(salt), 비밀번호 재설정, 만료 토큰, 일회용 토큰, 세션 무효화, 계정 열거(account enumeration) 방지, 무차별 대입 방어, 쿠키 속성, CSRF, 레이트 리미팅 같은 엄청난 양의 공학적 지식이 축적되었습니다.

프레임워크의 진짜 가치는 코드가 아니라 결정이다

개발자들이 프레임워크에서 처음 배우는 것은 '코드를 덜 쓰게 해준다'는 것이지만, 저자는 이것이 프레임워크를 심하게 과소평가한 설명이라고 말합니다. 성숙한 프레임워크에는 다른 사람이 이미 내려야 했던 결정, 이미 부딪힌 엣지 케이스, 이미 발견된 취약점, 필요하다고 배운 수정사항이 담겨 있습니다. 인증의 해피 패스(자격증명 제출 → 계정 조회 → 비밀번호 확인 → 세션 생성 → 성공 반환)는 경험 적은 개발자도 구현할 수 있지만, 운영 환경의 인증이 어려운 이유는 해피 패스 주변의 모든 것 때문입니다. 반복된 실패 시도 후에는 무엇이 일어나는가, 에러 메시지 비교로 사용자명 존재 여부를 알아낼 수 있는가, 비밀번호 변경 후 기존 세션은 어떻게 되는가 — 처음 인증을 만드는 개발자는 이런 질문을 해야 한다는 것 자체를 모릅니다. 성숙한 프레임워크는 종종 알고 있습니다. 이것은 키스트로크 절약과는 전혀 다른 종류의 가치입니다.

통제의 쌍둥이, 책임

어셈블리에서 고수준 언어로, C에서 관리형 런타임으로, 라이브러리와 프레임워크로 소프트웨어는 전문 지식을 추상화 뒤에 두며 진보해 왔습니다. 어떤 계층도 아래 계층을 없애지 않았고, 바뀐 것은 '누가 그것을 일상적으로 생각해야 하는가'뿐입니다. 개발자들은 통제를 무조건적인 선처럼 이야기하지만, 통제에는 덜 언급되는 쌍둥이인 책임이 있습니다. 메모리 할당을 통제하면 메모리 할당에 책임을 지고, 인프라를 통제하면 설정·보안·관측·업데이트·트러블슈팅에 책임을 집니다. 인벤토리 API를 C로 작성해 네트워킹, HTTP 파싱, 라우팅, 직렬화, 인증, 동시성을 직접 다룰 수도 있지만, 그것은 Flask·FastAPI·Django·Rails·Spring이 수년간 '재미없는 문제'로 만들어 온 것들을 자원해서 떠안는 일입니다. 이 거래는 '추상화 대 통제'가 아니라 '적은 통제와 적은 책임 대 많은 통제와 많은 책임'에 가깝습니다.

'Opinionated'는 비판이기도 하고 결정의 위임이기도 하다

Opinionated(의견이 강한)는 때로 비판으로 쓰이지만, 의견이란 곧 팀이 내리지 않아도 되는 결정입니다. 인증, 마이그레이션, 폼, 라우팅, 검증, 세션, 프로젝트 구조에 대한 확립된 접근법은 그만큼의 질문을 팀의 안건에서 지워줍니다. 대가는 다른 사람이 선택지의 모양을 부분적으로 정한다는 점입니다. Django에서 MongoDB를 쓰는 일이 오랫동안 그 사례였는데, Django의 데이터 계층은 관계형 데이터베이스에 맞춘 가정 위에 설계되어 있었습니다. 흥미로운 점은 MongoDB가 2025년 초 공식 Django 백엔드를 퍼블릭 프리뷰로 내놓아 임베디드 모델, 쿼리 가능한 암호화, 지리공간 조회 등을 지원하게 되었다는 것입니다. 프레임워크의 의견은 뒤집히지 않고 확장되었으며, 그 작업에는 수년이 걸렸습니다. 축적된 지식이 곧 제품이며, 그 축적은 느리게 일어납니다.

매니지드 플랫폼과 복잡성 예산

매니지드 플랫폼은 이 거래를 더 선명하게 보여줍니다. AWS는 App Runner·Elastic Beanstalk·Lambda를 파는 동시에 EC2·VPC·로드밸런서·IAM 정책 묶음도 팔고, Google Cloud는 Cloud Run과 Compute Engine·GKE를, Azure는 App Service와 VM·AKS를 함께 제공합니다. 같은 제공자, 같은 워크로드, 극적으로 다른 책임의 양입니다. 한 가지 비대칭은 미리 가격을 매겨둘 가치가 있습니다. 매니지드 경로는 진입은 싸지만 이탈은 비싸다는 것입니다. 저자는 이를 '복잡성 예산(complexity budget)'으로 부릅니다. 모든 팀의 주의력은 유한하고, 자체 인증을 만들면 예산의 일부를 인증에 쓴 셈입니다. Dan McKinley의 'Choose Boring Technology'의 혁신 토큰(innovation token) 논지와 이웃한 개념으로, '우리가 만들 수 있다'는 사실은 아무것도 증명하지 않으며, 더 나은 질문은 '이것이 우리 복잡성 예산을 쓸 자리인가'입니다.

AI 에이전트가 놓친 불변조건

저자는 최근 코딩 에이전트에게 작은 애플리케이션의 비밀번호 재설정을 구현하게 했습니다. 5분 만에 이메일이 오고, 링크가 열리고, 비밀번호가 바뀌고, 새 비밀번호로 로그인이 되었습니다. 모든 것이 작동했지만, 재설정 링크가 두 번째로도 작동했습니다. 구현은 눈에 보이는 동작을 만족시키면서 그 아래의 불변조건 — 재설정이 성공하면 토큰은 무용해져야 한다 — 을 놓친 것입니다. 이것은 40년 전 'sysop이 모두의 비밀번호를 읽을 수 있는가?'라는 질문과 같은 패턴입니다. 성숙한 프레임워크에서 일회용 토큰 검사는 누가 그 이유를 기억하든 말든 실행됩니다. 교훈은 기억되는 것이 아니라 강제됩니다. 반면 대규모 코드 말뭉치로 학습한 모델은 기관의 기억과 비슷한 무언가를 흡수했지만, 결정 자체가 아니라 결정 이후에 만들어진 산출물에서 배웠기 때문에, 어떤 구현이 살아남고 어떤 구현이 그러지 못했는지를 강제하는 무언가는 물려받지 못합니다. 저자는 '해피 패스는 풍부하지만, 불변조건은 결정 속에 산다'로 글을 맺습니다.

원문: dev.to / 번역·요약: Trawling