⌜What’s Next⌟는 클라이언트와 RPC 노드를 통해 상호작용 할 수 있는 컨트랙트, 그리고 서버로 구성되어진다. 클라이언트를 통해 유저에게 서비스 사용을 위한 UI/UX를 제공받는다. 만화의 장면을 이어나가기 위해서 하는 커뮤니티의 투표는 온체인 상으로 이루어지고, 컨트랙트를 통해 블록체인에 기록된다. 클라이언트와 컨트랙트는 RPC 노드를 통해서 상호작용할 수 있다. 서버는 데이터베이스와 사용자 인증을 관리하며, 온체인 상에 기록되는 데이터를 서버에 저장해두고, 블록체인에서 조회하는 것보다 더 빠르게 유저가 데이터를 확인할 수 있다.
블록체인은 중요한 데이터를 분산 저장하며, 참여하는 노드들의 합의를 통해 추후에 만들어지는 데이터 저장 여부를 결정하는 프로토콜과 네트워크를 말한다. 블록 단위로 데이터가 저장이 되며, 보통은 디지털 자산의 소유권에 대한 정보를 저장하고 있다. 이더리움을 필두로, 작성되어 있는 컨트랙트 코드의 논리데로 작동하는 가상 머신이 네트워크에 존재하여 원하는 탈중앙화 서비스를 개발할 수도 있다.
⌜What’s Next⌟는 커뮤니티의 투표를 투명하게 공개하기 위해서 블록체인 기술을 이용하고 있다. 블록체인에 기록되는 데이터는 공개되어 있기 때문에 누구나 투표 과정과 결과를 열람할 수 있다. 투표 전반적인 시스템도 블록체인 상에서 컨트랙트를 통해 구현할 수 있다. ⌜What’s Next⌟의 주요 기능인 토큰을 이용한 투표는 컨트랙트로 구현되는 회계 시스템으로 구현된다.
⌜What’s Next⌟의 주요 목표 중 하나는 기존 Web2 환경에서 웹툰을 즐겨오던 유저들의 원활한 온보딩이다. 목표를 달성하기 위해 ⌜What’s Next⌟는 니어 프로토콜을 이용하기로 했다. 타 체인들과는 다르게, 니어 프로토콜은 Web 2.5를 지향하는 블록체인이다. 니어 프로토콜은 Web2 유저들의 온보딩을 위해 쉬운 지갑 연동과 획기적인 key 관리 시스템을 마련해주고 있다. 또한 대표적인 Layer-1 체인인 이더리움의 값비싼 가스비 문제를 해결해 유저들이 저렴하게 블록체인 서비스를 이용할 수 있게 만들어주고 있다.
프롬프트에 유저가 만들고 싶은 이미지 키워드만 입력하면, 해당 키워드로 이미지를 만들어주는 것이 AI 이미지 생성기다. Stable Diffusion과 MidJourney가 대표적이며 이 외에도 많은 모델을 존재하여 새로운 이미지를 만드는데 사용되고 있다. 특히 Stable Diffusion 같은 경우는 개발사인 OpenAI 측에서 오픈소스로 공개해서 많은 참여자들이 존재하고 있다.
특히 WebUI는 Stable Diffusion을 기반으로 여러 부가적인 기능을 유저들이 손쉽게 이용할 수 있게 클라이언트까지 만들어 제공해주고 있다. 이를테면 기능들을 모듈별로 추가할 수 있으며, 만들어지는 이미지의 인물이 포즈를 취하게 만들거나, 동일한 인물이 새로운 이미지에 나타날 수 있게 만든다. 또한 API Listener를 만드는 기능도 제공해주고 있어 AI 이미지 생성 서버로 이용 가능하다.
기능 | 설명 |
---|---|
웹툰 컨텐츠 리스트 뷰 및 감상하기 | 커뮤니티를 통해서 만들어지고 있는 웹툰의 리스트를 확인할 수 있고, 특정 웹툰을 감상할 수 있는 화면이 제공된다. |
웹툰 다음 장면 제안 | 유저가 다음 장면을 생성하기 위한 프롬프트 키워드를 제안하고, 만들어질 이미지에 대한 설명을 덧붙일 수 있게 만든다. |
제안 리스트 뷰 및 투표하기 | 다음 장면 생성을 위해 유저들의 제안을 리스트로 확인할 수 있으며, 플랫폼에서 발행하는 토큰을 원하는 만큼 지불하며 투표를 할 수 있다. |
투표 결과 산출 및 AI 이미지 생성 웹툰에 추가 | 커뮤니티에서 정한 기간 동안 이루어진 투표에 가장 많은 투표를 받은 제안의 프롬프트 키워드로 AI 이미지를 생성한다. 이후 해당 커뮤니티가 관리하는 웹툰의 마지작 장면으로 삽입되어 유저가 컨텐츠로 확인할 수 있게 만든다. |
유저는 배포된 클라이언트로 UI/UX를 제공받는다. 유저에게 보여주고자 하는 웹툰 컨텐츠들은 IPFS에 저장하고 제공된다. 서버에 저장된 데이터를 통해 유저가 접하고자 하는 컨텐츠를 맵핑해서 보여준다.
핵심 기능인 투표 기능은 니어 프로토콜 컨트랙트로 구현된다. 투표에 사용되는 플랫폼 토큰은 니어 프로토콜의 NEP-141 표준을 따르는 Fungible Token의 형태로 발행된다. 플랫폼 토큰이 지불되고 투표에 기록되는 회계시스템 또한 니어 프로토콜 컨트랙트로 구현된다. 기존 유저가 가지고 있는 플랫폼 토큰이 사용되는 만큼 차감되고, 차감된 만큼 투표에 정산되는 형태로 구현하고 있다.
투표가 종료된 후 제안이 선정되면, WebUI를 통해 만들어진 AI 이미지 생성기를 이용해서 새로운 만화 장면을 생성한다. 이를 IPFS에 저장시키고 컨텐츠와 맵핑시켜 클라이언트에게 전달해, 유저가 새로운 컨텐츠를 즐길 수 있게 만든다.
필자는 ⌜What’s Next⌟ 프로젝트에서 컨트랙트를 담당했다. 니어 프로토콜은 이더리움과 달리 컨트랙트 작성을 Rust 언어로 한다. 니어에서 만든 near-sdk 라이브러리를 이용해서 컨트랙트를 작성해나가면 된다. 글리치 해커톤 밋업 후 3주 동안은 Rust만 공부했다.
Rust 가 가장 인상깊었던 것은 기존의 언어들의 메모리 관리 방식과는 전혀 다른 방식을 취하는 것이었다. 소유권이라는 개념으로, 한 값에 대해, 해당값을 가지는 주체는 오너 한 명 뿐이라는 것이다. 그래서 브라켓 영역 밖으로 벗어나면 메모리를 자동으로 해제해 주거나, 함수의 인자로 전달이 되면 함수 브라켓 안에서 새로운 오너 하나 명만 해당 값을 소유할 수 있다.
또한 Rust는 Javascript하고는 다르게 타입이 명시되어야 하는 언어이다. Typescript하고 비슷하다고 할 수 있는데, Rust는 더 강력하게 사용한다. 이를테면 Option 이라는 열거형과 Result라는 열거형을 사용하는데 개발자가 개발을 하면서 사용할 수 있는 Null 상태를 인지하며 처리할 수 있게 만든다.
블록체인에 남겨지는 데이터는 모든 노드들에 중복되어 저장이 된다. 그렇다보니 어떻게든 데이터를 적게 저장하는 것이 관건이다. 그래서 온체인에 꼭 저장되어야 하는 데이터와 서버에만 저장해도 되는 데이터를 구분해야 한다. 이를테면 NFT에 대한 메타데이터는 JSON의 형식으로 인터넷에서 접근할 수 있게 만들어 URL만 온체인에 저장한다.
그런 맥락에서 near-sdk는 Borsh라는 라이브러리를 이용해서 컨트랙트의 데이터를 온체인에 저장할 때 직렬화를 사용해서 저장을 해놓는다. 이는 다음과 같다.
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
pub struct Contract {
pub accounts: LookupMap<AccountId, Balance>,
pub total_supply: Balance,
pub metadata: LazyOption<FungibleTokenMetadata>,
}
그래서 VM을 통해 컨트랙트 메소드가 실행되면 BorshDeserialize를 통해 역직렬화를 시켜 객체화해 사용할 수 있게 만든다. near-sdk는 이렇게 기본적인 데이터 사용부터 전반적인 컨트랙트 작성에 필요한 많은 기능을 제공해준다.
필자가 가장 해맸던 부분은 컨트랙트를 어떻게 설계할 것이냐는 것이었다.
우선 투표가 필요하고, 투표는 한 커뮤니티에서 시간 순서로 여러 개가 만들어질 수 있었다. 커뮤니티는 웹툰 컨텐츠와 1:1로 매칭되어 한 커뮤니티 당 한 웹툰 컨텐츠를 갖게 되는데, ⌜What’s Next⌟는 여러 커뮤니티와 여러 컨텐츠가 이용하는 플랫폼이기 때문에, 플랫폼 기준으로 또 여러 커뮤니티와 웹툰 컨텐츠가 만들어진다. 그래서 처음에는 다음과 같이 만들어졌다.
투표 팩토리와 커뮤니티 팩토리, 컨텐츠 팩토리를 하나씩 만들어 컨트랙트 생성 기능에만 맞춘 컨트랙트를 설계해 봤었다. 하지만 이렇게 설계한 것 때문에 클라이언트에서 가지고 있어야 할 컨트랙트 주소가 많아졌고, 또한 컨트랙트 메서드 호출도 복잡해진 것 같다. 관리가 매우 어려워졌다.
그래서 이후에는 커뮤니티 팩토리를 통해 만들어진 커뮤니티 객체에서, 투표 컨트랙트를 만들고, 컨텐츠 팩토리를 소유할 수 있게 만들려고 수정해봤다. 지금 와서 한 번 더 고쳐본다면, Uniswap에서 사용하는 Router 처럼 모든 주소를 컨트랙트 상에 상수로 저장해놓고 여러 컨트랙트들과 클라이언트의 상호작용을 돕는 Entry Point 역할을 하는 컨트랙트를 작성해서 사용하는 것도 좋을 것 같다는 생각을 하고 있다.
니어 프로토콜이 Web 2.5를 지향하고 있어서 ⌜What’s Next⌟도 더 쉽게 사용자들이 이용할 수 있는 DApp이 되게끔 만들고자 고민을 많이 했다. 그러다보니 여러 해결해야 될 문제들이 발생했다.
일단 첫 번 째로, 니어 프로토콜 설계와 쉬운 온보딩 시스템의 충돌이다. 니어 프로토콜은 컨트랙트 스토리지를 사용하고자 하는 유저에서 수수료를 예치하게끔 만든다. 이 수수료는 니어 프로토콜에서 발행하는 니어 코인을 통해 지불된다. 예치된 니어 코인은 더 이상 스토리지를 안 사용하게 되면 인출해 갈 수 있다. 이를 통해 스토리지 공격을 막는다는 계산도 있다.
하지만 온보딩을 하면서 유저가 니어를 쇼유하고 있지 않아도 서비스가 대납할 수 있게끔 만드는 기능이 있는데, 스토리지 사용에 대한 대가를 받는 시스템과 상충하고 있다는 생각을 하고 있다. 스토리지 사용 수수료는 사용 당사자가 낼 때 의미가 있다 생각하기 때문이다. 그럼 ⌜What’s Next⌟는 어디까지 할 의향이 있는 유저를 온보딩 시킬 것인지 선택해야 했다.
사실 니어를 사서 본인의 니어 프로토콜 계정으로 전송하는 것까지도 엄청나게 큰 허들이라고 생각해서 대납하는 기능을 생각했었다. 하지만 ⌜What’s Next⌟는 만화 장면 제안 같은 경우 온체인에 올라가는 데이터라, 제안하는 유저가 스토리지를 영구적으로 사용하게 된다.
그리고 두 번 째로, Access Key 관리와 서버 인증 문제이다. 니어 월렛을 통해 손쉽게 사용자의 Full Access Key를 동의를 받고 가져올 수 있는 것과 이 덕분에 수많은 트랜잭션 처리도 기존 Web2 환경을 이용하는 것처럼 자연스럽게 처리할 수 있었던 것도 바로 이 덕분이었다.
Access Key를 가지고 오게되면 브라우저의 LocalStroage에 저장되게 된다. 그리고 이 Access Key가 탈취되면 ⌜What’s Next⌟만이 아닌 모든 해당 유저와 연결된 재산과 직결될 정도로 위험하다. 이 때문에 니어는 Function Call Key를 사용하는 것을 더 권장한다.
Function Call Key는 대신에 각 컨트랙트마다 새로 발행해야한다. ⌜What’s Next⌟처럼 새로운 투표 컨트랙트를 만들어서 사용하는 경우는 컨트랙트와 상호작용을 시작할 때마다 발행해와서 사용해야 한다. 어디까지가 UX를 위한 것이고 어디까지가 보안을 위한 것인지 고민해야할 필요가 생겼다.
우선은 Access Key를 사용해서 당분간의 개발 편의를 도모하는 쪽에 손을 들어줬다. 하지만 점점 더 ⌜What’s Next⌟를 이용하면서 유저에게 할당되는 크립토자산이 생길 것이고 더 신중한 보안을 위해 방법을 바꿔야할 필요가 생길 것이다.
AI 이미지 생성기를 이용하여 이미지를 생성하는 것은 생각보다 비용이 크게 들어간다. 기본적으로 N 사의 최신 그래픽카드를 사용하며 16GB VRAM이 넘어야 한다. 기존의 이미지를 선정하는 방식에서 프롬프트 키워드를 선정하는 방식으로 바꾼 것도, 사용하는 컴퓨팅 파워를 줄이기 위해서였다.
또한 AI 리스크는 뜻밖에 대중의 반감이라는 문제도 맞닥뜨리게 되었다. 기존 Web2 웹툰 플랫폼에서 소유한 컨텐츠들을 학습시켜 새로운 AI 만화를 만들었던게 화제가 되었다. 이는 학습 데이터를 제공한 작가가 정당한 대가를 못 받아서 생긴 문제였다. 그리고 아직은 AI가 완전한 만화의 내러티브를 형성하기에는 부족하다는 평가도 있었다. 이를테면 같은 장소에 놓여져 있는 물건들이 바뀌거나 미세하게 그림체들이 바뀌는 문제였다.
이 프로젝트가 AI 이미지 생성기를 사용하는 것에 대한 정당성을 확보하려면 사용하는 학습 데이터 모델이 정당한지 확인할 필요가 생겼다. 그리고 또한 선정된 프롬프트 키워드로 만들어지는 웹툰 장면이 내러티브를 만들만큼 개연성이 있게 만들어지게끔 고민해야 한다.
우선 적어도 등장하는 인물은 의도한 장면에 똑같이 등장 시킬 수 있는 방법을 마련해보려고 한다. 우리 팀은 그래서 LoRA 라는 기술을 통해 작가가 학습시킨 케릭터 모델을 이용해서 웹툰 장면을 생성할 수 있게 해결 방법을 제시하려고 한다.