DID 수료증 PoC 개발 회고

부제: Quick & Dirty, 생산성과 기술 부채 그 사이에서 갈피를 잡기

안녕하세요 코드스테이츠 블록체인 엔지니어링 부트캠프 팀의 주니어 블록체인 엔지니어 한승욱입니다.

저는 블록체인 부트캠프를 운영하는 일원으로서 수강생 교육과 콘텐츠 개선 업무를 진행하며 이외에도 블록체인 기술을 통해 해결할 수 있는 다양한 시도를 하고 있습니다.

최근 제가 참여한 “DID 수료증 PoC” 개발 경험을 회고하고 공유하고자 이렇게 글을 작성하게 되었습니다.

PoC란 Proof of Concept의 약자로, 말 그대로 “개념 증명”을 의미합니다.

이는 새롭게 시작하는 프로젝트가 정말 구현이 가능한지, 실현 가능성이 있는지 기술적으로 검증하는 것입니다.

예를 들어 “김치볶음밥”을 만들겠다고 한다면, 김치가 정말로 볶아지는지, 가스레인지가 작동 가능한 상태인지 확인하는 것을 PoC로 말할 수 있을 것입니다.

하나의 프로젝트가 결과물을 세상에 뱉어내기까지 수많은 설득의 과정이 필요합니다.

그중 초기 설득 과정에서 PoC를 통해 빠르게 실현 가능 여부를 검증하고 프로젝트의 추가 진행 여부 또는 타당성을 검토받고는 합니다.

그래서 본인에게 주어진 미션도 Quick & Dirty였습니다.

“빠르게, 완벽하지는 않아도 시도에 초점을 맞추자”

결과적으로 6주간의 개발 과정을 통해 스스로 생각하던 수준의 결과물을 뱉어낼 수 있었습니다.

이 과정 속에서 얻은 것은 문서화/커뮤니케이션의 중요성을 깨닫고, 자기 자신의 기준과 타협하는 법을 배운 것입니다.

반면 아쉬운 점은 Dirty 함을 제대로 이해 못하고 타협하지 못하는 바람에 Quick 함을 놓쳐버린 것입니다.

“이렇게 개발해도 되나?”, “이게 맞나?”의 수많은 고민과 내적 갈등, 그리고 개발기를 소개하고자 합니다.

배경

코드스테이츠의 교육 과정 수료자는 해당 과정을 성실히 이수했음을 “수료증 발급”을 통해 증명할 수 있습니다.

기존의 발급 과정은 아래와 같았습니다.

1. 수료생이 수료증 발급 신청

2. 부트캠프 운영자가 확인

3. 부트캠프 운영자가 신청자 검증

- 정말 부트캠프를 수료한 것이 맞는지

4. 부트캠프 운영자가 수기로 수료증 작성

- 이때 일러스트 작업을 직접 진행

5. 부트캠프 운영자가 수료생에게 메일 발송

- 이때 작성한 수료증을 첨부

이를 자동화하면서 DID(Decentralized Identity, 탈중앙 신원 증명)라는 기술로 보호를 하자는 것이 이번 프로젝트의 개요였습니다.

Decentralized Identity(탈중앙 신원 증명, 이하 DID)란, 데이터의 주권이 개개인에게 있고, 필요할 때 그 데이터를 중앙화된 시스템을 거치지 않고 증명할 수 있는 기술로써, 분산원장 기술(Distributed Ledger Technology, DLT)을 기반으로 사용자 정보를 저장하여 안전하고 편리한 인증이 가능하도록 합니다.

코로나가 한창일 때 쓰던 CooV 앱을 생각하면 보다 직관적으로 이해하기 쉬울 것입니다.
해당 프로젝트가 성공적으로 상용화된다면 크게 두 가지 이점이 있습니다.

  • 부트캠프 운영자의 번거로움을 덜 수 있음(시간 확보)
  • 부트캠프 수료 여부 검증 가능(신뢰성 확보)

사실 처음에 프로젝트를 접했을 때의 제 솔직한 심정은 아래와 같았습니다. 여기에 굳이 DID라는 기술이 필요할지, 블록체인으로 풀어야 하는 문제가 맞는지 의구심이 들었습니다.

