티캣

Backend

블록체인 티켓과 포토카드 거래를 제공하는 공연 예매 플랫폼

2026.08 ~ 2026.10Blockchain Developer · Backend 성능 개선 · Monitoring6인 팀

공연 예매와 티켓 소유 증명, 포토카드 발행·거래를 제공하는 플랫폼입니다. 블록체인 컨트랙트·내부 API 전반, 모니터링, 티켓팅 성능 개선·가상 대기실과 NFT 거래의 이상거래 규칙·섀도 모델을 담당했습니다.

티캣 서비스 화면

프로젝트 개요

목표
티켓과 포토카드의 온체인 소유·발행 규칙을 구현하고, 예매 집중 시점의 부하와 NFT 거래의 이상 징후를 처리하는 구조를 만들었습니다. 서비스 상태와 비동기 발행 흐름을 확인할 수 있도록 모니터링도 직접 구축했습니다.
배경
티켓 소유·양도 규칙과 포토카드 발행 이력을 검증할 수 있어야 했습니다. 예매 화면의 반복 조회는 DB·서버·프록시에 부하를 만들었고, 비동기 발행은 HTTP 응답 이후의 실패까지 확인해야 했습니다. 개발·운영 스택이 같은 EC2 자원을 사용해 모니터링 자체의 자원 소비도 제한해야 했으며, 경매·거래 기능에는 계정 관계와 거래 패턴을 확인할 심사 절차가 필요했습니다.
주요 기능
  • ERC-721 기반 양도 제한 티켓 SBT, ERC-20 포인트 토큰, ERC-1155 포토카드 NFT와 추첨 컨트랙트 구현
  • HD 지갑 파생, 내부 API, 트랜잭션 직렬화·멱등 처리와 발행 확정 감시 구현
  • 개발·운영 환경의 지표·중앙 로그·오류 추적·장애 알림을 직접 구축하고 부하 테스트의 병목 분석에 활용
  • 좌석맵 1초 캐시와 nginx upstream keepalive 적용으로 DB 조회·연결 생성 병목 개선
  • 서버 직접 호출 부하 측정 기록에서 3,600 VU 구간의 서버 p95 20ms·실패율 0% 확인
  • 회차별 기본 정원 5,000명과 틱당 입장 상한을 갖춘 Redis·Lua 기반 가상 대기실 구현
  • 8개 이상거래 규칙, FLAG·HOLD 모드와 관리자 판정·통계 기능 구현
  • 합성 거래 547건 검증에서 규칙 재현율 37.2% 대비 모델 93.1%·정상 오탐 12건 확인, 모델은 섀도 모드로 기록

역할·팀 구성

팀 내 역할 분담 · 6인 팀

Frontend
공연 탐색·예매·좌석 선택·가상 대기실, 포토카드 거래·경매 및 관리자 화면 구현과 API 연동
Backend
인증·회원, 공연·좌석·예매·결제, 포토카드 거래·경매 API와 데이터 처리, 대기열 및 이상거래 심사 구현
Blockchain
티켓 SBT·포인트 토큰·포토카드 NFT·추첨 컨트랙트, 지갑·트랜잭션 처리와 블록체인 내부 API 구현
Infra
Docker 기반 실행·배포 환경, CI/CD와 nginx 구성, 지표·중앙 로그·오류 추적·장애 알림 구축 및 부하 테스트·성능 개선

담당 역할

Blockchain Developer · Backend 성능 개선 · Monitoring

blockchain 디렉터리의 스마트 컨트랙트·내부 API 구현 전반과 프로젝트 모니터링 구축을 맡았습니다. 티켓팅 부하 테스트와 성능 개선, 가상 대기실, NFT 거래 이상거래 규칙·섀도 모델도 구현했습니다.

