Youngjae

React로 인터랙티브 갤러리 키오스크 만들기

React로 인터랙티브 갤러리 키오스크 만들기

2022.10.03

dev
react
 
 
회사에서 오픈한 갤러리의 입구에서 방문객들을 맞아주는 거대한 TV에 들어갈 키오스크용 SW를 만들기 위해
키오스크용 인터랙티브한 SW가 필요했다.
 
‘대체 이걸 어떻게 만들지?’
 
데스크톱이나 모바일 브라우저에서 사용하는 보통의 웹과는 다른, 생소하고 일반적이지 않은 프로젝트였다. 보통 어떤 언어와 프레임워크를 사용해 키오스크를 만드는지, 어떻게 구글링을 해야(How to make Interactive Kiosk? Which framework is Kiosk software made with)할 지도 감이 잘 오지 않았다.
구글링을 아무리 하고, 다른 키오스크는 윈도우 계열, 리눅스 계열에서 mfc나 c++로 개발한다는 사실을 알게돼도 그건 중요한게 아니었다.
갤러리용 키오스크를 SPA(Single Page Application)로 충분히 구현할 수 있을 것 같았고, React를 이용해 개발해보고자 했다.
👉
SPA(Single Page Application) A web application or website that interacts with the user by dynamically rewriting the current web page with new data from the web server
 
회사에서나 개인 프로젝트들을 할 때에는 SSR을 지원하는 Next.js를 애용하고 있지만, 이 키오스크의 경우 서버사이드에서 렌더링할 필요가 없기(SEO을 고려할 필요도 없으며 오히려 client-side에서 렌더링해줘야할 부분이 많아 보이는 프로젝트이기 때문에) 때문에 React를 사용하기로 했다.
본 프로젝트에서는 스마트 컨트랙트를 호출해 NFT를 확인하고 POAP NFT Minting을 하는 기능 또한 신경써서 개발했지만, 본 글에서는 내가 대형 화면에서 쓰는 Single Page Application(갤러리용 키오스크 인터페이스)를 어떻게 설계하고 컴포넌트를 구성했는지 고민했던 내용들에 집중해 소개하고자 한다.

요구사항 구체화하기

우선 갤러리 키오스크에 들어갔으면 하는 기능들을 듣고 요구사항을 아래와 같이 정리해보았다.
✔️
Flow 1. 평상시에는 갤러리 상설 전시 주제에 맞는 영상을 보여준다.
2. 사용자가 TV 앞 QR코드 리더기에 메타마스크앱의 QR코드를 찍으면 지갑 주소(=계좌번호)를 인식한다.
3. 지갑주소를 통해 POAP NFT를 소유하고 있는지(= 방문해서 이미 NFT를 받은 사람인지) 확인한다.
4-1. 첫방문이라면 POAP NFT를 선택해서 민트(수령)한다.
4-2. 재방문이라면 소유하는 POAP NFT를 화면에 보여주며 재방문 환영 메시지 + 이미 발급받았음을 보여준다. 4-3. (이미 public sales를 한 NFT 콜렉션의 경우) NFT 소유자(홀더)일 경우 보유한 NFT를 보여주고 환영 메시지를 보여준다.
이더리움의 스마트 컨트랙트를 호출하는 것은 직접 서버 API를 호출하는 것 보다 느리다. response가 오기까지 2-3초 정도의 시간이 걸리기 때문에 갤러리 인터페이스가 이런 기술적 한계를 극복하고 사용자에게 매끄럽고 부드러운 경험을 제공해야했다.
 
 

경험을 위해 신경 쓴 부분들

1. 대형 터치 스크린이라는 특수성

갤러리에 있는 TV에서만 사용할 어플리케이션이기 때문에 아래와 같은 조건을 고려해서 UI단부터 기획했다.
  • 터치 기능이 포함된 4K 해상도(3840 x 2160)의 대형 TV. 반응형 디자인을 적용할 필요가 없다.
  • 키보드 입력이 불가능하다.
  • 장시간 아무런 인터랙션이 없을 시 초기 화면으로 돌아가게 한다.
  • 특정인이 너무 길게 키오스크를 점유하여 기다리는 줄이 생기지 않도록 최대 시간을 정해둔다.
 
개발 기간이 촉박했던 만큼 요구사항을 받자마자 기한 내 구현할 수 있는 프로토타입을 알려드려야겠다고 생각했다. Figma로 내가 생각하는 User Flow와 Wireframe을 간략하게 그려서 디자이너분께 먼저 전달드렸다. 기술적으로 빠르게 구현이 가능한 범위 내에서 너무 화려하거나 이상적인 인터랙션(3D 모델, canvas로 어렵게 구현을 해야하는 loading Animation 등)은 빼고 기능을 우선으로 컴포넌트를 배치하고 mocking했다.
 

2. 렌더링 최적화와 매끄러운 애니메이션

