예외를 던지는 것을 멈추세요. 대신 Option과 Result를 사용하세요.

발행: (2026년 2월 20일 오후 09:10 GMT+9)
5 분 소요
원문: Dev.to

I’m happy to translate the article for you, but I’ll need the full text you’d like translated. Could you please paste the content (excluding the source line you already provided) here? Once I have the article, I’ll translate it into Korean while preserving the original formatting, markdown, and any code blocks or URLs.

JavaScript 오류 처리의 문제점

function getUser(id: number): User | null {
  // ...
}

호출자는 null 검사를 기억해야 합니다. 타입 시스템이 힌트를 주지만, 이를 방지할 방법은 없습니다:

const user = getUser(42);
console.log(user.name); // user가 null이면 런타임에 TypeError 발생

더 나쁜 패턴은 async 함수에서 가능한 실패를 숨기는 것입니다:

async function fetchConfig(): Promise {
  // 네트워크 오류, 파싱 오류, 검증 오류 등을 발생시킬 수 있음...
  // 이러한 오류들은 타입 시그니처에 나타나지 않음
}

오류가 보이지 않기 때문에 호출자는 어떤 오류를 처리해야 할지 알 수 없습니다.

TypeScript에서 OptionResult 소개

Rust의 OptionResult는 타입 시그니처에 값이 없거나 실패할 가능성을 명시합니다. 이와 같은 아이디어를 @rslike/std가 TypeScript에 도입했습니다.

npm i @rslike/std

Option 사용하기

import { Some, None, Option, match } from "@rslike/std";

function findUser(id: number): Option {
  const user = db.find(u => u.id === id);
  return user ? Some(user) : None();
}

안전한 추출

const opt = findUser(42);

// 대체값
const user = opt.unwrapOr(guestUser);

패턴 매칭

const greeting = match(
  opt,
  (user) => `Hello, ${user.name}!`,
  () => "Hello, guest!"
);

변환

const displayName = findUser(42)
  .map(u => `${u.firstName} ${u.lastName}`)
  .unwrapOr("Unknown User");

옵션 체이닝

const avatar = findUser(42)
  .flatMap(u => findAvatar(u.avatarId))
  .unwrapOr(defaultAvatar);

기본 API

const opt = Some("hello");
opt.isSome();      // true
opt.isNone();      // false
opt.unwrap();      // "hello"

const empty = None();
empty.isNone();                // true
empty.unwrapOr("fallback");    // "fallback"
empty.unwrap();                // throws UndefinedBehaviorError — intentional!

Result 사용하기

import { Ok, Err, Result, match } from "@rslike/std";

function divide(a: number, b: number): Result {
  return new Result((ok, err) => {
    if (b === 0) {
      err("Division by zero");
    } else {
      ok(a / b);
    }
  });
}

결과 검사

const r = divide(10, 2);
r.isOk();        // true
r.unwrap();      // 5

const bad = divide(10, 0);
bad.isErr();          // true
bad.unwrapErr();      // "Division by zero"
bad.unwrapOr(0);      // 0

Result로 JSON 파싱하기

function parseJSON(raw: string): Result {
  return new Result((ok, err) => {
    try {
      ok(JSON.parse(raw));
    } catch (e) {
      err(e as SyntaxError);
    }
  });
}

const config = parseJSON(rawInput)
  .map(data => validate(data))
  .mapErr(e => `Invalid config: ${e.message}`)
  .unwrapOr(defaults);

Result 매칭하기

const message = match(
  parseJSON(rawInput),
  (data) => `Loaded: ${JSON.stringify(data)}`,
  (err) => `Error: ${err.message}`
);

match 유틸리티

match는 불리언, Option, Result와 함께 동작하며, 전체를 포괄하는 두 갈래 디스패치를 제공합니다.

import { match } from "@rslike/std";

// Boolean
match(isAdmin, (t) => "admin panel", (f) => "dashboard");

// Option
match(someOption, (value) => `Got: ${value}`, () => "nothing");

// Result
match(someResult, (n) => n * 2, (e) => -1);

TypeScript는 입력으로부터 콜백 매개변수 타입을 추론하여, 오류 핸들러를 실수로 성공 핸들러로 사용하는 것을 방지합니다.

전역 임포트 (선택 사항)

// entry.ts — once
import "@rslike/std/globals";

// Anywhere else in your app — no imports needed
const x = Some(42);
const r = Ok("success");
const n = None();
const e = Err(new Error("oops"));

코드 리뷰의 장점

OptionResult가 함수 시그니처에 나타날 때, 논의는 “null/예외 처리를 놓쳤나요?”에서 “의도된 계약은 무엇인가요?”로 이동합니다.

BeforeAfter
function getSession(token: string): Session | nullfunction getSession(token: string): Option
async function createOrder(cart: Cart): Promiseasync function createOrder(cart: Cart): Promise>

설치

npm i @rslike/std
0 조회
Back to Blog

관련 글

더 보기 »

C#의 람다 식

소개 C에서 람다 식은 짧고 가독성 있게 익명 메서드를 작성할 수 있게 해줍니다. 이들은 `=>` 람다 연산자를 사용하여 정의됩니다. 람다...