스마트 컨트랙트 구현
  • 양도 제한 티켓 SBT

    ERC-721 기반 TicketSBT에 티켓 발행·소각·소유 조회를 구현하고, 계정 간 이전과 승인 함수를 제한. 티켓 키로 tokenId를 결정하고 소각 후에도 발행 이력을 유지해 같은 키의 재발행 방지

  • 캣머니 포인트 토큰

    ERC-20 기반 CatMoney에 발행·소각·멱등 전송을 구현. 작업 종류와 호출자별로 실행 키를 분리하고 관리자·발행자·운영자 권한 및 일시 정지 범위 구성

  • 포토카드 NFT

    ERC-1155 기반 PhotocardNFT에 도안별 발행 한도와 메타데이터 URI, 최대 200건 배치 발행, 중복 키 건너뛰기와 멱등 전송 구현. 최초 발행 이후 도안의 수량·메타데이터 변경 제한

검증 가능한 추첨 구현
  • Commit–Reveal 추첨

    시드 해시와 참여자·도안 수량의 입력 해시를 먼저 온체인에 기록하고, 시드 공개 시 커밋 다음 블록의 해시를 결합해 난수 확정. 배정 요청의 입력 해시를 다시 검증하고 같은 난수·입력으로 배정 결과 재현

  • 자동 리빌과 재시작 복구

    미공개 추첨을 주기적으로 확인해 리빌하고, 최근 256블록의 DrawOpened 이벤트를 조회해 재시작으로 놓친 추첨 복구. 리빌 기한이 지난 추첨의 취소와 추첨 ID 재사용 제한 구현

블록체인 내부 API와 트랜잭션 처리
  • HD 지갑과 내부 API

    마스터 니모닉과 인덱스로 사용자 지갑을 파생하고 서명 시 개인키를 계산하는 구조 구현. Express·TypeScript로 지갑, 캣머니, 티켓, 포토카드, 추첨, 트랜잭션 조회 API를 제공하고 내부 키 인증·Zod 검증·OpenAPI 문서 연결

  • 논스 충돌과 중복 실행 처리

    단일 프로세스의 전송 큐로 트랜잭션을 직렬화하고 주소별 다음 논스를 직접 관리. 실패 시 논스를 다시 조회하도록 초기화하고, 컨트랙트의 실행 키와 기발행 조회로 재시도에 따른 중복 발행·차감·전송 방지

  • 비동기 확정 감시와 발행 증거 검증

    전송 접수와 블록 확정을 분리하고 영수증 감시·DB 미확정 행 재조회로 발행 상태 동기화. 포토카드 배치의 개별 이벤트와 과거 발행 이력을 대조해 수령인·도안이 다른 키 재사용이나 발행 이벤트 누락을 실패로 분류

  • 체인 환경 대응과 관측 지표

    SSAFY 체인의 Constantinople EVM에 맞춰 컴파일·테스트 환경을 구성하고 가스 가격 0 설정 적용. 전송 큐 대기, 전송 결과, 논스 초기화와 확정 지연 등을 Prometheus 지표로 노출

모니터링 전반 구축
  • EC2 자원을 고려한 스택 구성

    개발·운영 스택이 함께 실행되는 EC2의 자원 제약을 고려해 Prometheus·Grafana·Loki·Alloy 구성 선택. 앱과 별도 Docker Compose로 배포하고 컨테이너별 메모리 한도와 지표·로그 보관 정책 설정

  • 애플리케이션·호스트·DB 지표 수집

    Spring Actuator·Micrometer와 Node.js prom-client로 API·런타임·업무 지표를 노출하고, node-exporter·cAdvisor·postgres-exporter로 호스트·컨테이너·DB 상태 수집. 개발·운영 환경을 라벨로 구분해 Prometheus에서 15초 주기로 수집

  • 블록체인 업무 지표와 Grafana 대시보드

    티켓·포토카드 발행 적체, 체인 연결·블록 진행, 논스 큐 깊이·대기·초기화, 트랜잭션 드롭·확정 지연을 계측. API p95·DB 커넥션 대기·락·JVM·Node 상태와 함께 보는 대시보드 및 데이터소스를 코드로 구성

  • 중앙 로그 수집

    Alloy가 Docker 컨테이너 로그를 읽어 Loki로 전달하도록 구성. 로그 수집을 앱 실행 경로와 분리하고 서비스·컨테이너 중심 라벨, 모니터링 스택 로그 제외, 마스킹과 14일 보관 정책 적용

  • 장애 알림

    발행 적체·체인 RPC 두절·트랜잭션 드롭·DB 커넥션 대기·컨테이너 메모리 한도 접근 등의 Prometheus 알림 규칙 작성. Alertmanager에서 환경·심각도별 그룹화와 중복 알림 억제, Mattermost 호환 웹훅 연동 구성

  • Sentry 오류 추적

    프론트엔드와 Spring 서버에 Sentry 오류 수집을 연결하고 환경·릴리스별로 구분. 서버는 Logback 연동으로 예외 스택을 수집하고, 프론트엔드는 오류 필터링과 민감정보 정리 적용

