Skip to content
/ moas Public

아티스트와 클라이언트 간의 계약 불투명성 문제를 해결하기 위해, 계약서를 블록체인(Smart Contract)에 기록하고 결제 완료 시 경력 증명 NFT를 자동 발행하는 플랫폼

Notifications You must be signed in to change notification settings

Yevin-WIN/moas

Repository files navigation

MOAS

블록체인 기반 아티스트-클라이언트 계약 투명화 플랫폼

Java Spring Boot Solidity Ethereum License


📌 프로젝트 개요

MOAS는 음악/예술 산업의 계약 불투명성 문제를 블록체인으로 해결하는 Web2.5 하이브리드 플랫폼입니다.

🎯 핵심 가치

  • 🔒 계약 위변조 방지: EIP-712 전자서명과 SHA-3 해싱으로 계약 무결성 보장
  • 🏆 경력 증명 NFT: 계약 완료 시 ERC-1155 기반 포트폴리오 NFT 자동 발행
  • 💰 투명한 정산: 스마트 컨트랙트 기반 자동 정산 및 수수료 처리
  • 🤖 AI 매칭: LLM + Vector DB를 활용한 프로젝트-아티스트 매칭

🧑‍💻 담당 직무 (Backend & Web3 Architecture)

"Web2의 편의성과 Web3의 신뢰성을 결합한 하이브리드 아키텍처 설계 및 구현"

  • Architecture Design: RDB(MySQL)와 Blockchain(Ethereum) 간의 상태를 동기화하는 이벤트 기반 시스템 설계
  • Core Business Logic:
    • Electronic Signature: EIP-712 표준을 준수한 서명 검증 및 계약 위변조 방지 로직 구현
    • Payment Integrity: PG사 결제 정보와 내부 주문 정보 간의 교차 검증 시스템 구축
    • Transaction Safety: 분산 환경에서의 데이터 정합성 보장을 위한 재시도(Retry) 및 격리(Isolation) 전략 수립

🏗️ 시스템 아키텍처

전체 구조

┌─────────────────────────────────────────────────────────────┐
│                       Frontend (React)                       │
│              Web3Auth (Google/Kakao/Apple)                   │
└───────────────────────┬─────────────────────────────────────┘
                        │ REST API + JWT
┌───────────────────────┴─────────────────────────────────────┐
│                   Spring Boot Backend                        │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │ Contract     │  │ Payment      │  │ Blockchain   │      │
│  │ Service      │  │ Service      │  │ Client       │      │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘      │
│         │                  │                  │              │
│  ┌──────▼──────────────────▼──────────────────▼──────┐      │
│  │        MySQL (Contract, Payment, Member)          │      │
│  └───────────────────────────────────────────────────┘      │
└───────────────────────┬─────────────────────────────────────┘
                        │ Web3j + WebSocket
┌───────────────────────▼─────────────────────────────────────┐
│           Ethereum Sepolia Testnet (Blockchain)              │
│  ┌────────────────────────────────────────────────────┐     │
│  │          MOASContract.sol (ERC-1155)               │     │
│  │  - createContract()                                │     │
│  │  - updateContractStatus()                          │     │
│  │  - cancelContract()                                │     │
│  │  - EIP-712 Dual Signature Verification            │     │
│  └────────────────────────────────────────────────────┘     │
└─────────────────────────────────────────────────────────────┘

하이브리드 데이터 동기화

[Web2 - MySQL]                    [Web3 - Blockchain]
    │                                     │
    │  1. Contract Creation               │
    ├────────────────────────────────────►│ 2. Mint NFT (txHash)
    │                                     │
    │  3. OnchainRecord (PENDING)         │
    ◄────────────────────────────────────┤ 4. Event Emitted
    │                                     │
    │  5. OnchainRecord (SUCCEEDED)       │
    │     ContractNft Record Created      │
    └─────────────────────────────────────┘

🛠️ 기술 스택

Backend

  • Language: Java 21 (Record, Pattern Matching, Switch Expression)
  • Framework: Spring Boot 3.2.x
  • Data Access: Spring Data JPA, QueryDSL, JPQL Projection
  • Security: Spring Security, JWT (Access/Refresh Token Rotation), Web3Auth OIDC
  • Validation: Hibernate Validator

