Minwook’s portfolio

Ad4u Final Project 회고 본문

Codestates 블록체인 부트캠프 6기

Ad4u Final Project 회고

yiminwook 2022. 12. 13. 09:21

코드스테이츠 블록체인 부트캠프에서의 마지막 프로젝트, 저에게는 세 번째 프로젝트인 Ad4u

 

Adu4는 광고주와 크리에이터를 대상으로 하는 블록체인, 스마트컨트랙트를 이용한 광고 중개 플랫폼 서비스입니다.

 

 

yiminwook - Overview

yiminwook has 10 repositories available. Follow their code on GitHub.

github.com

 

프로젝트 소개

배경.

1. 마케팅 대행사를 거치면 중개수수료가 많이 발생된다. 

2. 계약서 없이 진행되는 광고가 많고 따라서 광고비 정산이 늦어지기도 한다.

3. 단방향 선택, 광고 의뢰는 보통 광고주가 크리에이터에게 의뢰를 맡기는 형태가 대부분이다.

 

저희 Team4u는 현 광고 중개시장의 문제점을 블록체인으로 해결해보고자 시작되었습니다.

 

핵심기술.

저희가 사용하는 블록체인 핵심기술은 두 가지입니다.

1. Multisig wallet Contract, 다중서명계약

2. SBT(soulbound Token), 양도 불가능한 NFT

 

해당 기술은 광고주와 크리에이터가 다중서명계약에 confirm을 하여 광고비를 정산(transfer)하고,

계약서는 SBT로 Mint하여 법적인 효력을 갖게 하는 것을 목적으로 사용됩니다.

 

저희의 Work flow는 광고주의 다중서명계약 deploy를 기준으로 크게 두 부분으로 나뉩니다.

 

전체적인 흐름을 간단히 설명하자면

1. 광고주가 다중서명계약을 배포(deploy)

2. 크리에이터가 다중서명계약에 서명(sign)

3. 광고주가 계약서를 작성하여 암호화한 뒤 IPFS에 업로드

4. 다중서명계약 내부의 SubmitTransaction을 실행, 계약금을 받아 예치, TokenURI를 받고 SBT를 민트(mint)

5. 이후 광고주, 크리에이터가 컴펌(confirm), 파기(revoke)가 가능

6. 둘 중 한쪽이 파기(revoke)하면 예치금이 광고주에게 전송(transfer)

7. 양쪽이 컨펌(confirm)하면 예치금이 크리에이터에게 전송(transfer)

 

 

나의 역할, 기여

 개발에 관련된 부분은 깃허브, 노션이 충분히 상세히 적어놓았다고 생각하기 때문에 일부 생략하고

블로그에는 저의 역할, 느낀 점을 중점적으로 적고자 합니다.

 

 우선 저희 프로젝트는 프론트엔드(2), 백엔드(1), 스마트컨트랙트(1), 총 4명이서 개발을 진행하였습니다.

제가 프로젝트에서 맡은 역할은 프론트엔드입니다. 첫 번째 프로젝트는 팀장으로서 전체적인 개발 흐름을 잡는데 집중했었고, 두 번째는 프론트엔드를 맡고 싶었지만 팀 내 지원자가 많았기 때문에 양보를 했었습니다. 이번 Ad4u 프로젝트는 처음부터 끝까지 프론트엔드 개발에 집중할 수 있었던 프로젝트입니다. 

 

제가 담당했던 부분은 

1. 프론트엔드 API 기획, 작성

2. 회원가입, 로그인, 로그아웃, 로그인 세션유지

3. 마이페이지

 

크게 본다면 3가지 부분이었습니다. 

 

1. 프론트엔드 API 기획, 작성

 저희 팀 백엔드 담당이 1명이기 때문에 백엔드 코드를 간단히 하고 복잡한 부분은 프론트에서 맡도록 기획하였습니다. 따라서 검색 기능이나 필터링 기능은 대부분 프론트에서 구현되었습니다. 개발 후반부에 광고 제안하기 기능을 추가할 때, 광고주가 작성한 광고 목록을 가져올 필요가 있었는데 추가적인 API를 만들기보다는 전체 광고를 가져오는 API 그대로 사용하고 프론트에서 필터링하는 방식으로 써서 백엔드의 업무를 덜어주기 위해 노력하였습니다.  

 