티켓팅 부하 측정과 병목 개선
  • 좌석 페이지 체류 부하 테스트

    좌석 화면의 3초 폴링을 재현하는 k6 시나리오를 구성하고 가상 사용자 수를 단계적으로 증가. 클라이언트·서버 p95, 처리량, Hikari 대기, 요청 처리 스레드, CPU와 타임아웃을 비교해 병목 추적

  • 좌석맵 응답 캐시

    회차·구역별 좌석맵에 Caffeine 1초 TTL 캐시를 적용하고 동일 키의 동시 로딩을 합쳐 반복 DB 조회와 커넥션 점유 감소. 캐시된 좌석 스냅샷과 응답 시점의 serverTime 분리

  • nginx 연결 재사용

    캐시 적용 후 nginx의 TIME_WAIT 누적과 임시 포트 고갈에 따른 502를 확인하고 upstream keepalive 적용. 외부 측정기의 네트워크 병목을 구분하기 위해 EC2 내부에서 서버를 직접 호출하는 테스트도 수행

가상 대기실 구현
  • Redis 대기열과 원자적 입장 처리

    Redis Sorted Set으로 회차별 대기 순서와 입장 만료 시각을 관리. Lua로 만료자 정리·정원 확인·대기자 이동을 한 번에 처리하고, 입장 처리자 중복 실행을 Redis 락으로 제어

  • 정원과 입장 속도 제어

    회차별 기본 정원 5,000명, 1초 주기의 틱당 최대 200명 입장, 10분 무활동 만료를 설정으로 분리. 관리자 API에서 회차별 활성화와 정원·입장 속도·만료 시간 조정 지원

  • 대기 화면과 서버 접근 제어

    대기 순번·예상 대기 시간과 입장 상태를 보여주는 화면 및 라우팅 가드 구현. 서버 인터셉터에서 좌석 조회·선점 요청의 입장 여부를 확인하고, 예매 완료·이탈 시 자리를 반환하도록 연결

경매·NFT 거래 이상거래 심사 구현
  • 8개 규칙 기반 탐지

    동일 단말, 동일 연락처, 반복 거래쌍·양자 간 순환, 가격 이상, 신규 계정 급행 거래, 거래량 집중, 매집, 계정 탈취 의심 규칙 구현. 거래 맥락을 한 번 수집해 규칙별 근거와 위험도를 계산

  • FLAG·HOLD 모드

    기본 FLAG 모드에서는 이상 징후와 관리자 판정을 기록하면서 정산을 진행. HOLD 모드에서는 판정 기준에 해당하는 거래를 온체인 전송 전에 RISK_REVIEW 상태로 보류하고 관리자 승인·거절에 따라 후속 처리

  • 관리자 심사 기능

    심사 목록·상세·통계·승인·거절 API와 관리자 화면 구현. 규칙 근거, 판매자·구매자 정보, 입찰 타임라인과 최근 거래 내역을 함께 보여주고 판정 기록 저장

  • 머신러닝 섀도 모델 학습·채점

    정상·이상거래 시뮬레이션 3개 배치에서 학습 시점 기준 1,640건을 생성하고 마지막 547건을 분리 검증. 규칙 판정값을 입력에서 제외한 32개 피처로 로지스틱 회귀를 학습해 Java 서버가 위험 점수만 저장하도록 연결