자동화라는 이점에 대해서는 100% 동의하지만,
신뢰성 측면에서는 아무리 극단적인 상황(예. 수료생이 수료증을 조작)을 가정해도 블록체인 기술을 활용하는 것의 비용이 더 크다고 생각했기 때문입니다.

하지만 여기서 제가 놓쳤던 부분이 있었습니다.
이러한 R&D 프로젝트의 숨겨진 목적은 “주니어 엔지니어의 역량 향상”이라는 것이었습니다.

즉, 아직은 블록체인 기술에 익숙하지 않은 주니어 엔지니어들의 손기술(코딩)을 향상하게 시키며, 더불어서 사업 타당성까지 검증된다면 사업 확장이라는 두 마리 토끼를 잡을 수 있는 것입니다.

프로젝트의 본질을 파악하자 마음 한편이 편안해졌던 기억이 있습니다.

이후 본격적으로 진행하기에 앞서 아래와 같이 목표와 제약조건 등을 정리해보았습니다.

프로젝트명: DID 수료증 개발

배경:
- 관리자 입장에서 수료증을 수기로 발급 중
- 수료증의 진위를 판별하기 어려움

목표:
- 풀스택 웹 기반 PoC
- 기능에만 집중하기

제약 조건:
- 원래 업무와 병행해서 진행해야 함
- 현재 디자인 / 퍼블리싱 리소스 없음

진행

저는 프로젝트가 진행되던 중간에 참여하게 되었기에 기존의 진행 상황 파악을 우선으로 진행했습니다.

노션에 작성되어 있던 여러 문서, 줌 녹화 기록을 검토하며 어떤 아키텍처로 기획되었는지, 지금까지 진행된 개발은 어느 정도인지 인지하는 것부터 시작하였습니다.

위의 아키텍처는 해당 문서에서 발췌한 것인데 PoC인만큼 비교적 간단한 구성이었습니다.

블록체인은 클레이튼을 활용하며 자체 DB에는 유저의 정보나 did 정보를 저장하는 방식이었습니다.

아키텍처
- 일반적인 웹 아키텍처(프론트, 백엔드 API, DB)와 동일
- 백엔드 API 단에서 컨트랙트를 호출하고 정보를 블록체인에 저장

개발 진행 상황
스마트 컨트랙트:
구현 완료
- Solidity

백엔드 API: 기본 틀 구현 완료
- Node.js & Express

프론트엔드: 유저, 어드민 구현 안 됨
- React.js 예정

프론트엔드를 우선순위로 개발하고 시간이 남으면 백엔드까지 개선해보자고 다짐하며 시작했습니다.

개발은 총 6번의 1주일 간격 스프린트에 걸쳐 진행되었습니다.
모든 개발 과정은 문서화해야 한다는 요구사항이 있었기에, 스프린트별로 페이지를 만들어 기록하면서 진행했습니다.

[기록 중 일부]

이러한 기록하는 과정이 가장 어려웠습니다.
매번 “왜” 그리고 “어떻게” 기록할지 생각해야 했고, 추후 코드가 수정되면 기록 역시 또 한 번 수정을 해줘야 하는 부분이 가장 시간을 많이 잡아먹었습니다.

“과연 이게 누구한테 도움이 될까?”, “오히려 Quick 하지 않은 것 같은데?”, “얼마나 구체적으로 기록해야 할까?”

관련하여 제 생각을 시니어분들께 전달하였을 때 들었던 답변은 아래와 같습니다.

“당장은 문서화가 어렵겠지만 익숙해질 필요가 있다. 결국은 팀의 커뮤니케이션을 위함이다”

처음에는 전혀 이해가 안 되었지만, 추후 팀원 한 분이 더 참여하셨을 때가 되어서야 참 의미를 이해할 수 있었습니다.
제 (투박한)문서가 새로운 참여자에게 지금까지의 진행 상항을 팔로우업하는 데 도움을 주고, 불필요한 커뮤니케이션을 줄여줄 수 있는 것을 알게 되었습니다.

만약 Dirty 하면서 문서화까지 되어 있지 않다면 그야말로 갚을 수 없는 기술 부채가 되어 버리지 않았을까요?
Quick & Dirty를 보완해줄 수 있는 것이 이러한 문서화라는 것을 깨달았습니다.

[개발 산출물 중 일부]