2. 로그인페이지 (회원가입, 로그인, 로그아웃, 로그인 세션유지)

 저희 프로젝트는 광고주, 크리에이터 간의 신뢰가 중요합니다. 그러므로 본인을 인증할 수 있는 수단이 회원가입 절차에 필요하였습니다. 저희는 크리에이터 중에서도 유투버를 가장 큰 타겟층으로 생각했기 때문에 유튜브 채널을 검증할 수 있는 Google OAuth를 사용하기로 기획하였습니다. 

 

저희의 회원가입 과정은 아래와 같습니다.

 

1. 클라이언트에서 회원가입 버튼을 누르면 광고주, 크리에이터 선택창이 열린다.

2. 선택 후에 선택정보가 Boolean 값으로 클라이언트 LocalStorage에 저장되고 서버로 전송

3. 구글 사용자 동의 페이지 URL를 서버에서  받아온다.

4. 해당 URL로 이동, 사용자가 개인정보 활용 동의를 하고 클라이언트로 리다이렉션, autorization code를 받아온다.

5. autorization code를 서버로 전송하고 서버에서 accessToken을 발급받는다.

6. access Token 데이터중 channel ID, refresh Token은 DB에 저장하고, 구글 이메일은 다시 클라이언트로 보낸다.

7. 클라이언트에서 회원가입 모달이 열리고 사용자는 아이디, 패스워드, 추가적인 데이터를 입력

8. LocalStorage에 저장된 선택정보, 서버에서 받은 구글 이메일 그리고 추가적인 데이터를 서버로 전송

9. 서버에서 광고주, 크리에이터 여부, 구글 이메일을 검증하고 추가적인 회원정보를  DB에 저장

10. 회원가입이 성공적으로 완료되면 LocalStorage 회원 시 선택정보를 지우고 회원가입 모달이 닫힌다.

 

회원가입은 프로젝트 기획을 시작하고 프로젝트 종료까지 가장 많은 수정이 이루어진 부분입니다.

 우선 첫 번째로 수정된 부분은 저희는 계정 종류가 광고주와 크리에이터로 나뉘어있습니다. 따라서 회원가입 시에 어떤 계정을 생성하는지 사용자가 선택하게 되는데 이 부분이 useState로 관리되고 있었습니다. 구글 동의 화면에서 리다이렉션 될 때 State가 초기화되기 때문에 해당 부분을 LocalStorage에 저장하고 회원가입 후에 삭제하는 방식으로 개선되었습니다.

 

 두 번째는 회원가입정보를 LocalStrage에 저장하면서 발생한 문제입니다. 저희는 페이지가 렌더링 될 때 refresh함수가 실행되어 로그인 여부를 확인하고 서버에서 refresh cookie에 저장된 로그인 정보를 가져와 LocalStorage에 저장하게 되는데 refresh cookie가 없으면 모든 LocalStorage를 지우도록 되어있었습니다. 이 refresh 함수에 의해서 회원가입 중간에 LocalStorage에 저장된 회원가입 정보까지 지워버려서 서버에서 해당 값이 undefined로 나오는 문제가 발생하였습니다. 문제를 인지하고 나서는 refresh 함수가 회원가입 데이터를 지우지 못하도록 수정하였습니다.

 

 세 번째는 Google OAuth 설정 관련이었습니다. 처음 서버로 access Token을 데이터에 받았을 땐 refresh Token이 없었고 

해당 access Token으로 youtube channel ID를 가져오면 오류가 발생되었습니다. 해당 문제는 백엔드를 담당하신 팀원과 같이 공식문서 stack overflow를 찾아보면서 youtube scope를 추가하여 권한을 가져오고, access_type: offline을 추가하여 refresh Token을 발급받아 서버에서 access Token을 재발급받을 수 있도록 설정했습니다. 이 부분들은 클라이언트와 서버를 어우르는 부분이었기 때문에 혼자서는 해결하려고 했다면 개발 스케줄이 밀릴 수도 있었을 것이라고 생각됩니다. 

 

3. 마이페이지

 저희는 마이페이지에서 광고 계약을 확인하고 관리하도록 기획하고 개발되었습니다. 또한 광고주, 크리에이터 별로  마이페이지의 컴포넌트 구성이 다릅니다.

 

광고주 마이페이지 주요 기능