사용 기술 & 이유 & 구현

커스터디 HD 지갑
선택 이유
3주간 실제로 운영하며 지표를 모으는 것이 목표였기 때문에, 짧은 기간에 많은 사용자가 쉽게 참여할 수 있도록 편의성을 우선했습니다. 외부 지갑 설치·연결과 시드 구문 관리 부담을 줄이기 위해 커스터디 방식을 선택했습니다.
구현 내용
니모닉과 인덱스로 사용자 지갑을 파생하고 서버에서 서명을 처리해, 별도 지갑 연결 없이 티켓과 포토카드를 이용하도록 구성했습니다.
Node.js · Express
선택 이유
Hardhat·ethers.js 등 블록체인 생태계를 활용하기 위해 Node.js를 선택했습니다. 블록체인 API를 혼자 담당해 빠르게 구현해야 했으므로 필요한 기능을 직접 조합할 수 있는 Express를 사용했습니다.
구현 내용
컨트랙트와 API의 타입을 공유하고 지갑·서명·트랜잭션 처리와 내부 API를 연결했습니다.
Caffeine · Redis · Lua
선택 이유
같은 좌석맵의 반복 조회는 Caffeine 로컬 캐시로 DB 비용을 줄이고, 처리 한계를 넘는 사용자는 Redis 대기열에서 관리하도록 나눴습니다. 정원 확인과 입장 사이의 경합을 막기 위해 Lua로 원자적으로 처리했습니다.
구현 내용
좌석맵에 1초 TTL 캐시를 적용하고, Redis Sorted Set과 Lua로 대기 순서·입장 만료·정원·입장 속도를 제어했습니다.
모니터링 도구
선택 이유
3주간의 운영에서 사용량·성능·오류 지표를 최대한 폭넓게 수집하는 것이 목적이었습니다. 초기 운영에서 다양한 오류가 발생할 것으로 예상해 지표·로그·예외·알림을 각각 관측하도록 도구를 구성했고, EC2 자원을 고려해 ELK 대신 Prometheus·Loki·Grafana 조합을 선택했습니다.
구현 내용
Prometheus·Grafana로 지표를, Loki·Alloy로 로그를 수집하고 Sentry로 예외를 추적하며 Alertmanager로 알림을 구성했습니다. k6 부하 결과를 서버 지표와 대조하고 수집 도구별 자원·보관 한도를 설정했습니다.
scikit-learn · 로지스틱 회귀
선택 이유
확정된 실거래 이상거래 라벨이 부족해 합성 시나리오에서 규칙의 사각지대를 먼저 검증하고, 피처별 영향과 오탐 원인을 추적할 수 있는 모델을 선택했습니다.
구현 내용
규칙 판정값을 제외한 거래 피처로 배치 단위 분리 검증을 수행하고, 학습된 계수와 전처리 기준을 JSON으로 내보냈습니다. Java 서버는 점수만 기록하며 심사·정산 결정에는 사용하지 않습니다.

문제 해결 사례

사례 1실사용자 유입을 위해 블록체인 진입 장벽을 낮춘 커스터디 지갑 도입

1. 오류 분석

문제 현상
실제 사용자를 유입해야 하는 3주간의 운영에서, NFT 기능을 위해 사용자가 MetaMask 같은 외부 지갑을 미리 준비하고 연결해야 한다면 가입 장벽이 높아질 수 있었습니다.
원인
외부 지갑을 전제로 한 방식은 사용자가 지갑 설치, 니모닉 관리, 트랜잭션 서명에 익숙해야 합니다. 일반적인 회원가입 경험을 기대하는 사용자에게 이 절차는 추가 부담이었습니다.
추가 확인 사항
  • 회원가입과 NFT 이용 과정에서 사용자에게 외부 지갑 연결을 요구하지 않는 흐름을 확인했습니다.
  • 회원마다 고유한 파생 인덱스를 사용해 같은 인덱스에서 같은 지갑 주소가 생성되는지 확인했습니다.
  • 회원 DB에는 지갑 주소와 파생 인덱스만 기록하고, 마스터 니모닉과 개인키는 저장하지 않는 구조를 확인했습니다.

