명품 영수증 관리 애플리케이션
개요
고가의 명품을 중고 거래할 때 명품을 구입한 가게에서 받은 영수증도 같이 보여주는 일은 꽤 빈번합니다. 내가 산 명품이 "진짜"임을 증명하는 방법이기도 하고, 모조품을 구하는 것보다 가짜 영수증을 만드는 것이 어떻게보면 더 어렵기 때문입니다. 그런데, 이렇게 중고 거래를 하려면 처음 받은 영수증을 보관하고 있어야 하는데 영수증은 보관하기 어렵습니다. 작고 얇아서 잃어버리거나 찢어지거나 구거지기 쉽고, 감열지를 사용하므로 열이나 빛을 받으면 내용이 쉽게 지워집니다.
따라서 블록체인에 명품 영수증을 보관한다면 영수증을 안전하게 영구적으로 보관하면서 이를 거래 시 자유롭게 활용할 수 있을 것입니다. 이 튜토리얼은 블록체인인 클레이튼상에서 영수증을 보관하고 전송하는 BApp(블록체인 애플리케이션) 예제를 소개합니다. 이 예제는 클레이튼의 대체 불가 토큰(Non-fungible Token, NFT)인 KIP-17을 기반으로 전자 영수증을 발행해서 중고 거래에 사용하도록 합니다. 영수증은 클레이튼에 배포되므로 영수증 주인이 개인키를 잃어버리지 않는 한 클레이튼상에 계속 보관해둘 수 있습니다. 따라서 중고 거래를 할 때 새로운 주인에게 영수증을 안전하고 쉽게 전달할 수 있고, 새로운 주인이 명품을 재판매할 때에도 동일하게 다음 주인에게 영수증을 넘겨줄 수 있습니다.
하나의 명품은 하나의 NFT(KIP-17) 스마트 컨트랙트를, 하나의 영수증은 하나의 NFT 토큰을 나타냅니다. 명품 브랜드마다, 혹은 브랜드를 판매하는 가게 수준에서 관리하는 기능을 추가할 수도 있으나, 이 튜토리얼에서는 하나의 가게만 존재하는 상황을 가정합니다.
이 애플리케이션의 핵심 기능은 아래와 같습니다.

새로운 NFT 스마트 컨트랙트 배포 = 명품 가게에서 새로운 명품을 (블록체인상에서) 등록
새로운 NFT 토큰 발행 = 가게에서 명품을 판매하고 전자 영수증을 (블록체인상에서) 손님에게 발급
NFT 토큰 전송 = 가게에서 명품을 구매한 손님이 다른 사람에게 중고로 판매할 때 (블록체인상에서) 영수증을 전송
위 기능들을 구현하기 위해, 아래와 같이 시스템을 구성하였습니다.
Frontend: React
Backend: Node.js, caver-js
caver-js: KIP-17 토큰 컨트랙트 배포, 토큰 발행, 토큰 전송
DB: MySQL
명품 가게에서 상품 정보, 발행한 영수증 정보 저장
KAS: Node API, Token History API
Node API로 클레이튼 Endpoint Node 사용
Token History API로 토큰 발급 기록 조회

