본문으로 건너뛰기
Kreath Archive
TechProjectsBooksAbout
TechProjectsBooksAbout
TechProjectsBooksAbout
© 2026 Kreath. All rights reserved.
홈TechProjectsBooksAbout
//
  1. 홈
  2. 테크
  3. 5장: 웹 표준 API와 Deno 네이티브 기능
2026년 7월 21일·프로그래밍·

5장: 웹 표준 API와 Deno 네이티브 기능

Deno가 채택한 웹 표준 API(fetch, WebSocket, Web Crypto, Streams)와 Deno 전용 API(Deno.serve, Deno.KV, Deno.open)를 심층적으로 분석합니다.

15분1,042자5개 섹션
typescriptperformancetoolingsecuritydeveloper-experience
공유
deno-runtime5 / 10
12345678910
이전4장: npm 호환과 패키지 관리다음6장: Bun과의 비교 - 성능, 호환성, 생태계

웹 표준을 선택한 이유

Deno의 API 설계에서 가장 핵심적인 원칙은 "웹 표준 우선"입니다. 브라우저에서 이미 표준화된 API가 있다면 그것을 그대로 사용하고, 서버에서만 필요한 기능에 대해서만 Deno 네임스페이스의 전용 API를 제공합니다.

이 접근 방식의 이점은 명확합니다. 브라우저에서 동작하는 코드를 서버에서도 그대로 실행할 수 있고, 반대로 서버에서 작성한 코드를 브라우저에 가져올 때도 수정이 최소화됩니다. 또한 WinterCG 호환 런타임(Cloudflare Workers, Vercel Edge Runtime 등)과의 이식성도 확보됩니다.

웹 표준 API 상세

fetch API

fetch는 HTTP 요청을 보내는 웹 표준 API입니다. 브라우저의 fetch와 동일한 인터페이스를 제공합니다.

fetch API 활용
typescript
// 기본 GET 요청
const response = await fetch("https://api.example.com/users");
const users = await response.json();
 
// POST 요청 with JSON body
const createResponse = await fetch("https://api.example.com/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": "Bearer token123",
  },
  body: JSON.stringify({
    name: "김개발",
    email: "dev@example.com",
  }),
});
 
// 응답 상태 확인
if (!createResponse.ok) {
  throw new Error(`HTTP ${createResponse.status}: ${createResponse.statusText}`);
}
 
const newUser = await createResponse.json();
Info

Deno의 fetch는 브라우저의 fetch와 거의 동일하지만, 서버 환경에 맞는 추가 기능도 있습니다. 예를 들어 로컬 파일도 file: 프로토콜로 fetch할 수 있고, HTTPS 인증서 검증 관련 옵션도 제공합니다.

Streams API

Streams API는 대용량 데이터를 청크(chunk) 단위로 처리할 때 필수적인 웹 표준입니다. Deno는 ReadableStream, WritableStream, TransformStream을 완전히 지원합니다.

Streams API 활용
typescript
// ReadableStream으로 대용량 파일 처리
const file = await Deno.open("./large-data.csv");
const readable = file.readable;
 
// TransformStream으로 데이터 변환
const lineTransform = new TransformStream<Uint8Array, string>({
  transform(chunk, controller) {
    const text = new TextDecoder().decode(chunk);
    const lines = text.split("\n");
    for (const line of lines) {
      if (line.trim()) {
        controller.enqueue(line);
      }
    }
  },
});
 
// WritableStream으로 결과 출력
const writable = new WritableStream<string>({
  write(line) {
    console.log("처리:", line);
  },
});
 
// 파이프라인 연결
await readable
  .pipeThrough(lineTransform)
  .pipeTo(writable);
fetch 응답의 스트리밍 처리
typescript
// SSE(Server-Sent Events) 스트리밍 읽기
const response = await fetch("https://api.example.com/stream");
const reader = response.body?.getReader();
 
if (reader) {
  const decoder = new TextDecoder();
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    console.log(decoder.decode(value));
  }
}

WebSocket API

WebSocket은 브라우저와 동일한 인터페이스를 사용합니다.

WebSocket 클라이언트
typescript
// WebSocket 연결 (브라우저와 동일한 API)
const ws = new WebSocket("wss://echo.websocket.org");
 
ws.addEventListener("open", () => {
  console.log("연결 성공");
  ws.send(JSON.stringify({ type: "hello", data: "안녕하세요" }));
});
 