2. 개선 과정

  1. 1.3주 운영과 실사용자 유입이라는 목표에 맞춰 외부 지갑 준비 과정을 가입 흐름에서 제거
  2. 2.블록체인 서비스가 보관하는 하나의 마스터 니모닉과 회원별 고유 인덱스로 HD 지갑 주소 파생
  3. 3.회원가입이 완료되면 지갑 발급 요청을 남기고 백그라운드에서 지갑 생성
  4. 4.발급을 재시도해도 같은 인덱스를 사용하도록 해 지갑 주소가 바뀌거나 중복 발급되지 않게 처리
  5. 5.사용자가 개인키를 직접 다루지 않아도 서비스에서 필요한 블록체인 작업을 진행하도록 구성

커스터디 방식의 HD 지갑을 도입했습니다. 사용자는 일반 계정으로 가입하고, 서비스는 마스터 니모닉과 회원별 고유 파생 인덱스로 각자의 지갑을 생성합니다. 마스터 니모닉은 블록체인 서비스에서 관리하며 회원 DB에는 지갑 주소와 파생 인덱스만 저장합니다.

3. Before & After 비교

티캣 · 실사용자 유입을 위해 블록체인 진입 장벽을 낮춘 커스터디 지갑 도입 비교
항목BeforeAfter
가입 경험NFT 이용을 위해 사용자가 외부 지갑을 준비하고 연결해야 하는 방식외부 지갑 없이 일반 회원가입 후 지갑이 자동으로 발급되는 방식
지갑 관리사용자가 자신의 니모닉과 개인키를 직접 관리해야 함서비스가 마스터 니모닉을 관리하고 회원별 고유 인덱스로 지갑을 파생

약 100명은 운영 기간의 사용자 유입 규모이며, 커스터디 도입이 가입 전환율에 미친 영향을 비교 측정한 값은 아닙니다.

해결 결과

사용자가 MetaMask 설치나 지갑 연결 없이 서비스를 시작할 수 있도록 했습니다. 3주간의 운영 기간에는 약 100명의 사용자가 유입됐습니다.

사례 25천명 동시접속을 처리하도록 좌석 조회 캐시와 nginx 연결 재사용 적용

1. 오류 분석

문제 현상
2,400 VU 부하에서 DB 커넥션과 요청 처리 스레드가 포화되면서 좌석 조회 p95가 약 7.08초까지 늘고, 요청의 약 4.0%가 타임아웃으로 실패했습니다.
원인
같은 좌석맵을 요청마다 DB에서 다시 조립했고, 서버가 처리할 수 있는 양보다 많은 조회 요청이 몰렸습니다.
추가 확인 사항
  • Grafana에서 DB 커넥션 대기와 요청 처리 스레드 포화를 확인했습니다.
  • 캐시 적용 후에도 남은 지연을 추적해 nginx의 연결 생성·임시 포트 고갈을 확인했습니다.

2. 개선 과정

  1. 1.2,400 VU 실패 재현·병목 확인
  2. 2.좌석맵 1초 캐시 적용
  3. 3.nginx 연결 재사용
  4. 4.재측정 후 가상 대기실로 입장 제어

좌석맵을 1초간 캐싱해 반복 DB 조회와 커넥션 점유를 줄이고, nginx keepalive로 연결을 재사용했습니다. 가상 대기실을 추가해 정원을 넘는 사용자는 대기시키고 순차 입장하도록 했습니다.

3. Before & After 비교

