Overview
2 - DApp 개발 환경 셋업
Overview DApp 만들기: 기본 개발 환경 셋업Overview DApp은 어떻게 만들 수 있을까요?OverviewDApp은 기존 Web 2.0의 중앙 집중식 구조에서 벗어나, 블록체인 기반의 탈중앙화된 방식으로 동작하는 애플리
spems.tistory.com
이전 시간에는 Foundry와 Node.js를 설치하며 기본적인 DApp 개발 환경을 구축했습니다. 이번 시간에는 DApp의 핵심이 되는 스마트 컨트랙트를 빌드하고 배포하기 위한 필요한 작업에 대해 알아봅시다.
브랜치 변경
GitHub - ooMia/hands-on-dapp: 블로그 연재 중인 DApp 제작 가이드 레포
블로그 연재 중인 DApp 제작 가이드 레포. Contribute to ooMia/hands-on-dapp development by creating an account on GitHub.
github.com
이전 1 - 기본 개발 환경 셋업에서 설치한 hands-on-dapp 레포가 복사된 디렉토리로 이동합시다.
readme.md의 안내에 따라 git checkout case1-hello-world 를 실행합니다.
README.md
code . 를 실행하면 현재 디렉토리에 대해 VIsual Studio Code를 실행합니다. 개발 관습 상, 프로젝트에 대한 설명을 README.md 파일에 작성하니, 습관적으로 확인합시다. 주어진 mermaid를 통한 다이어그램은 여러분이 위에 적힌 npm install && npm start 를 실행했을 떄, 프로젝트가 어떻게 동작하는지에 대한 대략적인 동작 방식을 표현하고 있습니다.
++ 저와 동일한 화면이 나오지 않을 수 있습니다. 크게 세 가지 이유가 있는데,
- Mermaid 문법의 미리보기는 확장 프로그램을 설치해야만 제대로 동작합니다. 필요에 따라 Markdown Preview Mermaid Support를 설치하거나, 그냥 GitHub 미리보기를 활용하더라도 무관합니다.
- 폰트의 차이가 있습니다. 두 문자 ->를 한 문자 →처럼 보이도록 하는, 합자 기능을 가진 폰트를 사용할 수 있습니다. Fira-code 또는 Monaspace 같은 폰트가 있겠네요.
- VS Code 자체의 개인화된 설정 차이입니다. IDE의 테마라든지, 바의 위치와 구성 등 원하는대로 변경할 수 있습니다. ⌘ + ⇧ + P (cmd + Shift + P)를 누르고, ui를 입력한 뒤, 기본 설정을 열어 여러분만의 설정으로 변경해보세요!
프로젝트 준비 단계를 하나씩 진행하며 각 단계를 이해해봅시다.
package.json
node 기반 프로젝트에서 다음으로 봐야 할 것은 package.json 파일입니다. 이 파일을 통해 명령어를 정의하고, 필요한 의존성을 명시하고, 기타 다양한 메타 정보를 설정하게 됩니다. 현재로서는 깊게 들어가지 않고, 핵심적인 부분 두 가지만 짚고 넘어가겠습니다.
- pre-와 post-라는 접두사의 의미와 같이, 우리가 npm start를 실행하면, prestart - start - poststart 순서로 실행됩니다. 이를 고려하여 이전 README.md의 다이어그램을 다시 한 번 살펴보세요. [참고: Life Cycle Scripts ]
- Dependencies와 달리, devDependencies는 개발 시점에만 필요한 의존성을 정의합니다. 따라서, 우리의 Hello, World! DApp은 native Node 서버임을 알 수 있습니다.
npm install
명령을 실행하면 앞서 개발 의존성으로 명시된 0.8.28 버전의 solc 패키지가 설치됩니다. 그리고 package-lock.json 파일과 node_modules 폴더가 생성되는데, package-lock.json은 의존성 패키지 트리를 정의하는데 사용되고, 모든 의존성은 node_modules 폴더 내에 로컬로 다운로드됩니다. 쉽게 말하면, 우리가 라면을 끓이는 프로젝트를 할 떄, 라면과 조리도구를 의존성에 명시하고 구매하면, 각각 라면은 건더기/스프/면, 조리도구는 냄비/젓가락/버너라는 하위 의존성까지 자동적으로 구매하는 것과 동일한 느낌입니다.
아래 이미지의 node_modules 내 폴더 이름을 살펴보면, 우리는 solc만 다운로드 받은 줄 알았는데, 다른 패키지들도 설치된 것을 볼 수 있습니다. 이들 중 대다수는 solc의 의존성으로 명시되어 있고, os-tmpdir 패키지만 tmp 패키지에 대한 의존성으로서 설치된 것을 알 수 있습니다. 우리가 설치한 solc는 Solidity 파일의 컴파일을 도와주는 역할을 맡고 있습니다. 자세한 내용은 다음 포스트에서 다루도록 할게요! 궁금하다면 installing-solidity 참고!
npm start (prestart - start - poststart)
npm start는 Node 기반 프로젝트에서 관습적으로 실행을 의미하는 명령어입니다. 단, Script 생명 주기에 따라 prestart가 먼저 실행되겠네요. 이를 통해 anvil이 실행되고, build 명령이 수행됩니다.
anvil --allow-origin 'http://localhost:3000'
Anvil은 우리가 이전 포스트에서 설치했던 Foundry의 일부입니다. DApp 개발 목적으로 활용되는 이더리움 로컬 노드인데요, 헷갈리지 않아야 하는 부분은 '노드'의 의미가 다르다는 것입니다. 마치, Java와 JavaScript의 차이처럼 이름만 비슷할 뿐 컨셉은 완전 다른데요, Node.js가 브라우저 없이도 JavaScript를 실행할 수 있도록 돕는 런타임이라면, 이더리움 노드는 이더리움 클라이언트 소프트웨어를 실행하는 이더리움 블록체인 네트워크를 구성하는 서버 개체입니다.
좀 더 상세히 들어가면, 블록체인은 독립된 개체들 간의 검증, 합의 그리고 합의 결과의 승인으로 데이터의 무결성을 준수합니다. 이 떄, 어떻게 검증하고, 합의하고, 결과를 받아들일 것인지 이더리움 클라이언트에 정의했습니다. 즉, 이더리움 클라이언트는 프로토콜(Protocol)이고, 이더리움 노드는 해당 프로토콜로 통신 가능한 개별 서버와 유사합니다. 그래서 핵심은 뭐다? 이게 Anvil이라는 서버에 살고 있는 무언가가 결국 Web2와 Web3의 차이를 만든다는 점! 궁금증이 해소되지 않는다면 what-are-nodes-and-clients를 참조하시고, 더 자세한 내용은 이론이 필요한 단계 - 예를 들어, 스마트 컨트랙트 보안 파트에서 다루도록 하겠습니다.
블록체인의 노드들은 기본적으로 표준화된 형태의 JSON-RPC API를 제공합니다. 해당 용어는 세 가지 부분으로 나누어 이해할 수 있어요. JavaScript Object Notation(JSON)은 말 그대로 JavaScript 내에서 Object를 정의할 때 사용하는 문법 또는 표준 형식을 의미하고, 중괄호 { } 안에 키와 값을 콜론 :으로 나누어 재귀적으로 할당할 수 있습니다. 참고 JSON으로 작업하기 일반적으로 Application Programming Interface(API)는 서로 다른 소프트웨어 간의 기능 호출을 위한 창구가 되는데, 앞에 Remote Procedure Call(RPC)이 붙으면 컴퓨터 B에서 컴퓨터 A의 프로세스에 대한 기능 호출이 가능하다는 의미로 확장돼요. 즉, 서로 다른 컴퓨터 간 기능 호출이 가능하다는 것이죠. 세 개를 합치면, 다른 소프트웨어 및 컴퓨터에서 내 컴퓨터의 소프트웨어의 기능을 실행할 수 있는 JSON 형태의 소통 창구 정도로 표현할 수 있겠네요.
다만, 모르는 컴퓨터가 내 IP를 알아내서 갑자기 기능을 실행해선 안 되겠죠? 그래서 브라우저는 Same-origin Policy(SOP)에 기반해서 악의적인 사이트로부터의 스크립트 실행을 막습니다. 호스트가 같아도, 포트가 다르면 다른 출처로 취급되기 떄문에, 우리의 경우에는 3000번 포트를 허용 가능한 출처로 명시하는 것이 바람직합니다. 자세한 내용은 동일 출처 정책을 참고하세요! 정보) Anvil은 기본적으로 모든 호스트로부터의 통신을 허용하니 설정하지 않더라도 동작합니다. 그리고 사실 개발용 노드는 경제적 가치가 없기 때문에 크게 걱정하지 않아도 됩니다. 나중에 CORS 문제가 발생했을 때, 서버의 정책과 클라이언트의 요청을 확인해보세요!
클라이언트가 다른 출처로부터의 자원을 허용하기 위해서는 어떻게 해야 할까요? 단순히 클라이언트가 원한다고 되는 것이 아니고, 서버에서 알맞은 CORS 설정을 해주어야 합니다. 이러한 맥락에서, 실행한 명령어 anvil -- 뒤에 명시된 allow-origin 옵션은 Cross Origin Resource Sharing(CORS, 교차 출처 자원 공유) 방식에 따라 허용하고 싶은 호스트를 정의하기 위한 옵션이에요. remote에서 첫 번쨰 사진처럼 preflight를 전송하여 origin 서버의 정책을 확인하고, 응답 헤더를 받아 그에 맞게 동작합니다. 필요하다면 Dreamhack의 CORS 취약점 강의를 수강하는 것도 이해에 도움이 될 거에요!
마치며
지금까지 스마트 컨트랙트를 빌드하기 위해 solc를 준비하고, 배포하기 위한 노드를 실행하여 RPC-API URL(localhost:8545)을 확보했습니다! 지금은 우리가 직접 개발용 노드를 실행했지만, 나중에는 동작중인 노드의 URL만 얻으면 동일한 작업이 가능합니다. 실행 중인 다양한 이더리움 노드를 찾아볼 수 있는 사이트들이 많은데, ChainList가 대표적입니다. HTTPS 외에도 웹 소켓 프로토콜 wss도 보이죠? 빠르고 잦은 상호작용을 위한 선택이라 생각하면 될 것 같습니다.
다음 시간에는 본격적으로 스마트 컨트랙트가 무엇인지, 빌드하고, 배포하고, 함수를 호출해보도록 하겠습니다! ☺️
'Learn > UPSIDE' 카테고리의 다른 글
5 - 스마트 컨트랙트 함수 호출 (0) | 2025.02.18 |
---|---|
4 - 스마트 컨트랙트 개발 및 배포 (0) | 2025.02.10 |
2 - DApp 개발 환경 셋업 (1) | 2025.02.09 |
1 - 기본 개발 환경 셋업 (0) | 2025.02.05 |
0 - DApp은 어떻게 만들 수 있을까요? (2) | 2025.02.04 |