ws.addEventListener("message", (event) => {
  const data = JSON.parse(event.data);
  console.log("수신:", data);
});
 
ws.addEventListener("close", (event) => {
  console.log(`연결 종료: ${event.code} ${event.reason}`);
});
 
ws.addEventListener("error", (event) => {
  console.error("WebSocket 에러:", event);
});
Tip

Deno의 HTTP 서버에서 WebSocket 업그레이드도 간단하게 처리할 수 있습니다. Deno.serve 내에서 Deno.upgradeWebSocket(request)를 호출하면 WebSocket 연결로 전환됩니다. 이 내용은 9장의 REST API 구축에서 더 자세히 다룹니다.

Web Crypto API

Web Crypto API는 암호화 관련 표준 인터페이스입니다. 해시 생성, 암호화/복호화, 서명/검증 등을 수행합니다.

Web Crypto API 활용
typescript
// SHA-256 해시 생성
async function hashText(text: string): Promise<string> {
  const encoder = new TextEncoder();
  const data = encoder.encode(text);
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
}
 
const hash = await hashText("안녕하세요");
console.log("SHA-256:", hash);
 
// UUID 생성
const uuid = crypto.randomUUID();
console.log("UUID:", uuid);
 
// HMAC 서명 생성
const key = await crypto.subtle.generateKey(
  { name: "HMAC", hash: "SHA-256" },
  true,
  ["sign", "verify"],
);
 
const signature = await crypto.subtle.sign(
  "HMAC",
  key,
  new TextEncoder().encode("서명할 데이터"),
);

URL과 URLSearchParams

URL 처리는 브라우저 표준 URL 클래스를 사용합니다.

URL 처리
typescript
// URL 파싱
const url = new URL("https://api.example.com/search?q=deno&page=1");
console.log(url.hostname);       // "api.example.com"
console.log(url.pathname);       // "/search"
console.log(url.searchParams.get("q"));  // "deno"
 
// URLSearchParams로 쿼리 문자열 구성
const params = new URLSearchParams({
  query: "Deno 런타임",
  limit: "10",
  offset: "0",
});
const apiUrl = `https://api.example.com/search?${params}`;
// "https://api.example.com/search?query=Deno+%EB%9F%B0%ED%83%80%EC%9E%84&limit=10&offset=0"

AbortController

비동기 작업의 취소를 위한 표준 메커니즘입니다.

AbortController로 요청 타임아웃 구현
typescript
async function fetchWithTimeout(
  url: string,
  timeoutMs: number,
): Promise<Response> {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
 
  try {
    const response = await fetch(url, { signal: controller.signal });
    return response;
  } catch (error) {
    if (error instanceof DOMException && error.name === "AbortError") {
      throw new Error(`요청 타임아웃: ${timeoutMs}ms 초과`);
    }
    throw error;
  } finally {
    clearTimeout(timeoutId);
  }
}
 
// 5초 타임아웃으로 요청
const response = await fetchWithTimeout("https://api.example.com/data", 5000);

Deno 네이티브 API

Deno.serve(): 고성능 HTTP 서버

Deno.serve()는 Deno의 대표적인 네이티브 API입니다. 최소한의 코드로 고성능 HTTP 서버를 구축할 수 있습니다.

Deno.serve() 기본 사용
typescript
// 가장 간단한 HTTP 서버
Deno.serve((_req) => new Response("Hello, Deno!"));
 
// 포트와 호스트 지정
Deno.serve({ port: 8080, hostname: "0.0.0.0" }, (req) => {
  const url = new URL(req.url);
 
  if (url.pathname === "/api/health") {
    return new Response(JSON.stringify({ status: "ok" }), {
      headers: { "Content-Type": "application/json" },
    });
  }
 
  if (url.pathname === "/api/users" && req.method === "GET") {
    const users = [
      { id: 1, name: "김개발" },
      { id: 2, name: "이서버" },
    ];
    return new Response(JSON.stringify(users), {
      headers: { "Content-Type": "application/json" },
    });
  }
 
  return new Response("Not Found", { status: 404 });
});
Info

Deno.serve()는 웹 표준 Request와 Response 객체를 직접 사용합니다. Express의 req.body, res.json() 같은 추상화 대신, 브라우저에서 사용하는 것과 동일한 API로 서버를 구축합니다. 이것이 Deno의 "웹 표준 우선" 철학을 가장 잘 보여주는 부분입니다.

WebSocket 서버