Blockchain

  • Smart Contract: Solidity 0.8.28, OpenZeppelin Contracts
  • Blockchain Interaction: Web3j 4.x (HTTP + WebSocket)
  • Standards: ERC-1155 (Non-Transferable NFT), EIP-712 (Typed Structured Data), ERC-2771 (Meta-Transactions)
  • Network: Ethereum Sepolia Testnet

Infrastructure

  • Database: MySQL 8.0
  • Cache/Session: Redis (Lettuce Client)
  • Storage: AWS S3 (File Upload), Thumbnailator (Image Processing)
  • Payment: Toss Payments API
  • Vector DB: QDrant (Semantic Search)
  • LLM: GMS GPT-4.1 API (SSAFY)

DevOps & Tools

  • Build: Gradle 8.x
  • Testing: JUnit 5, Mockito, H2 (In-Memory DB)
  • API Documentation: Swagger/OpenAPI 3.0
  • Logging: SLF4j + Logback

🚀 핵심 기능

1. 전자 계약 시스템

  • EIP-712 Dual Signature: 리더와 아티스트 양측의 전자서명으로 계약 체결
  • SHA-3 해싱: 계약 내용을 해싱하여 위변조 방지
  • Smart Contract 검증: 온체인에서 서명 검증 후 NFT 발행
// 서명 검증 예시 (SignatureVerifier.java)
public boolean verify(String signerAddress, TypedDataResponse typedData, String signature) {
    StructuredDataEncoder encoder = new StructuredDataEncoder(typedDataJson);
    byte[] messageHash = encoder.hashStructuredData();
    BigInteger recoveredPublicKey = Sign.signedMessageHashToKey(messageHash, signatureData);
    String recoveredAddress = "0x" + Keys.getAddress(recoveredPublicKey);
    return signerAddress.equalsIgnoreCase(recoveredAddress);
}

2. 이벤트 기반 블록체인 동기화

  • 비동기 트랜잭션: Spring Event + @Async로 블록체인 트랜잭션 전송
  • 감사 로그 분리: @Transactional(REQUIRES_NEW)로 트랜잭션 전파 제어
  • 재시도 메커니즘: @Retryable (5회, 2초 백오프)로 네트워크 장애 대응
// 블록체인 동기화 플로우 (ContractCommandListener.java)
@Async
@TransactionalEventListener
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void handleContractPaidEvent(ContractPaidEvent event) {
    OnchainRecord record = onchainRecordService.create(contractId, MINT);
    String txHash = blockchainClient.createContract(contract);
    record.updateTxHash(txHash);
}

// 이벤트 수신 및 재시도 (OnchainEventProcessService.java)
@Retryable(maxAttempts = 5, backoff = @Backoff(delay = 2000))
public void processContractCreatedEvent(ContractCreatedEvent event) {
    onchainRecord.markSucceeded();
    contractNftService.createNft(contractId, tokenId, txHash);
}

3. 결제 시스템 및 멱등성 보장

  • Toss Payments 연동: 결제 승인, 부분 취소, 구매 확정
  • 금액 위변조 검증: 클라이언트 금액과 서버 금액 교차 검증
  • 중복 승인 방지: 주문 상태 체크로 멱등성 보장
// 금액 검증 및 중복 방지 (PaymentService.java)
public PaymentApproveResultDto approvePayment(String paymentKey, String orderId, Long amount) {
    Order order = orderRepository.findById(orderId).orElseThrow();

    // 중복 승인 방지
    if (order.getStatus() == OrderStatus.PAID) {
        return PaymentApproveResultDto.from(order);
    }

    // 금액 위변조 검증
    if (!order.getAmount().equals(amount)) {
        throw PaymentException.amountMismatch();
    }

    // Toss Payments API 호출 및 처리
    // ...
}

4. AI 기반 프로젝트 매칭

  • Vector Embedding: Ollama API로 프로젝트 설명 임베딩
  • Semantic Search: QDrant에서 유사도 기반 프로젝트 추천
  • LLM 추천: GMS GPT-4.1로 맞춤형 프로젝트 분석

🚦 시작하기

필수 요구사항

  • Java: 21 이상
  • Gradle: 8.x
  • MySQL: 8.0
  • Redis: 6.x
  • Node.js: 18.x (Solidity 컴파일용)

