· Nacho Coll · Guides · 15 분 소요
IPFS CID 설명: CID란 무엇이며 콘텐츠 주소 지정 방식
IPFS Content Identifier (CID)에 대한 명확한 기술 설명. 콘텐츠 주소 지정 방식, CID 버전, 그리고 첫 CID 생성 방법까지.

IPFS (InterPlanetary File System)를 다뤄봤다면 QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG 또는 bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi 같은 문자열을 본 적이 있을 겁니다. 이는 무작위 문자열이 아니라 Content Identifier (CID) — IPFS 콘텐츠 주소 지정 시스템의 중추입니다.
CID를 이해하는 것은 IPFS 위에서 무언가를 만드는 모든 사람에게 필수적입니다. 파일을 업로드하든, 탈중앙화 애플리케이션을 만들든, 콘텐츠 배포 시스템을 구현하든 마찬가지입니다. 이 가이드는 IPFS CID에 대해 알아야 할 모든 것, 콘텐츠 주소 지정의 작동 방식, 그리고 프로젝트에서 CID를 시작하는 방법을 분해해 설명합니다.

IPFS CID란?
**Content Identifier (CID)**는 IPFS에서 콘텐츠 한 조각을 나타내는 고유한 지문입니다. 위치를 가리키는 전통적인 웹 URL(예: https://example.com/file.pdf)과 달리, CID는 저장된 위치와 관계없이 콘텐츠 그 자체를 가리킵니다.
이렇게 생각해 보세요:
- 위치 기반 주소 지정: “메인 스트리트 123번지로 가서 빨간 책을 달라고 하세요”
- 콘텐츠 기반 주소 지정: “ISBN 978-0-123456-78-9 책을 찾으세요” (어느 도서관에 있든 상관없음)
CID도 비슷하게 작동합니다 — 암호학적 해시로 콘텐츠를 식별하므로 콘텐츠는 불변이고 검증 가능합니다. 파일에서 단 1바이트라도 바뀌면 CID는 완전히 달라집니다.
콘텐츠 주소 지정이 중요한 이유
전통적인 웹 아키텍처는 위치 기반 주소 지정에 의존합니다. https://example.com/image.jpg를 방문할 때 당신은 다음을 신뢰합니다:
- 도메인 소유자가 콘텐츠를 바꾸지 않았다
- 서버가 온라인이고 접근 가능하다
- 콘텐츠가 변조되지 않았다
CID를 사용한 콘텐츠 주소 지정에서는:
- 불변성: CID는 콘텐츠가 변경되지 않았음을 보장
- 탈중앙화: 콘텐츠를 가진 모든 IPFS 노드에서 가져올 수 있음
- 검증: 받은 콘텐츠가 올바른지 암호학적으로 검증 가능
- 효율성: 동일한 콘텐츠는 자동으로 중복 제거
CID의 구조
전형적인 CID를 분해해 그 구성 요소를 이해해 봅시다:
bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
└─┬─┘└─────────────────┬─────────────────────────────────┘
│ │
│ └─ 콘텐츠 해시 (Base32 인코딩됨)
└─ Multibase 접두사 (인코딩을 나타냄)CID에는 몇 가지 정보가 담겨 있습니다:
1. Multibase 접두사
첫 문자는 CID가 어떻게 인코딩되었는지 나타냅니다:
Q= Base58 인코딩 (CIDv0)b= Base32 인코딩 (CIDv1)f= Base16/16진수 (CIDv1)z= Base58 (CIDv1)
2. CID 버전
- CIDv0: 항상
Qm으로 시작, SHA-256 사용, DAG-PB 코덱으로 제한 - CIDv1: 더 유연, 다양한 해시 함수와 코덱 지원
3. Multicodec
콘텐츠가 어떻게 구조화되어 있는지 지정 (DAG-PB, DAG-CBOR, 원시 바이트 등)
4. Multihash
콘텐츠의 실제 암호학적 해시로 다음을 포함:
- 해시 함수 식별자 (보통 SHA-256)
- 해시 길이
- 해시 다이제스트
CIDv0 vs CIDv1: 차이점 이해하기
IPFS는 두 가지 주요 CID 버전을 거쳐 진화했으며 각각 고유한 특성을 가집니다:
CIDv0: 원래 형식
CIDv0 CID는 항상 Qm으로 시작하며 다음과 같이 생겼습니다:
QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG특성:
- Base58 인코딩만
- SHA-256 해시 함수만
- DAG-PB (Protobuf) 코덱만
- 46자 길이
- 모든 IPFS 구현과 하위 호환
CIDv0를 사용할 때:
- 오래된 IPFS 노드와의 최대 호환성
Qm접두사를 기대하는 기존 시스템과의 작업- 파일 저장 (가장 일반적인 사용 사례)
CIDv1: 현대 표준
CIDv1 CID는 더 유연하고 다음과 같이 보일 수 있습니다:
bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi # Base32
zb2rhj7crUKTQYRGCRATFaQ6YFLTde2YzdqbbhAASkL9uRDXn # Base58
f01551220d1e2c35... # Base16특성:
- 여러 인코딩 형식 (Base32, Base58, Base16)
- 다양한 해시 함수 지원 (SHA-256, SHA-512, BLAKE2 등)
- 여러 코덱 (Raw, DAG-CBOR, DAG-JSON 등)
- 자가 설명적 형식
- Base32 사용 시 대소문자 구분 없음
CIDv1를 사용할 때:
- 새 애플리케이션 구축
- 대소문자 구분 없는 식별자가 필요할 때
- 구조화된 데이터 (JSON, CBOR) 작업
- 대체 해시 함수 사용
버전 간 변환
동일한 콘텐츠 참조를 유지하면서 CID를 버전 간 변환할 수 있습니다:
// CIDv0
const cidv0 = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
// Convert to CIDv1 Base32
const cidv1 = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi";
// Both reference the same content!콘텐츠 주소 지정 작동 방식
IPFS에서 콘텐츠 주소 지정은 동일한 콘텐츠가 항상 동일한 CID를 생성하도록 보장하는 결정론적 프로세스를 따릅니다:
1. 콘텐츠 준비
IPFS에 콘텐츠를 추가하면 먼저 분해됩니다:
- 작은 파일: 단일 블록으로 저장
- 큰 파일: 청크로 분할되어 Merkle DAG (Directed Acyclic Graph)로 조직됨
- 디렉터리: 파일을 연결하는 DAG 구조로 표현
2. 해싱 프로세스
각 콘텐츠 조각은 다음을 거칩니다:
- 직렬화: 콘텐츠가 코덱에 따라 포맷됨
- 해싱: 암호학적 해시 함수가 직렬화된 데이터를 처리
- Multihash 생성: 해시가 알고리즘과 길이 정보로 래핑됨
- CID 조립: 버전, 코덱, Multihash가 결합됨
3. Merkle DAG 구조
IPFS는 Merkle DAG로 콘텐츠를 조직하며 거기서:
- 각 노드가 CID를 가짐
- 부모 노드는 CID로 자식 노드를 참조
- 모든 노드의 변경 사항은 트리 위로 전파
- 전체 구조를 암호학적으로 검증 가능
Root CID: bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi
├── file1.txt (QmHash1...)
├── file2.jpg (QmHash2...)
└── subdirectory/
├── file3.pdf (QmHash3...)
└── file4.mp4 (QmHash4...)실용적 예제: CID 작업하기
IPFS Ninja의 API를 사용해 실제로 CID를 어떻게 다루는지 살펴봅시다:
콘텐츠 업로드와 CID 얻기
// Upload a file and get its CID
const uploadFile = async (content, filename) => {
const response = await fetch('https://api.ipfs.ninja/upload/new', {
method: 'POST',
headers: {
'X-Api-Key': 'bws_1234567890abcdef1234567890abcdef12345678',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: btoa(content), // Base64 encode binary content
description: `Upload of ${filename}`
})
});
const result = await response.json();
console.log('CID:', result.cid);
console.log('IPFS URL:', result.uris.ipfs);
console.log('HTTP URL:', result.uris.url);
return result.cid;
};
// Example usage
uploadFile('Hello, IPFS!', 'greeting.txt');
// Returns: bafkreifjxz6zwqh27k5xnr5qfbx4w6n5vuwwwdcngguwjewzj2e3xxfgvi기존 콘텐츠를 CID로 핀
이미 CID가 있다면 핀해서 계속 사용 가능하도록 만들 수 있습니다:
const pinByCID = async (cid) => {
const response = await fetch('https://api.ipfs.ninja/pin', {
method: 'POST',
headers: {
'X-Api-Key': 'bws_1234567890abcdef1234567890abcdef12345678',
'Content-Type': 'application/json'
},
body: JSON.stringify({
cid: cid,
description: 'Pinned via API'
})
});
const result = await response.json();
console.log('Pinned CID:', result.cid);
return result;
};
// Pin the "Hello World" of IPFS
pinByCID('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u');CID로 콘텐츠 접근
CID가 있으면 여러 방법으로 콘텐츠에 접근할 수 있습니다:
// Direct IPFS gateway access
const ipfsUrl = `https://ipfs.ninja/ipfs/${cid}`;
// Custom gateway (if configured)
const customGatewayUrl = `https://my-app.gw.ipfs.ninja/ipfs/${cid}`;
// Fetch content programmatically
const fetchContent = async (cid) => {
const response = await fetch(`https://ipfs.ninja/ipfs/${cid}`);
const content = await response.text();
return content;
};개발자를 위한 CID 모범 사례
1. 항상 CID 검증
애플리케이션에서 CID를 사용하기 전에 형식을 검증하세요:
const isValidCID = (cid) => {
// Basic validation patterns
const cidv0Pattern = /^Qm[1-9A-HJ-NP-Za-km-z]{44}$/;
const cidv1Pattern = /^[bf][a-z2-7]{58}$/;
return cidv0Pattern.test(cid) || cidv1Pattern.test(cid);
};2. 두 CID 버전 모두 처리
애플리케이션은 CIDv0와 CIDv1 모두에서 작동해야 합니다:
const normalizeCID = (cid) => {
if (cid.startsWith('Qm')) {
// CIDv0 - can convert to CIDv1 if needed
return cid;
} else if (cid.startsWith('b') || cid.startsWith('f') || cid.startsWith('z')) {
// CIDv1
return cid;
} else {
throw new Error('Invalid CID format');
}
};3. CID 매핑 캐싱
CID를 자주 생성한다면 캐싱을 고려하세요:
const cidCache = new Map();
const getCachedCID = (content) => {
const contentHash = btoa(content);
if (cidCache.has(contentHash)) {
return cidCache.get(contentHash);
}
// Upload and cache result
return uploadFile(content).then(cid => {
cidCache.set(contentHash, cid);
return cid;
});
};4. 의미 있는 설명 사용
콘텐츠를 업로드할 때 설명적인 메타데이터를 포함하세요:
const uploadWithMetadata = async (content, metadata) => {
return fetch('https://api.ipfs.ninja/upload/new', {
method: 'POST',
headers: {
'X-Api-Key': 'bws_1234567890abcdef1234567890abcdef12345678',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: btoa(content),
description: metadata.name || 'Uploaded file',
metadata: {
filename: metadata.filename,
contentType: metadata.contentType,
uploadedAt: new Date().toISOString(),
version: metadata.version || '1.0'
}
})
});
};CID의 일반적인 사용 사례
1. 정적 웹사이트 배포
전체 웹사이트를 IPFS에 배포하고 CID로 참조:
// Upload website directory structure
const deployWebsite = async (files) => {
const uploads = await Promise.all(
files.map(file => uploadFile(file.content, file.path))
);
// Root CID references entire site
const rootCID = uploads.find(u => u.path === 'index.html').cid;
console.log(`Website deployed: https://ipfs.ninja/ipfs/${rootCID}`);
return rootCID;
};웹사이트 배포에 대해 더 알고 싶다면 IPFS에 파일 업로드하는 방법 가이드를 확인하세요.
2. NFT 메타데이터 저장
CID를 사용해 NFT 메타데이터를 불변으로 저장:
const nftMetadata = {
name: "My Awesome NFT",
description: "A unique digital collectible",
image: "ipfs://bafkreibc5sgo2plmjkq2tzmhrn54bk3crhnqekiy7u66fqvqm37pu2e5gw",
attributes: [
{ trait_type: "Color", value: "Blue" },
{ trait_type: "Rarity", value: "Epic" }
]
};
const metadataCID = await uploadFile(
JSON.stringify(nftMetadata, null, 2),
'metadata.json'
);
// Use in smart contract
console.log(`Token URI: ipfs://${metadataCID}`);3. 콘텐츠 배포
분산 콘텐츠 전달에 CID 사용:
// Upload once, access everywhere
const distributeContent = async (content) => {
const cid = await uploadFile(content, 'content.txt');
// Content available via multiple gateways
const gateways = [
`https://ipfs.ninja/ipfs/${cid}`,
`https://ipfs.io/ipfs/${cid}`,
`https://cloudflare-ipfs.com/ipfs/${cid}`
];
return { cid, gateways };
};CID로 IPFS 핀닝 이해하기
CID는 기본적으로 임시적입니다 — 사용 가능하게 유지하려면 “핀”되어야 합니다. 이 중요한 개념에 대한 종합 가이드인 IPFS 핀닝이란 무엇인가에서 더 알아보세요.
IPFS 핀닝 서비스를 선택할 때 IPFS Ninja vs Pinata 비교를 읽거나 오늘 사용할 수 있는 최고의 IPFS 핀닝 서비스 요약을 살펴보세요.
30초만에 첫 CID 생성
첫 CID를 생성할 준비가 되셨나요? IPFS Ninja의 API를 사용한 빠른 예제입니다:
# Using curl (replace with your actual API key)
curl -X POST https://api.ipfs.ninja/upload/new \
-H "X-Api-Key: bws_YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{
"content": "SGVsbG8sIElQRlMgV29ybGQh",
"description": "My first IPFS upload"
}'// Using JavaScript
const createFirstCID = async () => {
const response = await fetch('https://api.ipfs.ninja/upload/new', {
method: 'POST',
headers: {
'X-Api-Key': 'bws_YOUR_API_KEY_HERE',
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: btoa('Hello, IPFS World!'), // Base64: "SGVsbG8sIElQRlMgV29ybGQh"
description: 'My first IPFS upload'
})
});
const result = await response.json();
console.log('🎉 Your first CID:', result.cid);
console.log('🌐 Access it at:', result.uris.url);
return result;
};
createFirstCID();다음과 같은 결과가 반환됩니다:
{
"cid": "bafkreif2pall7dybz7vecqka3zo24irdwabf7rbiiweuhau7a2hjlqvfjw",
"sizeMB": 0.000017,
"uris": {
"ipfs": "ipfs://bafkreif2pall7dybz7vecqka3zo24irdwabf7rbiiweuhau7a2hjlqvfjw",
"url": "https://ipfs.ninja/ipfs/bafkreif2pall7dybz7vecqka3zo24irdwabf7rbiiweuhau7a2hjlqvfjw"
}
}더 자세한 API 예제는 IPFS 업로드 API 튜토리얼을 확인하세요.
결론
CID는 IPFS 콘텐츠 주소 지정 시스템의 기초로, 불변하고 검증 가능하며 분산된 콘텐츠 식별을 제공합니다. CIDv0 vs CIDv1의 기술적 세부 사항부터 실용적인 구현 패턴까지 작동 방식을 이해하는 것은 견고한 분산 애플리케이션을 구축하는 데 필수적입니다.
핵심 요약:
- CID는 위치가 아니라 콘텐츠를 고유하게 식별한다
- CIDv0는 최대 호환성을 제공하고, CIDv1는 유연성을 제공한다
- 콘텐츠 주소 지정은 검증과 중복 제거를 가능하게 한다
- 올바른 CID 처리는 운영 애플리케이션에 필수적이다
NFT 메타데이터 저장, 분산 웹사이트 배포, 콘텐츠 배포 시스템 구축 어느 것이든 CID는 진정으로 분산된 애플리케이션에 필요한 신뢰할 수 있는 기반을 제공합니다.
핀닝을 시작할 준비가 되었나요? 무료 계정 만들기 — 50 파일, 저장 1 GB, 월 2 GB 대역폭. 신용카드 불필요.