인셔셔RSS 관심 있는 블로그, 뉴스, 기술 정보를 효율적으로 추적하고 읽으세요
원문 읽기 InertiaRSS에서 열기

추천 피드

小众软件
小众软件
博客园 - 叶小钗
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
Hugging Face - Blog
Hugging Face - Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
aimingoo的专栏
aimingoo的专栏
Blog — PlanetScale
Blog — PlanetScale
爱范儿
爱范儿
T
Tailwind CSS Blog
Jina AI
Jina AI
量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
V
Visual Studio Blog
月光博客
月光博客

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python)
더 좋은 기본 키: Rails 개발자를 위한 ULIDs 가이드
Zil Norvilis · 2026-05-28 · via DEV Community

이전 기사에서 Snowflake IDs에 대해 이야기했습니다. 그들은 매우 좋지만, "Worker IDs"를 관리해야 하므로 약간의 구성이 필요합니다.

더 간단한 것을 원하면서도 동일한 이점(보안 URL과 빠른 데이터베이스 정렬)을 얻고 싶다면 ULIDs (Universally Unique Lexicographically Sortable Identifiers)를 살펴보아야 합니다.

왜 UUID를 사용하지 않을까요?

대부분의 개발자는 자동 증가하는 정수에서 UUID로 전환하는 이유는 그들이 자신의 사업 규모를 숨기고 싶기 때문입니다. 주문 ID가 order/550e8400-e29b...라면, 당신이 1명의 고객이든 100만 명의 고객이든 아무도 모릅니다.

하지만 UUID는 큰 문제가 있습니다: 그들은 완전히 무작위입니다.
백만 개의 무작위 UUID를 데이터베이스에 삽입하면 "B-Tree" 인덱스가 분할되고 느려집니다. 당신의 데이터베이스는 새로운 데이터를 넣을 위치를 하드 디스크 전체를 뛰어다니며 찾아야 합니다.

ULIDs는 이를 해결합니다.
ULID는 128비트(UUID와 같습니다)이지만 ID의 첫 부분은 시간戳입니다는 이를 의미합니다 ULIDs는 시간 순서대로입니다. UUID와 같이 고유하지만 정수와 같이 정렬됩니다.

Rails 8 앱에서 ULIDs를 구현하는 방법은 다음 4단계로 간단합니다.

단계 1: Gem 설치

우리는 문자열을 생성하기 위해 ulid gem을 사용할 것입니다. 이를 Gemfile에 추가하세요.

gem "ulid"

Enter fullscreen mode Exit fullscreen mode

터미널에서 bundle install를 실행하세요.

단계 2: ULID 문제

우리는 모델에 ULIDs를 추가하는 것을 매우 쉽게 만들고 싶습니다. 이를 위해 Concern을 사용하는 것이 가장 좋습니다. 이 코드는 새로운 레코드를 생성할 때마다 ULID가 생성되고 ID에 할당되도록 보장합니다.

app/models/concerns/has_ulid.rb에서 새로운 파일을 만드세요:

# app/models/concerns/has_ulid.rb
module HasUlid
  extend ActiveSupport::Concern

  included do
    # Before we save to the DB, generate the ULID
    before_create :set_ulid
  end

  private

  def set_ulid
    # ULID.generate creates a string like: 01ARZ3NDEKTSV4RRFFQ69G5FAV
    self.id ||= ULID.generate
  end
end

전체 화면 모드로 전환 전체 화면 모드 종료

단계 3: 이전 작업

새로운 모델을 만들 때는 Rails에 id이(가) string이(가)라는 것을 알려야 하며, 기본 자동 증가 논리를 비활성화해야 합니다.

rails g model Product name:string

전체 화면 모드로 전환 전체 화면 모드 종료

이민 파일을 엽니다하고 이렇게 수정하세요:

# db/migrate/XXXXXXXXXXXXXX_create_products.rb
class CreateProducts < ActiveRecord::Migration[8.0]
  def change
    # id: false stops the automatic integer ID
    create_table :products, id: false do |t|
      # We use string for ULID primary key
      t.string :id, primary_key: true
      t.string :name

      t.timestamps
    end
  end
end

전체 화면 모드로 입력하세요 전체 화면 모드 종료

단계 4: 모델을 업데이트합니다

이제 단계 2에서 쓴 우려 사항만 포함하세요.

# app/models/product.rb
class Product < ApplicationRecord
  include HasUlid
end

전체 화면 모드로 입력하세요 전체 화면 모드 종료

STEP 5: 작동하는 모습을 보세요

Rails 콘솔을 엽니다bin/rails c) 몇 가지 제품을 만드세요:

Product.create(name: "Laptop")
Product.create(name: "Monitor")
Product.create(name: "Keyboard")

# Check the IDs
Product.pluck(:id)
# => ["01HQV...", "01HQV...", "01HQV..."]

전체 화면 모드를 입력하세요 전체 화면 모드를 종료하세요

자세히 보면 모든 ID가 동일한 문자로 시작합니다. 같은 분에 생성되었기 때문입니다. 정렬할 수 있으므로 여전히 Product.order(:id)를 실행할 수 있으며, 그들은 올바른 시간 순서로 정렬됩니다!

왜 Rails에서 ULIDs를 선호하는가

  1. 더 나은 성능: ID가 정렬할 수 있기 때문에 PostgreSQL (또는 SQLite)는 인덱스 끝에 이를 추가할 수 있습니다. 이는 "쓰기 집중형" 앱에 비해 랜덤 UUID보다 훨씬 빠릅니다.
  2. 읽기 쉬움: ULIDs는 혼동을 유발하는 문자("I", "L", "O" 등)를 제외한 특별한 알파벳(Crockford's Base32)을 사용합니다. 이로 인해 사용자가 입력해야 할 경우 더 쉽게 읽을 수 있습니다.
  3. 설정 없음: Snowflake ID와는 달리 서버 ID나 워커 노드를 구성할 필요가 없습니다. 그저 gem을 설치하고 사용하면 됩니다.

거의 그것이 전부입니다. 애플리케이션을 훨씬 더 전문적이고 확장 가능하게 만드는 작은 아키텍처 변경입니다.