이 프로젝트는 쇼핑몰 사이트과 같 많은 상태관리를 해야하거나 복잡한 로직을 필요로 하지 않는다. 이 프로젝트에서 무엇보다 중요한건 경험이라 생각했다. 입구에 위치한 키오스크부터 갤러리 방문 경험의 시작되기 때문에 무엇보다 사용자 경험을 중요시해야 했다. DOM mutation을 제대로 하지 않으면 성능 이슈가 발생할 수 밖에 없기 때문에 브라우저의 렌더링 과정도 상기하며 최적화도 고려해야했다.
 
☑️ 이미지 캐싱
웹으로 구현했지만 로딩속도에 있어서 버벅이거나 느리면 안된다. 고해상도의 이미지와 동영상 에셋의 용량이 크다보니 캐싱이 안되어있으면 이미지가 매번 느리게 로딩되는 현상이 발생했다. 어차피 한 페이지에서 고정으로 띄워두는 페이지가 될 것이기 때문에 revalidate를 할 필요가 없다. 따라서 Cache-control의 max-age를 거의 무한(3153600)으로 두고 불필요하게 데이터를 재요청하지 않도록 했다.
 
 
☑️ 피할 수 없다면 즐겨라
NFT를 발급/조회하는 기능이 들어가기 때문에 스마트 컨트랙트에 트랜잭션을 보내야 한다. 블록체인을 이용할 시 사용성을 저하시키는 요인이 있는데 바로 수십 TPS 밖에 안되는 느린 처리 속도다.
중앙화 되어있는 일반적인 API 서버를 이용하면 빠르게 처리할 수 있는 일도 블록체인을 이용하면 느릴 수 밖에 없다. 이런 많은 Web3 DApp들은 이런 느린 처리 속도 극복하기 위해 결국에 중앙화된 서버를 앞에 두는 등의 방법을 사용하고 있지만.. 아무튼 이런 느린 TPS는 블록체인을 이용한 서비스의 프론트엔드 개발을 할 때 참 아쉬운 부분이다. 사용자를 기다리게 해서는 안되지만, 기다려야한다면 이를 유쾌한 경험을 바꿔야겠다고 생각했고 방법을 모색했다.
일반적으로 시스템이 느리게 반응하면 인터페이스를 사용하는 사람의 생산성도 급격하게 떨어진다. 지연시간이 1초 이상으로 늘어나면 사용자는 집중하기 어려워지고 작업 수행에 필요한 정보를 놓치기 시작하므로 생산성은 감소한다. 그 결과 작업을 이어가는데 필요한 인지 부하가 커지고 사용자 경험은 나빠진다. UX에서 도허티 임계라는 개념이 이런 부분을 설명해준다.
 
👉
도허티 임계 컴퓨터와 사용자가 서로를 기다리지 않아도 되는 속도(0.4초 이하)로 인터랙션하면 생산성은 급격히 높아진다.
 
필요한 프로세싱(NFT 민팅)이 수행되는 동안 방문객에게 처리 시간에 관한 피드백을 주면 좋을 것 같다는 생각을 했다. 민팅 완료된 메시지를 보여주기 전에 발급중인 진행상태를 명확하게 보여주면 방문객은 속도와 반응성이 실제보다 낫다고 인지할 것이다.
다양한 아이디어가 있었다. 스피너를 넣는 가장 간단한 방법부터(별로 좋지는 않다), 세로로 물이 차오르듯이 프로그레스 상태를 보여주는 애니메이션 컴포넌트, NFT 이미지가 날아가는 효과, 귀여운 Lottie를 이용한 애니메이션 컴포넌트, 그 짧은 찰나에 보여줄 영상(?) 등등. 애니메이션이 들어간 예쁜 스피너를 넣는 것으로 우선 구현했고, 전시에 따라 유연하게 변경할 수 있도록 컴포넌트를 설계했다.
 
notion image
 
기다리는 시간 동안 스피너와 함께 ‘지금 NFT가 당신의 지갑으로 날아가고 있어요’와 같은 메시지를 테마에 맞는 애니메이션으로 전달하도록 했다.
간단한 방법임에도 이러한 방법이 효과적인 이유는 방문객이 요청한 작업(NFT 발급)이 처리되고 있다는 사실을 분명히 알 수 있고, 기다리는 동안 볼거리를 제공해주며, 실제 대기 프로세스가 아닌 진행표시줄 애니메이션에 관심이 집중되어 기다린다는 느낌을 줄여줄 수 있다.
 
 
☑️ 부드러운 전환과 애니메이션
발급 step마다 컴포넌트를 교체해서 표시되는 내용을 바꾼다. 컴포넌트로 분리한 팝업들이 딱딱하게 전환되는 것보다 fade-in이나 slide-in/out 으로 부드럽게 전환되도록 하고 싶었다. 브라우저 렌더링 과정 상 부드러운 애니메이션을 적용하기 위해서는 reflow와 repaint를 최소화해야한다.
useState로 관리하는 상태로 CSS opacity, animation, transform 속성을 조정해 자연스럽게 fade-in할 수 있는 애니메이션을 구현할 수 있는 Headless한 HOC(High Order Component)를 이용하기로 했다.
Fragmer 애니메이션을 구현해주는 컴포넌트를 만들면서 상태, 인터페이스를 어떻게 노출할 것인지 생각을 할 수 있었다.
<Transition show={isShowing} effect="fade" time={70} > <ChildComponent /> </Transition>
 