이 페이지의 모든 내용은 KAS로 블록체인 애플리케이션 개발을 돕는 예제입니다. 소스코드를 포함한 모든 내용은 사용자 개발 환경에 따라 다르게 적용될 수 있습니다. 소스코드를 포함한 모든 내용을 사용하는 것에 대한 모든 책임은 전적으로 사용자 본인에게 있습니다.
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
시작하기
프로그램 설치
MySQL 설치
코드에서는 아이디
root, 패스워드root로 설정되어있습니다.test데이터베이스에 테이블이 존재하기 때문에,test데이터베이스가 없는 경우 생성해야 합니다.
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
데이터베이스 셋업
product와receipt두 개의 테이블이 필요합니다.product는 등록된 명품을 관리하기 위한 테이블입니다.
receipt는 발행된 영수증을 관리하기 위한 테이블입니다.
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
저장소 복사하기
https://github.com/ground-x/kas-bapp-luxurytracker 에 있는 코드를 클론합니다.
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
npm install
루트 디렉토리의
server.js파일이 백엔드 서버 기능을 담당하고,client디렉토리는 리액트 기반 프론트엔드 기능을 담당합니다. 이렇게, 이 튜토리얼은 백엔드/프론트엔드 모두 자바스크립트 기반의 패키지 매니저를 사용했기 때문에npm install이 2번 필요합니다: 루트 디렉토리에서 1번,client디렉토리에서 1번npm install이 필요합니다.
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
KAS 설정하기
client/src/Config.js에 KAS Console을 통해 발급받은 accessKeyId와 secretAccessKey를 입력합니다.
튜토리얼에 사용할 계정 충전하기
본 튜토리얼에 사용되는 판매자와 구매자 계정은 트랜잭션을 직접 발생시키기 때문에, 트랜잭션 발생에 필요한 KLAY가 없다면 node.js에서 아래와 같은 에러가 발생할 수 있습니다. 테스트넷인 Baobab 네트워크에서 본 튜토리얼을 실행하는 경우 Faucet을 통해서 테스트에 필요한 KLAY를 지급 받을 수 있습니다. Cypress 네트워크를 사용할 경우 판매자와 구매자 계정에 KLAY를 직접 충전해주어야 합니다.
실행하기
루트 디렉토리에서 아래 명령어를 실행합니다. 아래 명령어로 백엔드 서버와 프론트엔드를 한 번에 실행시킬 수 있습니다. http://localhost:3000 에서 실행된 프로그램을 확인할 수 있습니다.
(해당 포트가 이미 사용중인 경우 다른 포트 번호를 사용하십시오.)
사용 영상
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
애플리케이션 워크플로우
위에서 소개한 것처럼 이 예제 BApp이 수행하는 핵심 기능은 아래와 같습니다.
새로운 NFT 스마트 컨트랙트 배포 = 명품 가게에서 새로운 명품을 (블록체인상에서) 등록
새로운 NFT 토큰 발행 = 가게에서 명품을 판매하고 전자 영수증을 (블록체인상에서) 손님에게 발급
NFT 토큰 전송 = 가게에서 명품을 구매한 손님이 다른 사람에게 중고로 판매할 때 (블록체인상에서) 영수증을 전송
프론트엔드에서는 애플리케이션 사용자(=명품 가게 주인, 명품을 구입하려는 손님)의 요청을 백엔드 서버로 보내고, 백엔드 서버의 응답을 사용자에게 보여줍니다. 프론트엔드 코드는 저장소에 있는 코드를 확인하십시오.
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
새 명품을 가게에서 파는 상품 목록에 등록
새로운 명품을 등록하는, 즉 새로운 컨트랙트를 배포하는 코드입니다. 이 튜토리얼에서는 명품 가게 주인이 새롭게 판매할 명품을 블록체인상에 직접 등록합니다. 명품 가게 주인이 새로운 스마트 컨트랙트를 배포 caver-js를 이용해서 KIP-17 컨트랙트를 배포하기 위해서는 가게 주인의 개인키가 필요합니다. 이 예제에서는 간단한 구현을 위해 클라이언트에서 서버에 보내는 req 오브젝트에 가게 주인 개인키가 들어 있습니다. 실제 서비스 개발시에는 서버에서 가게 주인의 개인키를 보관하는 것이 좋습니다.
./client/src/components/ProductAdd.js에서 KIP-17 컨트랙트를 클레이튼에 배포하겠다는 요청을 보내면, ./server.js 에서 이 요청을 받아서
새로운 KIP-17 컨트랙트(=새롭게 판매할 명품)를 배포(=등록)하고
배포된 KIP-17 컨트랙트의 정보를
product테이블에 저장합니다.
전체 플로우는 다음과 같습니다.
가게 주인 개인키를 caver 지갑에 등록 (이미 등록된 경우 생략) - 프론트엔드
등록할 명품 정보 입력, 명품 정보를 백엔드 서버에 전송 - 프론트엔드
프론트엔드에서 받은 명품 정보를 바탕으로 KIP-17 컨트랙트 배포 - 백엔드
배포된 KIP-17 컨트랙트에 대한 정보(=새 명품 정보)를
product테이블에 저장 - 백엔드
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
명품 매출 발생 시 손님에게 영수증 발행
새로운 스마트 컨트랙트를 배포함으로써 새롭게 출시되는 명품을 블록체인에 등록헸다면, 명품 가게 주인은 이제 이 명품을 판매하기 시작할 것입니다. 명품 가게에 찾아온 손님에게 명품을 판매하면 손님에게 영수증을 발급합니다. 이 때 전자 영수증을 블록체인상에서 손님에게 발급합니다.
블록체인상에서 영수증을 손님에게 발급하는 것은, 위에서 만든 KIP-17 스마트 컨트랙트에서 새로운 토큰을 손님의 EOA로 발행하는 것과 같습니다. caver-js를 이용해서 KIP-17 토큰을 발급하기 위해서는 가게 주인의 개인키가 필요합니다. 이 예제에서는 간단한 구현을 위해 클라이언트에서 서버에 보내는 req 오브젝트에 가게 주인 개인키가 들어 있습니다. 실제 서비스 개발시에는 서버에서 가게 주인의 개인키를 보관하는 것이 좋습니다.
./client/src/components/ReceiptAdd.js 에서 요청을 보내면, ./server.js 에서 요청을 받아서
새로운 KIP-17 토큰(=전자 영수증)을 손님에게 발급하고
발급한 KIP-17 토큰의 정보를
receipt테이블에 저장합니다.
전체 플로우는 다음과 같습니다.
가게 주인 개인키를 caver 지갑에 등록 (이미 등록된 경우 생략) - 프론트엔드
발행할 영수증 정보 입력, 백엔드 서버에 이 영수증 정보를 전송 - 프론트엔드
프론트엔드에서 받은 영수증 정보를 바탕으로 새로운 KIP-17 토큰 발급 - 백엔드
발급된 KIP-17 토큰에 대한 정보를
receipt테이블에 저장 - 백엔드
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
중고품 판매자가 구매자에게 가게에서 받은 영수증 전송
손님은 구매한 명품을 한동안 잘 사용하다가 이를 중고로 처분하고 싶은 마음이 생겼습니다. 이렇게 명품을 다른 사람에게 중고로 판매할 때, 명품 가게에서 받은 영수증도 중고품 구매자에게 함께 전달하려고 합니다. 이 예제 BApp에서는 중고 명품 판매자가 중고 명품 구매자에게 KIP-17 토큰을 보냄으로써, 명품을 처음 살 때 받은 영수증을 다른 사람에게 넘깁니다.
이 예제에서는 간단한 구현을 위해 클라이언트에서 서버에 보내는 req 오브젝트에 중고 명품 판매자의 개인키가 들어 있습니다. 실제 서비스 개발시에는 서버에서 중고 명품 판매자의 개인키를 보관하는 것이 좋습니다.
./client/src/components/ReceiptSend.js 에서 요청을 보내면, ./server.js 에서 요청을 받아서
중고 명품 판매자가 KIP-17 토큰(=영수증)을 중고 명품 구매자에게 전송하고
전송한 KIP-17 토큰의 정보를
receipt테이블에 업데이트합니다.
전체 플로우는 다음과 같습니다.
중고 명품 판매자의 개인키를 caver 지갑에 등록 (이미 등록된 경우 생략) - 프론트엔드
중고 명품 판매자가 구매자에게 전송할 영수증을 선택 후 중고 명품 구매자의 EOA 주소를 입력하면, 이 EOA를 백엔드 서버에 전송 - 프론트엔드
프론트엔드에서 받은 정보를 바탕으로 KIP-17 토큰(영수증)을 중고 명품 구매자 EOA로 전송 - 백엔드
전송한 KIP-17 토큰에 대한 정보를
receipt테이블에 업데이트 - 백엔드
영수증 전송 과정을 좀 더 자세히 설명하면 아래와 같습니다.
중고 명품 판매자는 BApp에서 자신의 중고 명품 구매자의 클레이튼 계정 주소(=EOA)를 선택하고 판매 버튼을 클릭
ReceiptSend.js는 영수증을 중고 명품 판매자로부터 구매자에게 전송하라고 백엔드 서버에 요청백엔드 서버(
server.js)는 이 요청을 받고, 먼저 영수증 소유권이 변경되었다는 내용을 DB에 업데이트DB 업데이트 후,
server.js는 영수증을 판매자로부터 구매자에게 전송하는 트랜잭션을 KAS에 요청KAS가 이 트랜잭션을 실행한 후, 중고 명품 구매자는 자신의 BApp에서 명품 영수증을 전달 받았다는 메세지 수신
구매자는 Klaytnscope에서 자신이 영수증을 잘 전달 받았는지(블록체인상에서 영수증 소유권이 잘 변경되었는지) 확인 가능
구매자는 BApp상에서도 언제든지 전달받은 영수증과 소유권 정보를 확인 가능
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
부가 기능: 명품 판매 기록 조회
명품 가게 주인은 자신이 판매한 명품 하나에 대해, 손님에게 발급한 영수증 목록을 불러올 수 있습니다. 이는 곧 어떤 KIP-17 컨트랙트 1개에서 발행한 모든 토큰 목록을 불러오는 것과 같습니다. product 테이블에 저장되어있는 contractAddr 을 바탕으로 Token History API의 NFT 조회 기능을 사용하면 영수증 목록을 불러올 수 있습니다. 이 부분에서는 위 예제 코드들과는 다르게 caver-js 를 사용하지 않고 REST API만을 사용합니다.
전체 플로우는 다음과 같습니다.
영수증 목록을 조회하고 싶은 명품 정보를 백엔드 서버에 전송 - 프론트엔드
프론트엔드에게 받은 명품 정보(=명품 아이디)를 바탕으로 product 테이블에서 대응되는 컨트랙트 주소 조회 - 백엔드
조회한 컨트랙트 주소를 바탕으로 KAS Token History API의 NFT 조회 기능 사용 - 백엔드
조회된 NFT 토큰 리스트를 프론트엔드로 리턴 - 백엔드
이 문서 혹은 KAS에 관한 문의는 개발자 포럼을 방문해 도움을 받으십시오.
Last updated
Was this helpful?