Skip to content
tutorials

실패를 가시화하는 Effect 업그레이드

깔끔해 보이는 `Promise<User>`는 프로덕션 서비스를 중단시키는 실패 요인을 숨길 수 있습니다. 놀라운 점은, 안전성을 추가하면 타입이 더 복잡해지는 것이 아니라 오히려 더 많은 정보를 제공하게 된다는 것입니다.

Marcus Lee
실패를 가시화하는 Effect 업그레이드

Promise 타입의 프로덕션 사각지대

코드베이스에서 흔히 볼 수 있는 Promise<User>라는 계약을 상상해 보세요. 이 타입은 모든 것이 잘 풀렸을 때 User 객체를 반환한다는 '해피 패스(happy path)'를 완벽하게 설명합니다. 하지만 현실 세계는 어떨까요? 이 타입은 HTTP 오류, 사용자 정보 없음, 또는 무한정 대기 상태에 빠져 애플리케이션을 멈추게 하는 요청에 대해서는 아무것도 알려주지 않습니다.

안타깝게도 TypeScript는 Promise 거부(rejection)를 안정적으로 타입 지정하지 못합니다. catch 핸들러는 종종 unknown 값을 받게 되며, 이로 인해 런타임에 무엇이 잘못되었는지 추측해야만 합니다. 즉, 팀은 강력한 컴파일러 검사가 아닌 시행착오를 통해 실패 동작을 정의하느라 귀중한 시간을 낭비하게 됩니다.

사용자 프로필을 가져오는 서비스를 예로 들어보겠습니다. 호출자는 단순히 User 객체나 타입이 지정되지 않은 오류 이상의 정보가 필요합니다. 일시적인 네트워크 문제처럼 요청을 자동으로 재시도해야 하는지, 명확한 "사용자를 찾을 수 없음" 메시지를 표시해야 하는지, 아니면 특정 시간 이후에 대기를 중단해야 하는지 알아야 합니다. 타입에 이러한 명확성이 없으면 프로덕션 환경은 사각지대가 되어, 실패의 근본 원인에 대한 중요한 정보를 숨기게 됩니다.

Effect가 계약에 빠진 부분을 채워줍니다

Effect는 Promise<User> 계약을 더 강력한 무언가로 변경합니다. 핵심 시그니처인 Effect<A, E, R>은 모든 연산에서 중요한 세 가지 측면, 즉 성공 값, 타입이 지정된 실패, 그리고 필요한 의존성을 정확하게 설명합니다.

이를 자세히 살펴보겠습니다. A는 예시의 User처럼 성공 시 얻게 되는 값을 나타냅니다. E는 실패를 위한 마법이 일어나는 곳으로, HttpError | NotFound와 같이 예상되는 모든 오류의 타입 유니온(typed union)을 제공합니다. 마지막으로 R은 "요구사항(requirements)"을 의미하며, HTTP 클라이언트나 데이터베이스 연결처럼 코드가 실행되기 위해 필요한 서비스나 의존성을 나타냅니다.

영상에 나온 사용자 조회 함수를 생각해 보세요. 단순히 Promise<User> 대신, Effect 타입은 Effect<User, HttpError | NotFound, SomeHttpClient>가 될 수 있습니다. 이는 계약을 명시적으로 만듭니다. 즉, User를 얻을 수 있다는 사실뿐만 아니라 HttpError나 NotFound 조건이 구체적이고 예상 가능한 실패 모드임을 알려줍니다.

이는 일반적인 Promise와 큰 차이점입니다. Effect 연산은 지연 값(lazy values)입니다. 즉, 무엇을 해야 하는지는 설명하지만 언제 해야 하는지는 설명하지 않습니다. 실행 전에 재시도, 타임아웃, 오류 처리 정책을 포함한 전체 연산을 구성합니다. 이를 통해 프로그램을 구축하는 동안 모든 요구사항과 잠재적 결과를 가시화하여, 사각지대를 상세한 지도로 변환합니다.

안전성을 추가함에 따라 오류 타입이 변하는 과정을 확인하세요

데이터 가져오기 파이프라인에 복원력을 추가할 때 오류 타입이 어떻게 진화하는지 추적해 보겠습니다. 초기에는 Effect<User, HttpError | NotFound, R>이 HttpError 또는 NotFound 오류로 실패할 수 있습니다.