WebSocket 서버 구현
typescript
Deno.serve({ port: 8080 }, (req) => {
  // WebSocket 업그레이드 요청 확인
  if (req.headers.get("upgrade") === "websocket") {
    const { socket, response } = Deno.upgradeWebSocket(req);
 
    socket.addEventListener("open", () => {
      console.log("클라이언트 연결");
    });
 
    socket.addEventListener("message", (event) => {
      console.log("수신:", event.data);
      socket.send(`에코: ${event.data}`);
    });
 
    socket.addEventListener("close", () => {
      console.log("클라이언트 연결 해제");
    });
 
    return response;
  }
 
  return new Response("WebSocket 서버", {
    headers: { "Content-Type": "text/plain; charset=utf-8" },
  });
});

Deno 파일 시스템 API

Deno는 파일 시스템 접근을 위한 자체 API를 제공합니다. Node.js의 fs 모듈과 유사하지만, 기본적으로 비동기이며 Promise 기반입니다.

Deno 파일 시스템 API
typescript
// 텍스트 파일 읽기/쓰기
const content = await Deno.readTextFile("./data.json");
await Deno.writeTextFile("./output.json", JSON.stringify({ result: "ok" }));
 
// 바이너리 파일 읽기/쓰기
const bytes = await Deno.readFile("./image.png");
await Deno.writeFile("./copy.png", bytes);
 
// 디렉토리 탐색
for await (const entry of Deno.readDir("./src")) {
  console.log(`${entry.isFile ? "파일" : "디렉토리"}: ${entry.name}`);
}
 
// 파일 정보 조회
const stat = await Deno.stat("./data.json");
console.log(`크기: ${stat.size} bytes`);
console.log(`수정일: ${stat.mtime}`);
 
// 저수준 파일 API (스트리밍 처리에 유용)
const file = await Deno.open("./large-file.csv", { read: true });
const buffer = new Uint8Array(1024);
const bytesRead = await file.read(buffer);
file.close();

Deno.KV: 내장 키-값 저장소

Deno.KV는 Deno에 내장된 키-값 데이터베이스입니다. 별도의 데이터베이스 서버 없이 영구 데이터를 저장할 수 있으며, Deno Deploy에서는 전역 분산 스토리지로 동작합니다.

Deno.KV 기본 사용법
typescript
// KV 저장소 열기
const kv = await Deno.openKv();
 
// 데이터 저장
await kv.set(["users", "user-001"], {
  name: "김개발",
  email: "dev@example.com",
  createdAt: new Date().toISOString(),
});
 
// 데이터 조회
const result = await kv.get(["users", "user-001"]);
console.log(result.value); // { name: "김개발", ... }
 
// 데이터 목록 조회 (접두사 기반)
const iter = kv.list({ prefix: ["users"] });
for await (const entry of iter) {
  console.log(entry.key, entry.value);
}
 
// 데이터 삭제
await kv.delete(["users", "user-001"]);
Deno.KV 원자적 트랜잭션
typescript
const kv = await Deno.openKv();
 
// 원자적 연산 (동시성 제어)
const user = await kv.get(["users", "user-001"]);
 
const result = await kv.atomic()
  .check(user) // 버전 확인 (낙관적 잠금)
  .set(["users", "user-001"], {
    ...user.value as Record<string, unknown>,
    lastLogin: new Date().toISOString(),
  })
  .commit();
 
if (!result.ok) {
  console.log("동시 수정 충돌 - 재시도 필요");
}
Warning

Deno.KV는 간단한 데이터 저장에는 적합하지만, 복잡한 쿼리나 관계형 데이터 모델링이 필요한 경우에는 PostgreSQL 같은 전용 데이터베이스를 사용하는 것이 적합합니다. KV의 키는 배열 형태로 계층 구조를 표현하며, 접두사 기반 범위 조회만 지원합니다.

Deno.Command: 프로세스 실행

외부 프로세스를 실행하기 위한 API입니다.

Deno.Command 사용
typescript
// 외부 명령 실행
const command = new Deno.Command("git", {
  args: ["log", "--oneline", "-5"],
  stdout: "piped",
  stderr: "piped",
});
 
const { code, stdout, stderr } = await command.output();
 
if (code === 0) {
  const output = new TextDecoder().decode(stdout);
  console.log("최근 커밋 목록:");
  console.log(output);
} else {
  const error = new TextDecoder().decode(stderr);
  console.error("에러:", error);
}

TypeScript 기본 지원

