백엔드 없이 만료되는 링크를 만든 방법 (React + TypeScript Only)

발행: (2026년 4월 29일 AM 11:12 GMT+9)
6 분 소요
원문: Dev.to

Source: Dev.to

Introduction

대부분의 “만료 링크” 도구는 같은 방식으로 동작합니다: 링크를 생성하고, 목적지와 만료 시간을 데이터베이스에 저장한 뒤, 클릭할 때마다 데이터베이스를 확인하고 그에 따라 리다이렉트하거나 차단합니다.
이 접근 방식은 백엔드, 데이터베이스, 서버 비용, 그리고 보안 위험을 필요로 합니다.

저는 React + TypeScript만 사용하고, Vercel에 배포하며 Node.js도, 데이터베이스도, 백엔드도 전혀 없는 제약이 있었습니다.
해결책은 링크 데이터를 URL 자체에 인코딩하는 것이었습니다.

How It Works

사용자가 만료 링크를 만들면 앱은 다음을 수행합니다:

  1. 목적지 URL을 가져옵니다.
  2. 만료 타임스탬프(Unix ms)를 가져옵니다.
  3. 두 값을 JSON 객체로 결합합니다.
  4. btoa()(Base64)로 JSON을 인코딩합니다.
  5. 인코딩된 페이로드를 URL 파라미터로 추가합니다.
  6. TinyURL API를 이용해 전체 URL을 단축합니다.
// Create payload
const payload = {
  url: destinationUrl,
  exp: expiryTimestamp
};

const encoded = btoa(JSON.stringify(payload));
const longUrl = `https://onetimelink.vercel.app/r?d=${encoded}`;

// Shorten (TinyURL)
const shortUrl = await shortenWithTinyURL(longUrl);

누군가 짧은 링크를 방문하면 TinyURL이 이를 다시 긴 URL로 확장합니다. React 앱은 클라이언트‑사이드에서 파라미터를 디코드합니다:

const params = new URLSearchParams(window.location.search);
const encoded = params.get('d');

if (!encoded) {
  // Invalid link
  return;
}

try {
  const payload = JSON.parse(atob(encoded));
  const now = Date.now();

  if (now > payload.exp) {
    // Expired — show expiration screen
    setExpired(true);
  } else {
    // Valid — redirect
    window.location.href = payload.url;
  }
} catch {
  // Malformed link
  setInvalid(true);
}

데이터베이스 조회도, 서버 호출도, 어디에도 저장된 데이터도 없습니다. 링크 자체에 만료 정보가 담겨 있으며, 리다이렉트 여부 판단은 전부 브라우저에서 이루어집니다.

Benefits

  • 스토리지 제로 → 보안 위험 제로. 데이터는 공유된 URL에만 존재합니다.
  • 서버 비용 없음. 제품은 Vercel 무료 티어에서 실행되며, 링크 방문 시 서버‑사이드 연산이 전혀 발생하지 않습니다.
  • 오프라인에서도 부분적으로 동작. URL이 캐시돼 있다면, 만료 검사는 단순히 타임스탬프 비교이므로 여전히 작동합니다.

Limitations

LimitationDetails
URL 길이JSON 객체를 Base64‑인코딩하면 문자 수가 늘어납니다. TinyURL이 링크를 짧게 만들어 주지만, 중간 URL은 길어질 수 있습니다.
서버‑사이드 검증 부재사용자가 페이로드를 디코드하고, 만료 타임스탬프를 수정한 뒤 다시 인코드해 “만료되지 않는” 링크를 만들 수 있습니다. 캐주얼한 사용 사례에는 적합하지만, 적대적인 상황에는 부적합합니다.
분석 기능 없음서버‑사이드 저장소가 없으므로 클릭 수를 추적하거나 대시보드를 볼 수 없습니다.
조기 폐기 불가한 번 생성되면 링크는 타임스탬프가 지나야만 만료되며, 조기에 삭제할 방법이 없습니다.

Ideal Use Cases

  • 임시 로그인 자격 증명을 전달할 때.
  • 리뷰 기간 동안의 스테이징 환경 링크.
  • 자연스러운 종료 날짜가 있는 비공개 문서.

이러한 시나리오에서는 제한 사항이 허용됩니다: 클라이언트가 한 번 클릭해 필요한 정보를 얻고, 창이 닫히면 링크가 사라집니다.

분석, 다중 클릭 추적, 조기 폐기 등이 필요하다면 적절한 백엔드가 필요합니다.

Tech Stack

  • React + TypeScript
  • Vite for bundling
  • Vercel (free tier) for deployment
  • TinyURL API (free tier, no authentication)
  • Built‑in browser functions btoa() / atob() for encoding

Total server infrastructure cost: $0.

Conclusion

백엔드의 오버헤드 없이 민감한 링크를 일시적으로 공유해야 할 때, 만료 데이터를 URL에 인코딩하는 방법은 실현 가능한, 비용이 전혀 들지 않는 대안이 됩니다. 실제 구현은 – 무료로 사용 가능하고, 계정도 필요 없습니다.

자세한 아키텍처와 제품 방향은 OneTimeLink 블로그에서 확인할 수 있습니다.

0 조회
Back to Blog

관련 글

더 보기 »