Effect-TS는 무료 API를 제공한다: 프로덕션 앱을 위한 TypeScript의 누락된 표준 라이브러리

발행: (2026년 3월 29일 PM 11:09 GMT+9)
3 분 소요
원문: Dev.to

Source: Dev.to

Overview

Effect는 프로덕션 애플리케이션을 위한 표준 라이브러리를 제공하는 TypeScript 라이브러리입니다. 주요 기능은 다음과 같습니다:

  • 타입이 지정된 오류 (어떤 오류가 발생할 수 있는지 정확히 알 수 있음)
  • 의존성 주입 (컨테이너가 필요 없음)
  • 구조화된 동시성 (fibers, 세마포어)
  • 백오프가 포함된 재시도 정책
  • 스키마 검증 (Zod와 비슷하지만 통합되어 있음)
  • 스트림 (반응형 데이터 처리)
  • 내장 트레이싱 및 메트릭스

TypeScript에는 타입이 지정된 오류, 의존성 주입, 재시도, 레이트 리밋, 구조화된 동시성을 다루는 표준 방법이 없습니다. Effect는 이러한 빈틈을 조합 가능하고 타입‑안전한 API로 메워줍니다.

Installation

npm install effect

Basic Usage

import { Effect, Console } from "effect";

const program = Effect.gen(function* () {
  yield* Console.log("Hello from Effect!");
  const result = yield* Effect.succeed(42);
  yield* Console.log(`Result: ${result}`);
});

Effect.runPromise(program);

Typed Errors

import { Effect, Data } from "effect";

class NotFoundError extends Data.TaggedError("NotFoundError") {}

class DatabaseError extends Data.TaggedError("DatabaseError") {}

const findUser = (id: string): Effect.Effect =>
  Effect.gen(function* () {
    const user = yield* queryDatabase(id);
    if (!user) {
      return yield* new NotFoundError({ id });
    }
    return user;
  });

// Handle specific errors
const program = findUser("123").pipe(
  Effect.catchTag("NotFoundError", (e) =>
    Effect.succeed({ name: "Default", id: e.id })
  ),
  Effect.catchTag("DatabaseError", (e) =>
    Effect.fail(new Error(`DB failed: ${e.cause}`))
  ),
);

Dependency Injection with Context & Layers

import { Effect, Context, Layer } from "effect";

class Database extends Context.Tag("Database") Effect.Effect }
>() {}

class Logger extends Context.Tag("Logger") Effect.Effect }
>() {}

const findUsers = Effect.gen(function* () {
  const db = yield* Database;
  const logger = yield* Logger;
  yield* logger.log("Fetching users...");
  return yield* db.query("SELECT * FROM users");
});

// Provide implementations
const DatabaseLive = Layer.succeed(Database, {
  query: (sql) => Effect.succeed([{ id: 1, name: "Alice" }]),
});

const LoggerLive = Layer.succeed(Logger, {
  log: (msg) => Effect.sync(() => console.log(msg)),
});

const MainLive = Layer.merge(DatabaseLive, LoggerLive);

Effect.runPromise(
  findUsers.pipe(Effect.provide(MainLive))
);

Retries, Scheduling, and Concurrency

import { Effect, Schedule } from "effect";

const fetchData = Effect.tryPromise(() =>
  fetch("https://api.example.com/data").then((r) => r.json())
);

// Retry with exponential backoff (up to 5 attempts)
const reliable = fetchData.pipe(
  Effect.retry(
    Schedule.exponential("1 second").pipe(
      Schedule.compose(Schedule.recurs(5))
    )
  ),
);

Running Tasks Concurrently

const tasks = [fetchUser(1), fetchUser(2), fetchUser(3)];

// Run all concurrently (max 3 at a time)
const results = yield* Effect.all(tasks, { concurrency: 3 });

Limiting Concurrency with a Semaphore

// Create a semaphore that allows up to 5 concurrent permits
const semaphore = yield* Effect.makeSemaphore(5);

// Wrap each task to acquire a permit before execution
const limited = tasks.map((task) => semaphore.withPermits(1)(task));
const results2 = yield* Effect.all(limited);

Resources

Feel free to explore the library for building robust, production‑grade TypeScript applications.

0 조회
Back to Blog

관련 글

더 보기 »

왜 Node.js를 공부해야 할까?

왜 Node.js를 공부해야 할까요? 개발 세계에 입문하거나 프로그래머로 성장하고 싶다면, Node.js를 공부하는 것이 가장 전략적인 선택 중 하나가 될 수 있습니다…