Dev Lab4 min read

블록체인 데이터베이스, 컨트랙트로 구현한 테이블형 저장소 설계

컨트랙트를 테이블처럼 쓰는 블록체인 데이터베이스 설계. Post·Auth·Relayer·Subscriber·Visitor·YouTube 저장소 구조와 주소/인증 전략까지 한 번에 정리.

#블록체인#데이터베이스#스마트컨트랙트#설계#메타트랜잭션#패스키#인증#릴레이어#아키텍처

컨트랙트를 테이블처럼 쓰는 블록체인 데이터베이스 설계.
Post·Auth·Relayer·Subscriber·Visitor·YouTube 저장소 구조와 주소/인증 전략까지 한 번에 정리합니다.

컨트랙트 관계


TL;DR

  • 컨트랙트 1개 = 테이블 1개로 보고 설계합니다.
  • 온체인은 “확정 가능한 원장(Write)”에 강하지만, “쿼리(Read)”는 약합니다.
  • 그래서 쓰기(온체인 확정) / 읽기(오프체인 인덱싱) 를 분리해야 서비스화가 가능합니다.
  • 테이블 간 조인은 체인에서 하지 않고, 이벤트(Log) → 인덱서/서버에서 결합합니다.
  • 민감 정보는 절대 원문 저장하지 않고 해시/암호화만 온체인 원칙으로 갑니다.

왜 블록체인을 DB처럼 쓰려 했나

중앙화 DB는 편리하지만 다음 한계가 있습니다.

  • 기록의 출처/변경 이력/검증 가능성은 결국 “운영자 신뢰”에 의존합니다.
  • “내가 만든 기록이 진짜인지”를 제3자가 검증하려면 별도의 증명 구조가 필요합니다.
  • 운영 비용(서버/DB/백업/권한/감사)을 계속 안고 가야 합니다.

반대로 블록체인은 불변성·투명성·검증 가능성을 제공하지만,

  • 스키마/쿼리 제약이 크고
  • 쓰기 비용(가스)과 프라이버시가 어렵습니다.

그래서 이 글은 “블록체인을 DB처럼”이라는 표현을 ‘테이블형 저장소(Write-Optimized Ledger)’로 쓰되, Read는 오프체인으로 서비스화한다라는 관점으로 정리합니다.


큰 그림: Write(온체인) / Read(오프체인) 분리

제가 실제로 의도한 데이터 흐름은 아래와 같습니다.

  1. 쓰기(온체인): 유저 서명 → 릴레이어 제출(가스 대납) → 컨트랙트에 기록
  2. 읽기(오프체인): 이벤트(Log) 인덱싱 → 서비스 DB/캐시 적재 → API로 결합 조회
  3. 정합성: 핵심 키(address, tokenId, hash)는 온체인에 남겨 “검증 가능성”을 유지

핵심은

  • 온체인은 “정답의 원천(Source of Truth)”
  • 오프체인은 “빠르고 편한 조회/결합/검색” 으로 역할을 나누는 것입니다.

컨트랙트 = 테이블: 저장소 맵핑

핵심 아이디어는 단순합니다.

컨트랙트 1개 = 데이터베이스 테이블 1개
각 테이블은 결국 address(혹은 tokenId/해시) 기반의 키로 귀결됩니다.

본 블로그 서비스에서 사용하는 주요 “테이블”은 다음과 같습니다.

컨트랙트(테이블)역할 요약주요 키/함수
PostStorageERC-721 기반 포스트 저장. 추후 확장 고려(메타트랜잭션)struct Post, getPosts, tokenId
AuthStorage생체인증(passkey) 기반 인증 데이터 저장소addPasskey, DEFAULT_PASSKEY_SLOTS
RelayerManager가스 대납 릴레이어 풀 관리/검증onlyRelayer, assertRelayer
SubscriberStorage구독 관계(인증/이메일) 저장claimPinCode, addSubscriberEmail, isPinCodeActive
VisitorStorage방문자 트래킹 데이터 저장currentDayId, addHashedVisitor, totalVisitorsOf
YoutubeStorageYouTube 영상 ID 보관(게시판 연동)struct YouTubeVideo, saveVideoFor, updateVideoFor

주의: 테이블 간 조인은 체인 레벨에서 직접 수행하지 않습니다.
조회는 인덱서/서버에서 결합하고, 정합성은 온체인 키(address, tokenId, hash)로 보장합니다.


“테이블 설계”를 위한 규칙 6가지

