라떼군 이야기


검증하지 말고 파싱하라: 버그를 원천 봉쇄하는 타입 주도 설계의 핵심

TL;DR 데이터를 단순히 검증(Validate)만 하면 그 유효성을 타입 시스템이 기억하지 못해 중복 체크와 버그가 발생합니다. 대신 데이터를 파싱(Parse)하여 구조적인 타입으로 변환함으로써, ‘유효하지 않은 상태’를 아예 표현할 수 없도록 만드는 것이 안전한 소프트웨어 설계의 핵심입니다.


2019년 Alexis King이 작성한 이 글은 정적 타입 언어 커뮤니티에서 ‘타입 주도 설계(Type-Driven Design)‘를 설명하는 가장 명쾌한 바이블로 꼽힙니다. 왜 우리는 수많은 방어적 코드를 작성하고도 여전히 런타임 에러에 시달릴까요? 이 글은 그 원인이 ‘검증’이라는 행위의 한계에 있다고 지적하며, 이를 ‘파싱’이라는 관점으로 전환했을 때 얻을 수 있는 강력한 안전성과 명료함에 대해 이야기합니다.

핵심 내용

원문의 핵심은 ‘검증(Validation)‘과 ‘파싱(Parsing)‘의 차이에서 출발합니다. 검증은 인자를 확인한 후 그대로 반환하므로, 이후 코드에서 그 데이터가 유효하다는 사실을 보장받지 못해 방어적 코드가 곳곳에 흩어지는 ‘Shotgun Parsing’ 안티 패턴을 유발합니다. 반면 파싱은 비구조적 입력(예: 단순 리스트)을 구조적 출력(예: 비어있지 않은 리스트 타입)으로 변환하여 타입 시스템 안에 정보를 보존합니다. 이를 통해 프로그램의 경계(Boundary)에서만 실패 가능성을 처리하고, 내부 로직에서는 타입이 보장하는 안전한 데이터만 다루게 됩니다.

기술적 인사이트

이 글의 기술적 통찰은 ‘부분 함수(Partial Function)‘를 ‘전전 함수(Total Function)‘로 전환하는 방법론에 있습니다. 단순히 Boolean 값으로 유효성을 체크하는 것은 정보 손실을 야기합니다. 대신 성공 시 ‘증명된 타입(Proof)‘을 반환하게 함으로써, 컴파일러가 로직의 정합성을 강제하게 만드는 것입니다. 이는 ‘불가능한 상태는 표현조차 할 수 없게(Make illegal states unrepresentable)’ 만드는 전략으로, 초기 타입 정의 비용은 들지만 장기적으로 런타임 에러와 테스트 비용을 획기적으로 줄여주는 트레이드오프를 가집니다.

시사점

실무 개발자들에게 이는 ‘Primitive Obsession(원시 타입 집착)‘을 버리고 도메인 제약이 반영된 타입을 적극적으로 사용해야 함을 시사합니다. 예를 들어, 이메일 주소를 단순 String으로 넘기는 대신 Email 타입으로 파싱하여 전달한다면, 함수 내부에서 다시 형식을 검사할 필요가 없어집니다. 모든 데이터 검증은 시스템의 최외곽 경계(I/O)에서 수행하고, 내부 코어 로직은 항상 ‘정제된 타입’만 다루도록 아키텍처를 구성해야 합니다.


당신의 코드는 데이터를 확인할 때마다 그 사실을 잊어버리고 있지는 않나요? ‘이 데이터가 유효한가?‘라고 묻는 대신, ‘이 데이터가 유효함을 증명하는 타입은 무엇인가?‘라고 질문을 바꿔보세요. 그것이 더 견고한 시스템으로 가는 첫걸음입니다.

원문 읽기

Collaboration & Support (협업 및 후원) Get in touch (연락하기) →