당장 도입하지는 않았지만 애니메이션에 대해 고민한 내용들은 아래와 같다.
  • Lottie를 이용해 gif보다 가볍게 애니메이션 컴포넌트 만들기
  • WebGL을 이용한 canvas를 통해 더 다이나믹한(?) 애니메이션을 구혀할 수 있도록
 
 

3. 전시 컨텐츠가 바뀔 것을 대비한 유연한 컴포넌트

갤러리는 우리 회사가 같이 협업하는 여러 NFT 프로젝트들을 상설 전시 형태로 공간을 제공한다. 큰 공간의 형태는 유지한 채 처음에는 A 프로젝트 전시를 하다가, B 프로젝트 전시로 구성을 바뀐다. 즉, 키오스크에 들어가야 할 컨텐츠도 바뀌고 전시 프로젝트 관계자 측의 요청이 있을 시 인터페이스의 수정이 필요할 수 있다.
따라서 유연하고 확장성 있게 컴포넌트를 설계하는 것이 필요했다.
 
같은 기능이지만 상황에 따라 다른 형태의 UI를 제공해야하는 예: 왼쪽은 refresh 버튼으로 n회 랜덤으로 바뀌는 NFT를 선택할 기회가 주어지 있고 오른쪽은 Carousel UI를 통해 마음에 드는 NFT를 직접 선택할 수 있다.
같은 기능이지만 상황에 따라 다른 형태의 UI를 제공해야하는 예: 왼쪽은 refresh 버튼으로 n회 랜덤으로 바뀌는 NFT를 선택할 기회가 주어지 있고 오른쪽은 Carousel UI를 통해 마음에 드는 NFT를 직접 선택할 수 있다.
위 이미지와 전시 프로젝트에 따라 다른 정책(NFT를 랜덤으로 보여주고 3번까지만 가능하게 하고 싶어요, NFT POAP 개수가 많지 않으니 스와이프 하면서 직접 원하는 NFT를 받게 하고 싶어요)이 올 수 있다.
클린 아키텍처에 나오는 대로 ‘같은 시점에 같은 이유로 변경되는 것들을 하나의 컴포넌트로 모으고, 다른 시점에 다른 이유로 변경된다면 분리한다’는 원칙을 명심하기로 했다. 컴파운드 패턴을 이용해 아래와 같이 Selector를 쉽게 변경할 수 있도록 했다.
<NftSelect> <NftSelect.Selector selector={<Slider />}/> // <Slider /> 대신 <RandomSelector limit={3}/> 사용 가능 <NftSelect.Value /> // 선택된 NFT를 보여줄 수 있는 Compound Componet </NftSelect>
한가지 역할만을 하는 컴포넌트들의 조합으로 빠르고 유연하게 변경가능하도록 설계했다. 덕분에 재사용하기도 좋고 확장 가능해졌다.
 

완성된 모습

갤러리 오픈 당일 찾아가보니 다른 분께서 설치해주신 키오스크가 잘 작동하는 것을 확인할 수 있었다. 갤러리 방문객들이 입장하자마자 터치를 하면서 인터랙티브하게 키오스크를 사용하고 있는 모습을 직접 보니 뿌듯하다.
갤러리에 가서 직접 보지 않아도 갤러리에 누군가가 입장해서 POAP NFT를 발행 받을 때마다 슬랙 모니터링 채널에 뜨는 minting transaction success 메시지를 확인하며 한번 더 뿌듯했다.
notion image
갤러리 개관 당일, 입구에서 키오스크를 체험해보는 방문객들
갤러리 개관 당일, 입구에서 키오스크를 체험해보는 방문객들
 
대형 화면에서 작동하는 갤러리 키오스크 SW를 만들 수 있음을 보여주었고, 사용자가 많은 웹이 아닌 한정적인 상황에서만 사용하는 SW를 만들 수 있었다.
 

What I learned

  • React로 색다른 프로젝트 진행
  • 재사용 가능한 컴포넌트 설계 방법
  • 새로운 문제가 와도 기술로 해결하는 경험 +1
 
p.s. 지금은 React를 브라우저 위에서 띄워주는 방식으로 구현했지만, 나중에는 Electron을 적용해보고 싶은 생각도 있다.
Electron.. 언젠간
Electron.. 언젠간
 
Video preview
이런 Visual Art도 웹(WebGL)으로 구현할 수 있으리라.
공유하기

Youngjae Jang

Copyright © 2022, All right reserved.