온체인 테이블을 설계할 때 제가 계속 지키려 한 규칙입니다.

  1. 키를 먼저 정한다
  • 무엇으로 unique를 보장할지: address, tokenId, bytes32 hash, (dayId, hash)
  1. 쓰기 단위는 작게
  • 한 트랜잭션에서 너무 많은 스토리지 변경을 하지 않기(가스 급증/실패 리스크)
  1. 쿼리는 체인에서 하지 않는다
  • 정렬/필터/검색은 체인에 맡기지 않고 이벤트 인덱싱으로 해결
  1. 민감 정보는 원문 저장 금지
  • 이메일/IP 같은 건 해시/암호화만 저장(원문은 서버에서 처리)
  1. 상태를 최소화한다
  • “무엇이 진짜로 온체인에 남아야 하는가?”만 남긴다(증명/정합성/권한)
  1. 업그레이드/이전 전략을 먼저 설계한다
  • Proxy로 갈지, 신규 배포 + 마이그레이션으로 갈지 사전에 결정

주소와 인증: 계정 불러오기 전략

모든 데이터는 결국 address로 귀속됩니다. 문제는 일반 사용자가 Hex 주소를 직접 관리하기 어렵다는 점입니다.

제가 선택한 방향은 다음과 같습니다.

  • “사용자만 아는 코드 + 생체인증(passkey)”로 파생 규칙을 만들고
  • 그 결과로 계정 address를 자동 매핑해 불러옵니다.

즉, 별도의 시드 문구나 복잡한 지갑 UX 없이
“나만의 코드 + 생체인증”으로 서비스를 재현 가능하게 하는 방향입니다.

  • passkey 원본은 다중 암호화 후 해시/파생키 형태로 저장
  • 실제 비밀키를 온체인에 그대로 보관하지 않는 것을 원칙으로 합니다.

메타트랜잭션과 릴레이어: 쓰기 비용의 현실 해법

블로그 같은 서비스에서 “쓰기”가 늘면 결국 두 가지 문제가 생깁니다.

  • 사용자 가스비 부담
  • 트랜잭션 동시성으로 인한 nonce 경합(특히 대납 계정에서)

그래서 저는 다음 구조로 정리했습니다.

  • 유저는 서명만 한다(EIP-712 등)
  • 릴레이어가 트랜잭션을 제출하고 가스비를 대납한다
  • 컨트랙트는 RelayerManager를 통해 msg.sender가 릴레이어인지 검증한다

운영 팁(제품 관점):

  • 릴레이어 풀은 최소 3개 이상으로 분산해 스루풋을 올립니다.
  • replay 보호(체인ID·만료시간·도메인 분리)를 넣습니다.
  • 대납 정책은 요금제/쿼터 개념으로 설계하고 남용 방지(서명 재사용 제한)를 둡니다.

nonce 충돌과 다중 relayer 선택은 아래 글에서 더 자세히 다룹니다.


데이터 모델과 쓰기/읽기 흐름(서비스화 관점)

  1. 주소/계정 파생
    “개인 코드 + 생체인증” → 파생 데이터 → 계정 address

  2. 쓰기(온체인 확정)
    유저 서명 → 릴레이어 제출 → RelayerManager 검증 → 각 저장소 컨트랙트에 기록

  3. 읽기(오프체인 서비스화)
    이벤트(Log) 인덱싱 → 서비스 DB/캐시 적재 → API에서 결합 조회
    (포스트 목록, 방문자 통계, 구독자 목록, 유튜브 연동 등)

  4. 무결성/검증 UX
    UI에는 최소 1회 이상 온체인 링크(tx hash, tokenId 등)를 노출해
    “검증 가능성”을 시각화합니다.


한계와 운영 상 고려사항

이 구조에는 명확한 한계가 있습니다. 중요한 것은 “한계를 알고 쓰는 것”입니다.

1) 비용(가스)

  • 테스트넷에서는 체감이 적지만, 메인넷/트래픽 증가 시 쓰기 비용은 커질 수 있습니다.
  • 따라서 온체인에는 “증명/정합성에 꼭 필요한 것”만 남기는 설계가 중요합니다.

2) 프라이버시

  • 공개 원장을 쓰는 순간, 민감 데이터는 그대로 노출됩니다.
  • 원칙: 원문 저장 금지 + 해시/암호화만 온체인 + 보관 목적 최소화

3) 스키마 진화(업그레이드)

  • 컨트랙트는 테이블 스키마와 같아서, 변경이 곧 마이그레이션 문제로 이어집니다.
  • Proxy로 갈지, 신규 배포 + 이전 스크립트로 갈지, 초기에 결정해야 운영이 편합니다.

4) 인덱싱 지연/정합성

  • 오프체인 인덱서는 지연될 수 있습니다.
  • UI에서는 낙관적 업데이트 + 재동기화를 같이 가져가는 편이 안정적입니다.

결론

“컨트랙트를 테이블로 본다”는 관점은
불변성·검증·확장성 사이의 균형을 맞추는 실용적인 절충입니다.

  • 온체인은 “확정 가능한 최소 상태”
  • 오프체인은 “조회/검색/결합”

이 분리를 명확히 하면, 블록체인을 DB처럼 쓰는 설계도 충분히 서비스화가 가능합니다.

참고 링크

다음으로 읽어볼 글