첫 주차 과정에 완성한 개발 산출물입니다.
이때 스프린트 목표는 아래와 같았습니다.

  • 리액트 프로젝트 세팅
  • 클립 로그인 기능 구현
  • 로그인 시 유저 정보 출력

요구한 기능은 전부 개발 완료하였습니다.

클립 로그인의 경우 예전에 동기가 개발하는 것을 옆에서 참고한 경험이 있어서 비교적 쉽게 개발할 수 있었습니다.
하지만 기존에 합의가 된 “기능 구현을 위주로 함”에 스스로 타협이 안 되는 문제가 발생했습니다.

레이아웃도 없고, 그 흔한 헤더도 없고, 그렇다고 당장 퍼블리싱을 할 수 있는 것도 아닌 제 상황을 스스로 받아들일 수 없었습니다.
자꾸 PoC를 개발한다는 것을 잊고, 프로덕트의 관점에서 지금의 모습을 바라보다 보니 자기 부정하는 시간이 늘어만 갔습니다.

“이 정도로는 안될 텐데?”, “이거는 Dirty의 수준을 넘은 것 같은데?”, “대체 무엇이 Best Practice일까?”, “Typescript로 짜는 게 좋지 않을까?”, “내가 지금 기술 부채를 만들고 있는 것 아닐까?”, “CSS 어떻게 하지?”

가뜩이나 프론트엔드 개발에 익숙하지 않고, 퍼블리싱의 “퍼”자도 모르는 상태에서 높은 기준만 내세우다 보니 스스로 만족이 되지 않는 것이었습니다.

이러한 상황은 이후 스프린트에도 영향을 미쳤습니다.

프론트엔드 & 백엔드 API를 엮는 것을 우선순위로 진행했어야 했지만, 자꾸 리소스를 CSS/SCSS, MUI 등에 낭비하게 되었고 그마저도 결과가 크게 개선이 되지 않았습니다.

당장 퍼블리싱 쪽으로 성과가 나지 않자 이번에는 백엔드 쪽으로 눈길을 돌렸습니다.
“조금 더 개선해보자”
2주라는 기간을 할애하여 API를 갈아엎고, 유효성 검사를 넣고, 구조를 다시 짜고, Docker를 도입하고…

기존 API를 조금만 변경해주고, 기존의 컨트랙트 호출 과정을 조금만 수정해주면 충분했을 것을, 본질을 벗어나 버리고 말았습니다.
역시나 자기 부정하는 시간이 늘어만 갔습니다.

“이 코드가 Clean 할까?”, “Typescript를 도입해야 하나?”, “Best Practice가 무엇일까?”, “테스트 코드도 짜야 할 것 같은데?”

본격적으로 프로덕트를 만들 때가 됐을 때, 다시 개발 컨벤션을 만들고, 프로세스를 만들고, 리팩토링하는 단계를 만들어도 늦지 않을 텐데, 검증하는 단계에서 굳이 필요없는 에너지를 낭비해 갔습니다.

이때 고민하던 부분을 시니어분들이나 팀 내에 공유해야 했는데 혼자서 끙끙 앓고 어려워했습니다.

‘고민 & 갈등 → 질문 & 공유 → 해결’ 의 구조로 나아가야 했지만,
‘고민 & 갈등 → 고민 → 갈등 → 고민 → 갈등 → …’ 이러한 재귀적 구조만 깊어져 갔습니다.

이때 2주 연속 “스프린트 목표”를 제대로 완수하지 못하기도 했습니다.
스스로 무언가 잘못되었다는 신호를 알아차리고 문제 상황과 해결방안을 정리해보았습니다.

문제
- Dirty 함에 타협을 못 하고 고민하는 시간이 많아짐
- 그렇다고 고민해서 나오는 결과가 Clean 한 것도 아님
- Quick 하게 결과물이 안 나옴

해결
- 어느 정도 Dirty까지 용납할 것인가 범위를 정해야 함
- 포기할 부분은 과감하게 포기할 줄 알아야 함(예. 퍼블리싱)
- 목표한 기능이 우선임을 다시 인지하기

이미 처음에 얼라인이 된 부분이었지만, 다시 한번 스스로에게 납득시키기 위해서는 현재 상황을 냉정하게 파악하고 곱씹어보는 과정이 필요했습니다.