1. 광고 업로드

2. 회사 정보 수정

3. 다중계약 배포(deploy)

4. 계약서 작성(민팅)

5. 민팅한 계약서 다운로드

6. 광고 컨펌 및 파기

7. 완료, 파기된 광고 조회

 

크리에이터 마이페이지 주요 기능

1. 회원가입 시 이더리움 계정(address) 확인

2. 광고 제안 승낙, 거절

3. 지원중인 광고 현황 조회 및 취소

4. 다중서명계약 서명(sign)

5. 민팅한 계약서 다운로드

6. 광고 컨펌 및 파기

7. 완료, 파기된 광고 조회

 

 광고주 마이페이지에서는 계약서를 암호화하여 민팅하고 다중서명계약에 저장하는 부분, 역으로 복호화해서 PDF 형식으로 가져오는 부분은 스마트컨트랙트 담당이시면서 팀장이신 현우 님이 작성해주셨습니다. 이외의 대부분의 기능은 제가 담당해서 개발을 했습니다. 

 마이페이지에서 제가 가장 신경 쓴 부분은 라우터와 컴포넌트 파일 정리입니다. 우선 저희 마이페이지는 광고주와 크리에이터로 나뉘어 있어 처음 마이페이지는 2가지 라우터로 나뉘게 됩니다. 또한 광고주는 광고를 업로드해서 크리에이터를 모집하고, 협의가 끝난 최종 계약서를 SBT로 민트 하기 위한 2가지 페이지가 필요했기 때문에 광고주 마이페이지에서 한번 더 라우터가 나뉘게 됩니다. 

 광고 진행상태별로 실행시킬 수 있는 스마트컨트랙트 함수가 다르기 때문에 6가지 진행상태별로 각각의 광고 컴포넌트가 다르게 랜더링 시킬 필요가 있었습니다. 따라서 다른 페이지에 비해서 마이페이지는 내부에 추가적인 페이지가 있는 데다가 컴포넌트 수도 매우 많았습니다. 정리를 잘하지 못하면 같이 작업하는 팀원들에게 혼란을 줄 수 도 있기 때문에 파일명, 파일 구조를 알기 쉽게 정리하였습니다.   

 

 

느낀 점

이번 프로젝트는 부트스트랩과 다양한 패키지를 사용해보고 프로젝트의 완성도를 높이는 것을 목표로 하였습니다. 

 

React & React router DOM

 Routes를 중첩해서 사용하여 뒤로 가기 앞으로 가기, 새로고침 등 사용자 경험을 생각하면서 짜임성 있게 페이지를 구성하였고 광고 ID는 useParams로 URL에서 가져오고 useEffect를 사용하여 서버에서 해당 광고에 대한 GET, POST 요청을 할 수 있도록 기획 때부터 다양한 React hooks를 고려한 WireFrame를 작성하였습니다. 이번 프로젝트를 약 4주간 진행하면서 React를 중점적으로 개발하다 보니 자연스럽게 React hooks에 대한 이해도가 높아지고 사용하는데 익숙해졌습니다. 

 

BootStrap

 프론트엔드에서 제가 가장 부족하다고 여기는 부분은 CSS입니다. Bootstrap의 가장 큰 장점인 꼽히는 그리드 시스템을 이용한 반응형 웹을 실제로 만들어보는 것이 제가 앞으로 프론트엔드 개발자로서 필요한 과제라고 생각되었습니다. 그리드 시스템을 사용하여 컴포넌트를 원하는 곳에 배치하는 것은 처음에는 어려웠지만 CSS를 함께 사용하여 구상했던 디자인을 만들어 나가는 과정은 매우 흥미로웠습니다. BootStrap을 사용하면서 유용했던 컴포넌트는 모달입니다 모달을 사용하지 않았을 때는 입력 폼을 위한 페이지를 하나 더 만들지, useState를 사용하여 컴포넌트를 ON/OFF 시켰었는데 모달을 사용하니 확실히 잘 정리된듯한 느낌을 받았고, 프로젝트의 완성도가 높아 보이게 하는 효과가 있었습니다.   

 