환경 변수 설정

.env 파일을 생성하고 다음 변수를 설정하세요:

# Database
DB_URL=jdbc:mysql://localhost:3306/moas_db
DB_USERNAME=your_db_user
DB_PASSWORD=your_db_password

# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=

# JWT
JWT_SECRET=your-secret-key-min-256-bits

# AWS S3
AWS_S3_ACCESS_KEY=your_access_key
AWS_S3_SECRET_KEY=your_secret_key
AWS_S3_BUCKET_NAME=your_bucket_name

# Blockchain
BLOCKCHAIN_RPC_URL=https://sepolia.infura.io/v3/YOUR_PROJECT_ID
BLOCKCHAIN_WS_URL=wss://sepolia.infura.io/ws/v3/YOUR_PROJECT_ID
SERVER_WALLET_PRIVATE_KEY=0xYourPrivateKey
MOAS_CONTRACT_ADDRESS=0xYourDeployedContractAddress
BLOCKCHAIN_CHAIN_ID=11155111

# Web3Auth
WEB3AUTH_AUDIENCE=your_web3auth_client_id

# QDrant
QDRANT_HOST=localhost
QDRANT_PORT=6334
QDRANT_API_KEY=your_qdrant_api_key

# LLM (GMS)
GMS_KEY=your_gms_api_key

# Toss Payments
TOSS_PAYMENTS_SECRET_KEY=your_toss_secret_key
TOSS_PAYMENTS_API_URL=https://api.tosspayments.com/v1/payments

# Encryption
ACCOUNT_ENCRYPTION_KEY=your_32byte_base64_key

빌드 및 실행

1. 프로젝트 클론

git clone https://github.com/yourusername/moas.git
cd moas/backend/moas

2. Solidity 컨트랙트 컴파일 및 래퍼 생성

# OpenZeppelin 의존성 설치
npm install

# Solidity → Java Wrapper 생성
./gradlew generateContractWrappers

3. 빌드

# 전체 빌드 (테스트 포함)
./gradlew build

# 빌드만 (테스트 제외)
./gradlew build -x test

4. 실행

# 개발 환경
./gradlew bootRun --args='--spring.profiles.active=dev'

# 프로덕션 환경
java -jar build/libs/moas-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

테스트 실행

# 전체 테스트
./gradlew test

# 특정 테스트 클래스
./gradlew test --tests "com.s401.moas.contract.service.ContractServiceTest"

# 커버리지 리포트
./gradlew jacocoTestReport

🧪 트러블슈팅 사례

1. 블록체인-DB 동기화 실패 복구

문제: 네트워크 장애로 블록체인 트랜잭션 전송 실패 시 DB 상태 불일치

해결:

// OnchainRecord 테이블로 실패 추적
@Retryable(maxAttempts = 5)
public void retryFailedTransactions() {
    List<OnchainRecord> failed = onchainRecordRepository.findByStatus(FAILED);
    failed.forEach(record -> {
        try {
            blockchainClient.retryTransaction(record);
            record.markSucceeded();
        } catch (Exception e) {
            log.error("재시도 실패: recordId={}", record.getId(), e);
        }
    });
}

2. PG사 Webhook 중복 처리 방지

문제: Toss Payments에서 동일한 Webhook을 여러 번 전송하는 경우 중복 처리

해결:

// Order 상태로 멱등성 보장
if (order.getStatus() == OrderStatus.PAID) {
    log.info("이미 처리된 주문: orderId={}", orderId);
    return PaymentApproveResultDto.from(order);
}

3. EIP-712 서명 검증 실패

문제: 프론트엔드와 백엔드의 TypedData 구조 불일치로 서명 검증 실패

해결: TypedData 스펙을 REST API로 제공하여 프론트엔드와 동기화

@GetMapping("/contracts/{contractId}/typed-data")
public TypedDataResponse getTypedData(@PathVariable Long contractId) {
    return contractService.generateTypedData(contractId);
}

About

아티스트와 클라이언트 간의 계약 불투명성 문제를 해결하기 위해, 계약서를 블록체인(Smart Contract)에 기록하고 결제 완료 시 경력 증명 NFT를 자동 발행하는 플랫폼

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published