Deno는 TypeScript를 일급 시민(first-class citizen)으로 취급합니다. 별도의 설정이나 컴파일 과정 없이 .ts 파일을 직접 실행할 수 있습니다.

설정 없는 TypeScript 실행
typescript
// main.ts - 바로 실행 가능
interface User {
  id: number;
  name: string;
  email: string;
}
 
async function getUser(id: number): Promise<User> {
  const response = await fetch(`https://api.example.com/users/${id}`);
  if (!response.ok) {
    throw new Error(`사용자를 찾을 수 없습니다: ${id}`);
  }
  return response.json();
}
 
const user = await getUser(1);
console.log(`사용자: ${user.name} (${user.email})`);
TypeScript 직접 실행
bash
# 아무 설정 없이 바로 실행
deno run --allow-net main.ts
 
# 타입 체크만 수행
deno check main.ts

Node.js에서는 TypeScript를 사용하려면 typescript 패키지 설치, tsconfig.json 설정, 빌드 스크립트 구성 등의 과정이 필요합니다. Deno에서는 이 모든 과정이 생략됩니다.

deno.json - TypeScript 컴파일러 옵션 (필요한 경우만)
json
{
  "compilerOptions": {
    "strict": true,
    "jsx": "react-jsx",
    "jsxImportSource": "react",
    "lib": ["deno.window", "dom"]
  }
}
Tip

대부분의 경우 compilerOptions를 별도로 설정할 필요가 없습니다. Deno의 기본 TypeScript 설정은 이미 strict: true이며, 서버 개발에 적합한 라이브러리가 포함되어 있습니다. JSX를 사용하거나 브라우저 DOM 타입이 필요한 경우에만 설정을 추가하면 됩니다.

API 설계 철학 정리

Deno의 API 설계를 관통하는 철학을 정리하면 다음과 같습니다.

웹 표준이 있으면 웹 표준을 사용합니다. fetch, URL, Streams, WebSocket, crypto 등 브라우저에서 표준화된 API는 서버에서도 그대로 사용합니다.

서버 전용 기능만 Deno 네임스페이스를 사용합니다. 파일 시스템 접근, 프로세스 실행, 권한 관리 등 브라우저에 존재하지 않는 기능만 Deno.* API로 제공합니다.

Promise 기반 비동기가 기본입니다. 콜백 패턴 대신 async/await를 기본으로 사용합니다. 동기 버전(Sync 접미사)도 제공하지만, 비동기가 권장됩니다.

다음 장에서는 Bun과의 상세 비교를 통해 두 현대 런타임의 차이점을 분석합니다. 성능 벤치마크, API 호환성, 생태계 성숙도 등 실무 선택에 필요한 기준을 제시합니다.

이 글이 도움이 되셨나요?

관련 글

프로그래밍

6장: Bun과의 비교 - 성능, 호환성, 생태계

Deno 2와 Bun을 심층 비교합니다. 아키텍처 차이, 성능 벤치마크, API 호환성, 생태계 성숙도, 그리고 프로젝트 특성에 따른 선택 기준을 제시합니다.

2026년 7월 24일·18분
프로그래밍

4장: npm 호환과 패키지 관리

Deno 2의 npm 호환성, JSR(JavaScript Registry), import map, deno add를 통한 패키지 관리, 그리고 Node.js에서 Deno로의 마이그레이션 전략을 다룹니다.

2026년 7월 18일·16분
프로그래밍

3장: Deno의 보안 모델 - 권한 기반 실행

Deno의 권한 기반 보안 모델을 심층 분석합니다. 각 권한 플래그의 동작 원리, Node.js와의 보안 비교, 공급망 공격 방어, 그리고 실무 보안 모범 사례를 다룹니다.

2026년 7월 16일·20분
이전 글4장: npm 호환과 패키지 관리
다음 글6장: Bun과의 비교 - 성능, 호환성, 생태계

댓글

목차

약 15분 남음
  • 웹 표준을 선택한 이유
  • 웹 표준 API 상세
    • fetch API
    • Streams API
    • WebSocket API
    • Web Crypto API
    • URL과 URLSearchParams
    • AbortController
  • Deno 네이티브 API
    • Deno.serve(): 고성능 HTTP 서버
    • WebSocket 서버
    • Deno 파일 시스템 API
    • Deno.KV: 내장 키-값 저장소
    • Deno.Command: 프로세스 실행
  • TypeScript 기본 지원
  • API 설계 철학 정리