AWS S3

 이번 프로젝트는 처음으로 클라우드 서비스를 프로젝트에 적용해보았습니다. S3와 RDS가 프로젝트에서 사용이 되었고 프론트엔드에서는 S3만을 다루었습니다. 항상 프로젝트를 진행할 때  이미지에 대한 저장 방식이 고민이었습니다. DB에 버퍼 형식으로 저장하고 가져온다면 부하가 많이 걸리고 서버 폴더에 저장을 하고 경로를 저장하는 방식으로 한다면 git에 추적되지 않도록 해야 하고 RDS로 팀원과 DB를 공유했을 때 경로가 다르기 때문에 이미지가 공유되지 않는 문제가 있었습니다. 클라우드 서비스를 사용하게 되어 클라이언트에서도 환경변수를 관리해야 할 필요가 생겼고 패키지는 dotenv를 사용하였습니다.

 

 

개선할 점

 이번 프로젝트는 테마가 정해져 있지 않고, 아이디어부터 내는 것부터 시작해서 기획을 한 프로젝트입니다. 기획의 중요성을 알고 있었기 때문에 다른 앞선 두 프로젝트보다 기획에 시간도 많이 투자하고 TODO List, WireFrame, WorkFlow를 구상했지만 프로젝트 종료를 앞두고서 기획에 허술한 점이 많이 드러났습니다. 

 

문제점

1. 크리에이터가 광고를 상당히 진행했는데 광고주가 일방적으로 파기 시에는 광고주에게는 가스비와 수수료를 부담하기 때문에 디메리트가 없진 않지만 크리에이터에게도 보상이 없습니다.

2. 예치금이 이더리움으로 변동성이 많습니다. 따라서 광고가 종료되고 예치금이 전송되는 시점에서 폭등하거나 폭락할 가능성 있습니다.

3. 수익구조를 기획하지 않았습니다.

4. 광고주 계정의 어뷰징 가능성이 있습니다.

 

 

해결방안 

1. 현재 광고가 6가지 진행도로 나뉘고 있는데 진행도를 더욱 세분화하고 컨펌도 현재 광고주, 크리에이터가 1번 컨펌하도록 되어있지만 여러 번 컨펌하도록 바꾸어 파기가 되더라도 광고의 진행도에 따라서 크리에이터가 예치금을 일부를 가져갈 수 록 개선해야 할 필요성을 느꼈습니다.

2. 원화와 동일한 가치를 스테이블 토큰을 발행하여 환전시스템을 구현할 필요성을 느꼈습니다. 또한 이더리움 대신에 토큰을 예치하도록 개선이 필요합니다.

3. 기술적인 부분과 개발만 생각하다 보니 실제로 서비스를 한다면 수익을 어떻게 만들어낼지에 대한 고민 자체를 하지 않았었습니다. 지금 생각해 보았을 때, 2에서의 환전시스템에서 환전수수료를 받는다면 광고주, 크리에이터 양쪽으로부터 공평하게 수익을 가져올 수 있을 것으로 예상됩니다.

 4. 크리에이터는 Google OAuth로부터 채널 인증을 받지만 광고주는 구글 이메일로 인증을 받는다고 해도 가짜 계정과 같은 어뷰징을 완전히 막을 수는 없습니다. 사업자번호를 통해서 인증하는 방법도 생각해보았지만, 사업자번호도 도용의 가능성이 없지 않다고 생각했기 때문에 관리자 계정을 만들어서 관리자가 직접 확인해서 회원가입을 신청받는 방식 또는 사업자번호 조회와 함께 휴대폰 인증, 카카오나, 네이버 간편 인증을 추가로 받아 본인인증을 강화하는 방식으로 개선이 필요합니다.

 

 기획에서의 문제점 외로 개선할 점은 CSS입니다. 반응형 웹을 만들려고 노력했지만 브라우저의 Width가 좁혀졌을 때 컴포넌트의 위치를 재지정하는 것이 어려웠고, Bootstrap의 컴포넌트를 그대로 사용하는 것은 매우 편리하다고 생각이 들었지만 반대로 정해진 형태의 컴포넌트밖에 사용할 수 없기 때문에 다양한 버튼(Button)을 사용하거나 카드(Card)를 사용하려면 결국 CSS로 직접 만들어내는 과정이 필요했습니다. 따라서 라이브러리에 의존하기보다는 CSS를 더 공부해서 직접 만들어낼 수 있는 수준에 도달해야 한다는 필요성을 느꼈습니다.

 

 

 

Comments