Visual Studio Code와 함께 Smart Contract 개발환경 구축하기.

--

최근 굉장히 많은 부류의 Contract를 개발해야 했습니다. 각각의 개발 환경이 독립적으로 작동해야 했는데, 테스트에 사용되는 프로세스가 다른 개발 환경에서 이미 동작 중이거나 내부 포트를 공유하는 일이 빈번하게 발생했습니다. 각각의 개발 환경을 독립적으로 작동하게 만들어야 했습니다.

몇 년 전이었다면 Vagrant를 이용해서 개발 환경을 구성하고 공유하겠으나, 이 또한 원활하게 사용기 위해서는 해주어야 할 것들이 많았습니다. Virtual box의 느린 속도 개선을 위한 트윅이거나, 로컬에서 작성 중인 소스코드를 Vagrant 환경과 동기화 시켜야 하는 일들 포함해서 말이죠. 이런 Tweak은, 배포 환경에 포함되지 않는 것도 문제였습니다.

어느 날부터는 Vagrant를 사용하지 않게 되었습니다. 비슷한 솔루션으로 Docker 또한 개발 환경으로 사용할 수 있다는 말은 들었지만, 당시 주로 사용하고 있던 Mac에 통합된 모습을 보여준 것은 아니어서 주어진 환경에서 개발을 많이 했었습니다.

그러면서 개발에 사용하는 편집기도 시간에 따라 바뀌었는데, Visual Studio나 XCode와 같은 무겁고 쓸모없는 것들이 많이 설치되는 IDE를 많이 사용했었다면, Sublime Text를 주로 사용하기 시작했고, 이후에는 Visual Studio Code를 이용하게 되었습니다. 내부적으로 터미널을 가진 것이 아주 인상적이었고, Sublime Text 못지않은 확장 기능들이 있는 것이 마음에 들었습니다.

최근에 VSCode에서 사용할 수 있는 확장 기능 중에 Remote라는 것이 생겼습니다. SSH, Docker, Windows Subsystem for Linux(WSL)을 통해서 원격지에 있는 개발 환경을 VSCode 인터페이스로 이용할 수 있다는 것이었죠. Vagrant를 이용하면서 장점으로 가지는 환상적인 영역 분리와 함께 에디터의 파워풀한 기능을 가질 수 있게 된 것입니다.

이번 글에서는 이 기능을 이용해서 Ethereum Smart Contract를 개발하는 환경을 구성하고, 더 나아가 이번에 미리 보기로 발표된 Visual Studio Online에서 같은 개발 환경을 이용할 수 있도록 설정해 줄 것입니다.

🕹 Remote 확장 기능 설치

Remote Development Extension

[🚀 Remote Development Extension]

보시다시피 이 확장 기능은 아직 미리 보기 이기 때문에 추후에 정식 출시되었을 때 기능이 변경될 수 있습니다. 당장 설치해서 이용해보죠. 😉

위 링크를 통해서 설치를 하면, 4개의 확장이 추가 설치되어, 총 5개의 확장이 설치되는 것을 확인할 수 있습니다.

앞서 말씀드렸듯, Remote는 다양한 환경을 지원하기 때문에 프로토콜 별로 확장 기능이 별도로 존재하는 형식입니다. 구성하고자 하는 환경에 따라서 WSL을 이용하거나, Containers를 이용할 수 있습니다.

제가 주로 개발하는 환경은 Mac인데, SSH 또는 Containers를 이용할 수 있을 것입니다. 이번에는 Containers를 이용해 보겠습니다.

Containers 기능을 이용하기 위해서는 Docker가 필요합니다. Mac에서 이용할 수 있도록 Docker for Mac이 필요하기 때문에, 이를 이용하고 있지 않으신 분들이라면 이번에 설치해보도록 하겠습니다.

[🚀 Docker Desktop for Mac]

설치가 끝났다면, 실행 또한 잘 되어 있으리라 생각합니다. 😉

🎋 환경 구성하기

우선 빈 디렉토리를 만들어서 VSCode로 열어야 합니다.

이렇게 아무것도 없는 화면이 뜬다면, [⇧(shift) + ⌘(cmd) + P] 단축키를 누르거나, Command Palette(명령 팔레트)를 찾아 띄우면 됩니다.

아래와 같이 입력하는 창이 뜬다면, remote를 검색해서 다음과 같은 명령어를 찾아주세요.

커맨드를 많이 사용했더니 자주 사용하는 명령어 목록에 올라가 있네요. 저기 선택되어 있는 Add Development Container Configuration Files…를 선택해 줍시다.

그러면 위와 같은 화면이 표출됩니다. 저희는 JavaScript로 구성된 개발 환경을 이용할 것이기 때문에, node를 검색해서 LTS 버전을 이용하겠습니다.

이 상태에서 ⏎(Enter)를 누르면 아래과 같이 파일들이 생성되고 아래 알림창이 하나 뜹니다.