티캣 · 5천명 동시접속을 처리하도록 좌석 조회 캐시와 nginx 연결 재사용 적용 비교
항목BeforeAfter
좌석 조회요청마다 DB 조회·커넥션 점유1초 캐시로 같은 조회 요청의 DB 작업 공유
초과 유입서버 내부에 요청이 쌓여 타임아웃 발생가상 대기실에서 대기 후 정원·입장 속도에 맞춰 진입

해결 결과

캐시 적용 후 1,200 VU의 서버 p95가 약 1.34초에서 13ms로 줄었습니다. 최종 서버 직접 호출 테스트에서는 5,000 VU 구간의 요청 실패율 0%를 확인했고, 가상 대기실로 한계를 넘는 유입을 대기·순차 입장으로 처리하도록 개선했습니다.

사례 3운영 과정에서 Pinata 파일 수 한도 초과로 사라진 NFT 이미지 복구 및 재발 방지

1. 오류 분석

문제 현상
Pinata 무료 플랜의 파일 수 한도 500개를 넘어 핀이 507개가 되자 운영 전용 게이트웨이가 403을 반환했습니다. 경매 상세, 마켓 목록, 포카덱스의 이미지가 실제 그림 대신 대체 이미지로 표시됐습니다.
원인
브라우저가 Pinata 게이트웨이에서 화면용 이미지를 직접 가져오는 구조였습니다. 또한 공연마다 이름이 다른 메타데이터 JSON을 새로 핀해, 이미지를 재사용해도 파일 수가 계속 증가했습니다.
추가 확인 사항
  • 배포에 적용된 전용 게이트웨이는 403을 반환하지만 공용 게이트웨이는 같은 CID에 200을 반환하는 것을 확인했습니다.
  • Pinata API에서 핀 507개를 확인했고, 운영·개발 DB를 함께 대조해 안전하게 정리할 수 있는 미참조 핀 52개를 찾았습니다.
  • 52개를 정리해 핀 수를 455개로 낮추자 전용 게이트웨이가 다시 200을 반환했습니다.

2. 개선 과정

  1. 1.배포에 적용된 게이트웨이와 Pinata 파일 수 한도 확인
  2. 2.운영·개발 DB가 참조하는 CID를 대조하고 미참조 핀을 백업한 뒤 52개 정리
  3. 3.기존 화면용 이미지 주소 407건을 CID 기반 MinIO 공개 URL로 전환
  4. 4.새 도안 생성 시 이미지를 MinIO에도 저장하고, 메타데이터에서 공연별로 달라지는 정보를 제거해 CID 중복을 줄임
  5. 5.개발·운영 Pinata 계정을 분리하고 이미지 접근 및 온체인 등록 결과 검증

화면용 이미지는 MinIO의 공개 고정 URL에서 제공하고, 기존 NFT의 온체인 URI와 외부 지갑이 사용하는 IPFS 핀은 유지했습니다. 새 도안의 메타데이터는 같은 템플릿이면 같은 CID를 재사용하도록 변경해 Pinata 파일 수 증가를 줄였습니다.

3. Before & After 비교

티캣 · 운영 과정에서 Pinata 파일 수 한도 초과로 사라진 NFT 이미지 복구 및 재발 방지 비교
항목BeforeAfter
화면용 이미지브라우저가 Pinata 전용 게이트웨이를 직접 호출해 한도 초과 시 403 발생브라우저가 MinIO 공개 URL에서 이미지를 조회
메타데이터 파일 수공연마다 메타데이터 내용과 CID가 달라져 도안 수만큼 핀 증가같은 템플릿의 메타데이터 CID를 재사용

이미지 응답 200은 운영에서 확인한 표본 3건의 결과입니다. 22건 생성 시 핀 증가량 7개는 기존 템플릿의 메타데이터 CID 재사용이 포함된 실측값입니다. 기존 NFT의 온체인 URI와 지갑용 IPFS 경로는 변경하지 않았습니다.

해결 결과