그리고는 아래와 같이 정리해보았습니다.

Dirty 함의 범위:
- 테스트 코드는 생략
- 디렉터리 구조는 분리하는 것을 원칙으로 함(최대한 지키되 필요시 생략 가능)

프론트: pages, components, apis 등
백:
db, controllers, routes, middlewares 등

- master/main 브랜치에 바로 커밋 가능(단, 상대방과 합의가 되었을시)
- 네이밍 컨벤션은 최대한 보편적인 컨벤션을 지킴
- 모든 예외 처리를 하려고 하지 말기

포기할 부분:
퍼블리싱
- 지금 스스로 아무리 고민해도 결과물을 향상시키는 것에 한계가 명확함(스프린트 경험에 근거함)
- MUI나 Bootstrap의 기본 템플릿 가져다 쓰는 방법으로 대체

클린 코드
- 지금 스스로 아무리 고민해도 완벽하게 할 수가 없음

보여지는 퍼포먼스
- 우선은 팀 내의 PoC이기에 부담을 안 가져도 됨

목표:
- PoC, PoC, PoC. 검증만 하자.
- 내가 성장한다면 그것만으로도 목표의 반은 이룬 것.

정리하고 나자 마음이 다시 한번 편안해졌던 기억이 있습니다:)

결과적으로는 마지막 6주 차 스프린트를 기점으로, 목표했던

  1. 유저가 수료증 발급을 신청할 수 있는 “유저 프론트엔드”
  2. 어드민이 수료증 확인 후 발급할 수 있는 “어드민 프론트엔드”
  3. 컨트랙트 호출
  4. 컨트랙트에 배포되는 내용 유저, 어드민이 확인할 수 있어야 함

모든 기능을 전부 완료 및 배포까지 진행할 수 있었습니다.

[유저 프론트엔드 중 일부]

[어드민 프론트엔드 중 일부]

스스로 기준 또는 범위를 재정의한 이후에는 고민하는 시간도 줄고 마음이 불편한 일도 줄어들었습니다.

그리고 고민되는 지점이나 궁금한 점이 있으면 그때마다 시니어분들께 질문하고 같이 이야기를 나누었습니다.

물론 결과물에 있어서 아쉬운 부분은 많습니다.

Authentication, Authorization, 퍼블리싱, 테스트코드, 클린 코드 등…

욕심은 끝이 없지만 주어진 기간 안에 모든 것을 다 할수도, 다할 필요도 없다는 것을 알기에 만족하고자 합니다.

모든 과정은 검증 가능한 형태로 구현이 되었고 이제는 설득 과정을 통해 MVP(Minimum Viable Product) 개발로 넘어가는 일만이 남았습니다.

Quick & Dirty…

어디까지 Dirty 함으로 인정해야 하는지에 대한 고민이 이번 프로젝트를 Quick하지 못하게 만들었습니다.

기준이나 범위를 사전에 조금이나마 명확하게 잡고 갔다면 보다 기간을 단축시킬 수 있지 않았을까 생각이 듭니다.
스프린트마다 목표를 세우는 것까지는 좋았지만 그것을 계획으로 풀어내고 관리하는 것 또한 부족했던 것 같습니다.

그러다 보니 업무 외 시간을 종종 투입하고는 했는데,
만약 완벽한 목표 달성이 어렵다면 스프린트 중간에 조정하는 것도 좋은 방법일 것입니다.

개발용 이슈 관리 툴을 활용해보는 것도 하나의 좋은 방법일 것입니다.
혹자는 엔지니어 또는 개발자에게 Dirty 함은 용납되지 않는다고 하기도 합니다.
저 역시 모든 것을 Dirty 하게 만들어서는 안 된다고 생각합니다.
하지만 PoC 또는 MVP처럼 Quick 함이 요구되는 경우만큼은 예외적으로 매우 유의미한 방법론이라고 생각합니다.

적절한 문서화를 통해 Dirty 함을 보완한다면 추후 기술 부채를 갚기 유리해지지 않을까요?

이상으로 언젠가는 Quick & Clean 한 개발을 할 수 있기를 바라며 글을 마무리합니다.

저와 비슷한 고민을 하고 계시는 분들 또는 블록체인 부트캠프 수강생분들에게 도움이 되었으면 합니다.

감사합니다.

--

--