생성된 파일들을 하나씩 살펴보자면,

devcontainer.json는 Container를 정의할 Dockerfile을 지정하고, 터미널이 실행될 때 작동하는 쉘을 지정합니다. 통신이 필요하다면 Port 설정을 할 수도 있고, Container가 만들어질 때 수행되는 명령어를 지정할 수도 있습니다. 이 파일을 변경하여 약간의 설정을 좀 해주겠습니다.

name의 값으로는 ‘Smart Contract Dev Enviroment’ 라고 변경했고,

postCreateCommand는 주석을 풀고, npm install으로 명령어를 변경했습니다. Container가 새롭게 생성될 때, 해당 명령어를 실행하게 됩니다.

extensions부분은, Container가 연결되어 있는 동안 사용할 확장 기능들의 목록을 적어주면 됩니다. 이때 설치되는 확장 기능들은, Container와 연결이 끊기는 즉시 삭제됩니다. 개발 환경을 온전히 공유할 수 있게 되는 것이죠! 이 목록에서는 Extension Id를 적어 주면 됩니다.

여기서 변경한 부분들은 gist로 공유됩니다. [gist]

이후에 다시 Command Palette(명령 팔레트)를 열어서 Reopen in Container를 실행합니다.

위에서 보다시피, Container가 설정되고 있고, 왼쪽 아래에는 ‘원격 여는 중…’이라 표시됩니다. 초기에 Container를 구성하는 초기에만 시간이 오래 걸리고 이후에는 거의 바로 실행됩니다.

Docker 명령어를 사용하면 Container가 자동으로 구성되어 작동 중인 것을 확인할 수 있습니다.

아래와 같이 VSCode 내부에서 Terminal을 작동 시키면, Container 내부의 작업 중인 디렉토리로 부터 쉘이 시작되며, 파일 또한 동일한 것을 확인할 수 있습니다. Container를 구성하기 전에 zsh 나 같이 생성되는 Dockerfile을 이용하여 유용한 도구들 또한 설치할 수 있을 것입니다.

Terminal을 그대로 두고, npm init -y명령어를 통해 간단히 Nodejs 개발환경을 초기화 해주고 생성된 package.json을 링크된 내용으로 바꿔줍시다. [gist]

그리고 npm i 명령어를 통해서 package.json 파일에 기재된 의존성 모듈들을 모두 다운로드 받아줍니다.

다음에 npm run truffle:init 명령어 또는 npx truffle init을 입력하면, 디렉토리가 비어있는 상태가 아닌데 진행하겠냐고 물어봅니다. Y를 입력해서 truffle를 사용하기 위한 기초를 설정해줍니다.

그렇습니다. 우리는 Truffle을 사용할 것입니다.

위 과정을 모두 성공적으로 마쳤다면 위와 같은 디렉토리 구조로 변경되어 있을 겁니다.

🥕 Contract와 테스트 코드 작성하기 🥕

우선 Ethereum에서 작동할 모든 Contract Code는 contracts/ 디렉토리 내부에 위치하여야 합니다. 우선 간단하게 아래의 코드를 Counter.sol이라는 이름으로 만들어 주겠습니다.

contracts/Counter.sol

그러면 이제 해당 코드를 배포하는 코드를 작성해야 합니다. 기본적으로 migrations라는 디렉토리 내부에 배포와 관련된 코드가 위치하게 됩니다. 다양한 Contract들을 배포하면서 배포에 필요한 로직들은 변형이 필요할 것이기 때문에, 이러한 구조를 가지게 되었습니다. Migration에 대한 자세한 정보는 truffle의 문서를 확인하세요.

migrations/디렉토리 내부에 1_initial_migration.js 파일이 존재하며, 이미 존재하고 있는 Migration Contract를 Ethereum에 배포하기 위한 코드입니다. Counter Contract를 배포하기 위해서 동일한 디렉토리에 2_deploy_contracts.js 파일을 하나 생성해 줍니다. 내용은 아래와 같습니다.

migrations/2_deploy_contracts.js

Contract 코드도 작성했고, 배포 스크립트도 작성하여 Ethereum에 배포할 수 있게 되었습니다. 이제 작성한 Contract가 명세에 맞게 잘 구현되었는지 확인해야 합니다. 테스크 코드를 작성해 봐야겠죠.

이러한 테스트 코드는 test/ 디렉토리 내부에 위치해야 하며, 파일 이름을 counter.spec.js라고 명명하겠습니다.

test/counter.spec.js

테스트 코드도 작성되었습니다! 지금은 Contract가 하나 뿐이기 때문에 유닛테스트로 작동하지만, 다양한 Contract를 가지고 있다면 통합 테스트를 진행할 수도 있습니다.

3가지 파일이 전부 준비되었다면, 터미널에서 npm run truffle:develop 또는 npx truffle develop을 입력하여, truffle에 내장된 개발 콘솔을 열 수 있습니다.