미참조 핀 정리 직후 파일 수가 507개에서 455개로 내려가 전용 게이트웨이가 복구됐습니다. 변경 후 운영에서 도안 22건을 생성하는 동안 핀은 7개만 증가해 총 462개가 됐습니다. 22건 모두 온체인 등록에 성공했고, 확인한 이미지 3건은 200으로 응답했습니다.

사례 4규칙이 놓친 NFT 이상거래를 탐지하기 위한 머신러닝 섀도 모델 구축

1. 오류 분석

문제 현상
8개 규칙 중 반복 거래쌍 규칙은 두 계정 사이만 확인해 A→B→C→A 형태의 3자 순환거래를 놓쳤습니다. 꾸민 카드에 적용한 가격 규칙 예외로 꾸밈 후 고가 거래도 탐지하지 못했습니다.
원인
개별 조건과 임계값으로 판단하는 규칙만으로는 카드 소유 이력, 거래 빈도, 가격과 계정 행동을 함께 평가하기 어려웠습니다.
추가 확인 사항
  • 합성 검증 배치에서 기존 규칙은 3자 순환거래 48건 중 1건, 꾸밈 후 고가 거래 20건 중 0건을 탐지했습니다.
  • 서로 다른 3개 시뮬레이션 배치 중 마지막 547건(이상거래 247건·정상 300건)을 통째로 분리해 기존 규칙과 모델을 같은 거래에서 비교했습니다.
  • 모델이 오탐한 정상 거래 12건은 모두 고정가 판매였습니다. 거래 유형 피처를 제외한 가상 재학습에서는 오탐 6건·탐지 223건으로 바뀌어 해당 피처의 영향을 확인했습니다.
  • 새 모델로 채점된 거래 548건에서 Java 점수와 Python 재계산값이 반올림 오차 범위에서 일치함을 확인했습니다.

2. 개선 과정

  1. 1.규칙과 동일한 거래 맥락에서 44개 후보 피처를 생성하고 규칙 판정값은 모델 입력에서 제외
  2. 2.앞선 두 배치 1,093건에서만 결측값 처리·극단값 범위·표준화 기준을 학습하고 마지막 배치 547건으로 검증
  3. 3.상수 피처를 제외한 32개 피처로 로지스틱 회귀 모델을 학습하고 동일 검증 거래에서 규칙과 탐지·오탐 비교
  4. 4.오탐 거래의 피처 기여도를 분석한 뒤 전체 1,640건으로 최종 모델을 다시 학습하고 Java 서버에 섀도 점수 기록 연결

학습된 계수와 전처리 기준을 JSON으로 저장하고, Java 서버가 거래 피처의 가중합에 시그모이드 함수를 적용해 0~1의 위험 점수를 계산하도록 했습니다. 모델 점수는 거래에 기록하되 관리자 심사 여부나 정산 보류 결정에는 사용하지 않았습니다.

3. Before & After 비교

티캣 · 규칙이 놓친 NFT 이상거래를 탐지하기 위한 머신러닝 섀도 모델 구축 비교
항목BeforeAfter
이상거래 247건 탐지기존 규칙 92건 탐지·재현율 37.2%모델 230건 탐지·재현율 93.1%
규칙의 사각지대3자 순환거래 1/48건, 꾸밈 후 고가 거래 0/20건 탐지모델이 각각 41/48건, 20/20건 탐지
정상 거래 300건 오탐기존 규칙 0건모델 임계값 0.5에서 12건, 모두 고정가 판매에 집중

탐지 성능은 시뮬레이터가 부여한 라벨 기준이며 실거래 성능이 아닙니다. 검증 배치의 이상거래 비율은 247/547건으로 높고 일부 피처가 시나리오를 거의 단독으로 구분해 성능이 낙관적일 수 있습니다. 피처 제외 실험은 오탐 원인 확인용 가상 비교로 실제 모델 변경이 아닙니다. 최종 저장 모델은 검증 뒤 전체 1,640건으로 다시 학습했으며, 548건 점수 대조는 채점 구현 검증이지 추가 탐지 성능 평가가 아닙니다.