먼저, 일시적인 HttpError를 처리하기 위해 지수 백오프 재시도 정책을 적용하지만, 재시도가 HttpError의 가능성 자체를 제거하는 것은 아니므로 타입 시그니처는 변경되지 않습니다. 다음으로 2초 타임아웃을 추가합니다. 이는 즉시 TimeoutError를 오류 타입에 도입하여 Effect<User, HttpError | NotFound | TimeoutError, R>이 됩니다.

그 후, 대체 값을 제공하여 NotFound 케이스를 명시적으로 처리합니다. 마법처럼 NotFound 타입이 오류 시그니처에서 사라지는데, 이는 이제 해당 오류가 처리됨이 보장되기 때문입니다. 결과적으로 타입은 Effect<User, HttpError | TimeoutError, R>이 됩니다. 이는 단순한 기교가 아니라, 컴파일러가 잠재적 실패를 실시간으로 계산하는 과정입니다.

이를 증명하기 위해 타임아웃을 50밀리초로 단축합니다. 코드를 실행하면 타입 시스템이 예측한 대로 정확히 TimeoutError가 발생합니다. 런타임에서 검증되는 이러한 컴파일 타임 피드백 루프는 Effect: Production-Grade TypeScript의 강력한 기능이며, 실패를 가시화하고 관리 가능하게 만드는 접근 방식입니다.

이 글이 마음에 드셨나요? 매일 아침 이런 글을 메일로 받아보세요.

하루 한 통 · 두 번의 클릭으로 구독 취소 · 제3자 추적 없음

성과와 전환 비용

명시적 에러 및 의존성 추적은 인증이나 결제와 같은 중요한 서비스에서 빛을 발합니다. 이러한 도메인에서는 외부 API 타임아웃이나 데이터베이스 연결 끊김과 같은 숨겨진 거부 경로가 복구와 검토를 훨씬 어렵게 만듭니다. Effect의 타입 기반 접근 방식은 이러한 잠재적 실패 모드를 사후 대응이 아닌 선제적으로 해결하도록 보장합니다.

Effect는 단순한 Result 타입 그 이상을 제공합니다. 재시도(retries), 타임아웃(timeouts), 동시성, 의존성 관리를 위한 강력한 런타임을 즉시 사용할 수 있도록 제공합니다. 기존의 Promise 기반 코드를 즉시 대체하는 대신, Effect는 이를 보완하여 점진적인 도입과 애플리케이션의 특정 고가치 영역에 대한 통합을 가능하게 합니다.

Effect를 도입하려면 학습 투자가 필요합니다. 고유한 Effect<A, E, R> 시그니처를 가진 이 모델은 특히 에러 타입이 파이프라인을 통해 어떻게 진화하는지 파악하는 데 시간이 걸립니다. Effect 타입은 애플리케이션 경계를 넘어 자연스럽게 전파되므로, 팀은 특히 민감한 시스템의 경우 신뢰성과 관측 가능성 향상이라는 이점과 학습 및 마이그레이션 비용을 신중하게 비교해야 합니다.

자주 묻는 질문

TypeScript에서 Effect란 무엇인가요?

Effect는 명시적인 성공 값, 타입이 지정된 에러, 필요한 서비스를 사용하여 비동기 프로그램을 모델링하기 위한 라이브러리입니다.

Effect는 Promise와 어떻게 다른가요?

Promise는 해결되거나 거부될 수 있는 값을 설명하지만 거부 타입을 인코딩하지는 않습니다. Effect는 타입이 지정된 실패와 의존성까지 모델링합니다.

에러가 처리될 때 Effect 타입은 어떻게 변경되나요?

타입이 지정된 에러를 처리하면 해당 실패가 Effect의 에러 타입에서 제거됩니다. 반면 타임아웃과 같은 작업을 추가하면 새로운 타입의 실패가 추가될 수 있습니다.

모든 TypeScript 프로젝트에 Effect를 도입해야 하나요?

반드시 그렇지는 않습니다. 명시적인 실패 처리와 런타임 제어가 필요한 복잡한 시스템에는 도움이 될 수 있지만, 그 개념과 타입의 영향력으로 인해 도입을 위한 투자가 필요합니다.

Found this useful? Share it.

For builders

Want Stork to write one of these about your product?

Send us a URL. We use the product, form a view, and publish what we actually think — in 8 languages, labeled Sponsored, with no copy approval on your side. That last part is what makes it worth quoting.

See how it works$199 · AI tools & software only

빌더를 위해

이 페이지는 지금 다른 사람의 도구를 위해 일하고 있습니다.

AI 에이전트가 읽고, 구매자가 도착합니다. 8개 언어와 MCP로 답합니다. 당신의 도구도 가질 수 있습니다 — 24시간 안에 공개.