truffle 개발 콘솔이 열린 모습

deploy를 입력하면, Contract 코드를 컴파일하고 내장된 Ethereum 개발 환경에 코드가 배포됩니다. 이 과정이 순식간에 이뤄지는데 실제 Ethereum 메인넷에 배포를 하게 되면 이렇게 빠르진 않겠죠.

이후에 test를 입력하면 다음과 같이 작성한 내용에 대해서 테스트가 이뤄지는 것을 볼 수 있습니다.

🪔 Visual Studio Online에서 사용하기

최근 Microsoft는 다양한 제품들을 출시했는데, 이중 미리 보기로 공개된 Visual Studio Online을 주목할 필요가 있습니다.

기본적으로는 위에서 보여드린 Remote를 이용하는 것과 다름없습니다. Azure에 가상머신을 실행시키고, Web Browser로 가상머신과 연결된 VSCode를 이용한다는 것입니다. 개발 환경이 이미 정의된 상태에서 배포되기 때문에 이를 이용하는 개발자들과 동일한 개발 환경을 구성할 수 있게 됩니다.

저는 위에서 작업했던 프로젝트를 github에 공유해 두었고, 다음과 같은 설정을 통해서 Visual Studio Online에 가상 머신을 만들 수 있었습니다.

Visual Studio Online 환경을 구성할 때 Github 저장소를 이용할 수 있습니다.

이렇게 생성된 개발환경에서 오른쪽 아래 햄버거 버튼을 누르면, Open in VS Code 가 있는데, 이는 Local 환경에 설치된 VSCode에 해당 개발 환경을 연결해줍니다. Remote 기능을 이용하는 것과 동일하다고 볼 수 있습니다.

또는Connect를 누르게 되면 브라우저 자체에 VSCode가 작동되며, 모든 작업을 동일하게 수행할 수 있습니다. VSCode가 웹 기술로 만들어 진 것을 고려하면 충분히 가능한 일이죠? 🤷

Visual Studio Online에서 동일한 테스트 케이스를 통과하는 모습

이는 분명 커다란 발전입니다. 이로 인해 개인이 가지고 있는 머신은 일종의 인터페이스 역할만 수행하게 되었기 때문에 노트북 보다 훨씬 가벼운 태블릿 PC에서도 동일한 개발환경을 가질 수 있게 되었습니다. 우리의 가방이 좀 더 가벼워 지지 않을까요? 😉

🤔 Self Hosting 버전은 없을까요?

가능…은 합니다. Visual Studio Online 공개와 동시에, Web Browser 개발 모드가 공개되었습니다. 그러나 이는 VSCode의 소스코드를 전부 받아서 실행시키는 것에 지나지 않습니다. 웹브라우저의 경험을 개선하기 위한 용도이기 때문에 개발을 이 기능으로 이용하기에는 무리가 있습니다. $50 이하의 리눅스 머신을 구해서 Remote-ssh 기능을 이용하는 것이 보다 합리적이라고 볼 수 있습니다.

좀 더 자세한 정보는 다음 링크를 참조하시길 바랍니다. https://code.visualstudio.com/updates/v1_40#_test-vs-code-running-in-a-browser

👩‍🍳 다른 용도로 사용 가능한가요?

가능합니다. 저는 Nodejs 이미지를 빌드해서 사용했지만, OpenJDK가 들어 있는 이미지를 기반한다면 Java를 기반한 개발 또한 가능하고, zsh 설정이나 에디터 설정이 포함되어 있다면 좀 더 강력한 개발 환경이 공유될 수 있을 것입니다.

또한 Port를 열어서 가상머신 외부와 통신을 할 수 있기 때문에 Front-End를 개발하는 작업에도 적합합니다. 여러 라이브러리를 이용하고 TypeScript를 이용할 때 버전이나, 대 소문자를 구분하는 파일 시스템과 관련된 사소한 트러블 슈팅을 막을 수 있습니다.

외에도 Python 개발 환경을 구성하는데 있어, Virtualenv와 같은 사소한 설정을 피할 수 있습니다.

Truffle을 좋아하지 않으신다면, Waffle을 사용해 볼 수도 있겠죠! Embark도 있고, Remix를 사용해 볼 수도 있겠죠?

궁금한 점이 있으시다면, 의견을 남겨주세요!

--

--

𝚢𝚘𝚘𝚗𝚜𝚞𝚗𝚐.𝚎𝚝𝚑

𝙱𝚕𝚘𝚌𝚔𝚌𝚑𝚊𝚒𝚗 𝚋𝚕𝚊𝚑 𝚋𝚕𝚊𝚑 🍻 𝙾𝚙𝚒𝚗𝚒𝚘𝚗𝚜 𝚊𝚛𝚎 𝚖𝚢 𝚘𝚠𝚗.