해결 결과

합성 검증 배치에서 모델의 PR-AUC는 0.987, 정밀도는 95.0%, 재현율은 93.1%였습니다. 규칙이 놓친 패턴을 더 많이 탐지했지만 정상 거래 12건을 오탐하는 차이도 확인했습니다. 별도 548건의 Java·Python 점수 대조로 서버 채점 구현의 일치 여부를 검증했습니다.

프로젝트 성과 및 결과

  • 외부 지갑 설치·연결 없이 가입할 수 있도록 회원별 HD 지갑을 자동 발급하고, 3주 운영 동안 약 100명의 사용자 유입
  • 개발·운영 환경의 지표·중앙 로그·오류 추적·장애 알림을 직접 구축하고 발행 적체·논스 큐·DB 대기 등 업무·성능 지표 확보
  • 1,200 VU 좌석 조회에서 캐시 적용 전후 서버 p95 약 1.34초 → 13ms
  • 최종 서버 직접 호출 기록에서 3,600 VU 서버 p95 약 20ms·실패율 0%, 4,800 VU 클라이언트 p95 약 619ms·실패율 0% 확인
  • 회차별 기본 정원 5,000명·틱당 최대 200명 입장을 제어하는 가상 대기실 구현
  • 8개 이상거래 규칙과 관리자 심사 구현, 모델 점수는 정산 결정에 사용하지 않는 섀도 모드로 기록
  • 합성 검증 547건에서 규칙 재현율 37.2% 대비 모델 93.1%·정상 오탐 12건 확인, 별도 548건에서 Java·Python 점수 일치 검증

프로젝트 회고

기술적 한계와 개선 방안

한계·아쉬운 점
3주 운영 동안 약 100명의 사용자를 유입했지만, 커스터디 도입이 가입 전환율에 미친 영향은 비교 측정하지 못했습니다. 마스터 니모닉에 사용자 지갑의 통제권이 집중되는 점도 운영 책임으로 남았습니다.
개선 방향
가입 단계별 이탈과 지갑 사용률을 측정하고, 마스터 니모닉의 접근 통제·백업·복구 절차와 사용자의 외부 지갑 이전 경로를 점검하겠습니다.
한계·아쉬운 점
최종 4,800 VU 결과는 서버를 직접 호출한 좌석 조회 테스트이며, 해당 구간의 CPU 사용률이 99%여서 운영 입장 정원을 확정할 근거로는 부족합니다.
개선 방향
nginx·TLS·가상 대기실을 포함한 경로에서 선점·결제 요청을 섞어 반복 측정하고, 결과에 맞춰 회차별 입장 정원과 속도를 조정하겠습니다.
한계·아쉬운 점
화면용 이미지는 MinIO로 분리했지만 NFT의 IPFS 핀은 유지해야 합니다. 검증 당시 Pinata 핀은 462/500개였고, MinIO 업로드 뒤 공개 읽기가 403을 반환하면 생성 시 폴백이 작동하지 않습니다.
개선 방향
핀 파일 수 경보와 미참조 핀 점검을 추가하고, MinIO 공개 읽기 정책을 배포 설정으로 관리하며 실제 이미지 GET 응답을 감시하겠습니다.
한계·아쉬운 점
모델 성능은 이상거래 비율이 높은 합성 거래에서 측정했습니다. 정상 오탐 12건이 고정가 판매에 집중됐고, 일부 피처가 시뮬레이터 시나리오를 거의 단독으로 구분해 실거래 성능은 아직 확인하지 못했습니다.
개선 방향
시뮬레이션의 거래 유형과 정상 재거래 패턴을 다양화하고, 관리자 확정 판정이 쌓이면 별도의 실거래 데이터로 정밀도·재현율과 임계값을 다시 평가하겠습니다. 그전까지 모델은 섀도 모드로 유지하겠습니다.