๐ ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ : ํ์ค์ํ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ ๐ณ๏ธ

์๋ , ์น๊ตฌ๋ค! ์ค๋์ ์ ๋ง ํฅ๋ฏธ์ง์งํ ์ฃผ์ ๋ก ์ฌ๋ฌ๋ถ๊ณผ ํจ๊ป ์ด์ผ๊ธฐ๋ฅผ ๋๋ ๋ณผ ๊ฑฐ์ผ. ๋ฐ๋ก ๋ธ๋ก์ฒด์ธ ๊ธฐ์ ์ ํ์ฉํ ํฌํ ์์คํ ์ ๋ํด์ ๋ง์ด์ง. ๐ค ์ด ์ฃผ์ ๋ ๋จ์ํ ๊ธฐ์ ์ ์ธ ์ด์ผ๊ธฐ๋ฅผ ๋์ด์, ์ฐ๋ฆฌ ์ฌํ์ ๋ฏผ์ฃผ์ฃผ์์ ํฌ๋ช ์ฑ์ ํ ๋จ๊ณ ์ ๊ทธ๋ ์ด๋์ํฌ ์ ์๋ ํ์ ์ ์ธ ์์ด๋์ด์ผ. ๊ทธ๋ผ ์ง๊ธ๋ถํฐ ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ์ ์ธ๊ณ๋ก ํจ๊ป ๋ ๋๋ณผ๊น?
๐ฏ ์ฐ๋ฆฌ์ ๋ชฉํ: ์ด ๊ธ์ ๋ค ์ฝ๊ณ ๋๋ฉด, ๋ํฌ๋ค๋ ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ์ ๊ฐ๋ ์ ์ดํดํ๊ณ , ์ฌ์ง์ด ๊ฐ๋จํ ํ์ค์ํ ์ ํ๋ฆฌ์ผ์ด์ (DApp)์ ๋ง๋ค ์ ์๊ฒ ๋ ๊ฑฐ์ผ. ์ด๋, ์ ๋์ง ์์? ๐
๊ทธ๋ฆฌ๊ณ ์ ๊น! ์ด๋ฐ ํฅ๋ฏธ๋ก์ด ๊ธฐ์ ์ด์ผ๊ธฐ๋ฅผ ๋๋๋ค ๋ณด๋ฉด, ํน์ ์ฌ๋ฌ๋ถ ์ค์์๋ ํ๋ก๊ทธ๋๋ฐ์ด๋ ๋ธ๋ก์ฒด์ธ์ ๊ด์ฌ ์๋ ์น๊ตฌ๋ค์ด ์์ ๊ฒ ๊ฐ์. ๊ทธ๋ฐ ์น๊ตฌ๋ค์๊ฒ ์ฌ๋ฅ๋ท(https://www.jaenung.net)์ด๋ผ๋ ์ฌ๋ฅ ๊ณต์ ํ๋ซํผ์ ์๊ฐํด์ฃผ๊ณ ์ถ์ด. ์ฌ๊ธฐ์๋ ๋ค์ํ ๊ธฐ์ ๊ด๋ จ ์ฌ๋ฅ์ ๋๋๊ณ ๋ฐฐ์ธ ์ ์๋. ๋์ค์ ํ ๋ฒ ๋ค๋ฌ๋ด, ์ด์ฉ๋ฉด ๋ค๊ฐ ๋ฐฐ์ด ๋ธ๋ก์ฒด์ธ ์ง์์ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๋๋ ์ ์๋ ๊ธฐํ๊ฐ ๋ ์ง๋ ๋ชฐ๋ผ!
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์์ํด๋ณผ๊น? ์ค๋น๋์ง? ๊ทธ๋ผ ๊ณ ๊ณ ! ๐
1. ๋ธ๋ก์ฒด์ธ๊ณผ ํฌํ ์์คํ ์ ๋ง๋จ ๐
๋จผ์ , ๋ธ๋ก์ฒด์ธ์ด ๋ญ์ง ๊ฐ๋จํ ์ค๋ช ํด๋ณผ๊ฒ. ๋ธ๋ก์ฒด์ธ์ ์ฝ๊ฒ ๋งํด์ ๋์งํธ ์ฅ๋ถ๋ผ๊ณ ์๊ฐํ๋ฉด ๋ผ. ์ด ์ฅ๋ถ๋ ํ ๊ณณ์ ์ง์ค๋์ด ์์ง ์๊ณ , ๋คํธ์ํฌ์ ์ฐธ์ฌํ๋ ๋ชจ๋ ์ฌ๋๋ค์ด ๋๊ฐ์ ๋ณต์ฌ๋ณธ์ ๊ฐ์ง๊ณ ์์ด. ๊ทธ๋์ ๋๊ตฐ๊ฐ๊ฐ ๋ง์๋๋ก ์ ๋ณด๋ฅผ ๋ฐ๊พธ๋ ค๊ณ ํด๋ ๋ค๋ฅธ ์ฌ๋๋ค์ ์ฅ๋ถ์ ๋ง์ง ์์ ๋ฐ๋ก ๋คํต๋๊ฒ ๋๋ ๊ฑฐ์ง. ๐
๊ทธ๋ผ ์ด๋ฐ ๋ธ๋ก์ฒด์ธ ๊ธฐ์ ์ ํฌํ ์์คํ ์ ์ ์ฉํ๋ฉด ์ด๋ค ์ฅ์ ์ด ์์๊น?
- ๐ ๋ณด์์ฑ ๊ฐํ: ๋ถ์ฐ ์ ์ฅ์ผ๋ก ํดํน์ด ๊ฑฐ์ ๋ถ๊ฐ๋ฅํด์ ธ.
- ๐ ํฌ๋ช ์ฑ ํ๋ณด: ๋ชจ๋ ํฌํ ๊ธฐ๋ก์ด ๊ณต๊ฐ๋์ด ๋๊ตฌ๋ ํ์ธํ ์ ์์ด.
- ๐โโ๏ธ ํจ์จ์ฑ ์ฆ๋: ์๋ํ๋ ์์คํ ์ผ๋ก ๋น ๋ฅธ ๊ฐํ๊ฐ ๊ฐ๋ฅํด์ ธ.
- ๐ฐ ๋น์ฉ ์ ๊ฐ: ์ค์ ๊ด๋ฆฌ ์์คํ ์ด ํ์ ์์ด ์ด์ ๋น์ฉ์ด ์ค์ด๋ค์ด.
- ๐ ์ ๊ทผ์ฑ ํฅ์: ์จ๋ผ์ธ์ผ๋ก ์ด๋์๋ ํฌํ์ ์ฐธ์ฌํ ์ ์์ด.
์, ์ ๋ง ๋๋จํ์ง ์์? ์ด๋ฐ ์ฅ์ ๋ค ๋๋ฌธ์ ์ ์ธ๊ณ์ ์ผ๋ก ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ์ ๋ํ ๊ด์ฌ์ด ๋จ๊ฑฐ์์ง๊ณ ์์ด. ์ฌ์ง์ด ์ผ๋ถ ๊ตญ๊ฐ์์๋ ์ด๋ฏธ ์๋ฒ ์ด์์ ํ๊ณ ์๋. ๐
๐ค ์๊ฐํด๋ณด๊ธฐ: ๋ํฌ๊ฐ ์ด๊ณ ์๋ ๋๋ค๋ ํ๊ต์์ ์ด๋ฐ ๋ธ๋ก์ฒด์ธ ํฌํ ์์คํ ์ ๋์ ํ๋ค๋ฉด ์ด๋ค ์ ์ด ์ข์๊น? ์น๊ตฌ๋ค์ด๋ ๊ฐ์กฑ๋ค๊ณผ ํ๋ฒ ์ด์ผ๊ธฐํด๋ด!
์, ์ด์ ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ์ ๊ธฐ๋ณธ ๊ฐ๋ ์ ์์์ผ๋, ๋ค์ ์น์ ์์๋ ์ด ์์คํ ์ ๊ตฌ์กฐ์ ์๋ ์๋ฆฌ์ ๋ํด ๋ ์์ธํ ์์๋ณผ ๊ฑฐ์ผ. ์ค๋น๋์ง? Let's go! ๐โโ๏ธ๐จ
2. ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ์ ๊ตฌ์กฐ์ ์๋ ์๋ฆฌ ๐๏ธ
์, ์ด์ ์ฐ๋ฆฌ์ ๋ธ๋ก์ฒด์ธ ํฌํ ์์คํ ์ด ์ด๋ป๊ฒ ์๊ฒผ๊ณ ์ด๋ป๊ฒ ๋์๊ฐ๋์ง ์์ธํ ๋ค์ฌ๋ค๋ณผ ๊ฑฐ์ผ. ๋ง์น ๋ ๊ณ ๋ธ๋ก์ ์กฐ๋ฆฝํ๋ฏ์ด, ํ๋์ฉ ์ฐจ๊ทผ์ฐจ๊ทผ ์ดํด๋ณด์๊ณ ! ๐งฑ
2.1 ์์คํ ์ ์ฃผ์ ๊ตฌ์ฑ ์์ ๐งฉ
- ์ค๋งํธ ์ปจํธ๋ํธ (Smart Contract): ํฌํ ๊ท์น๊ณผ ๋ก์ง์ ๋ด๊ณ ์๋ ์๋ํ๋ ๊ณ์ฝ์ด์ผ.
- ๋ถ์ฐ ์์ฅ (Distributed Ledger): ๋ชจ๋ ํฌํ ๊ธฐ๋ก์ด ์ ์ฅ๋๋ ๋ถ์ฐ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ง.
- ๋ ธ๋ (Node): ๋คํธ์ํฌ์ ์ฐธ์ฌํ๋ ์ปดํจํฐ๋ค์ด์ผ. ๊ฐ ๋ ธ๋๋ ์ ์ฒด ๋ธ๋ก์ฒด์ธ์ ๋ณต์ฌ๋ณธ์ ๊ฐ์ง๊ณ ์์ด.
- ํฉ์ ๋ฉ์ปค๋์ฆ (Consensus Mechanism): ๋ ธ๋๋ค์ด ์๋ก์ด ํฌํ ๊ธฐ๋ก์ ์ ํจ์ฑ์ ๊ฒ์ฆํ๋ ๋ฐฉ๋ฒ์ด์ผ.
- ์ฌ์ฉ์ ์ธํฐํ์ด์ค (User Interface): ํฌํ์๋ค์ด ์ฝ๊ฒ ํฌํํ ์ ์๋๋ก ๋ง๋ ์ฑ์ด๋ ์น์ฌ์ดํธ์ผ.
์ด ๊ตฌ์ฑ ์์๋ค์ด ์ด๋ป๊ฒ ์ํธ์์ฉํ๋์ง ๊ทธ๋ฆผ์ผ๋ก ํ๋ฒ ๋ณผ๊น? ๐
์ด๋, ์ด๋ ๊ฒ ๋ณด๋๊น ์ข ๋ ์ดํด๊ฐ ์ ๋์ง? ๐ ๊ฐ ์์๋ค์ด ์๋ก ์ฐ๊ฒฐ๋์ด ํ๋์ ์์คํ ์ ์ด๋ฃจ๊ณ ์๋ ๊ฑธ ๋ณผ ์ ์์ด.
2.2 ์๋ ์๋ฆฌ: ํฌํ ๊ณผ์ ๋จ๊ณ๋ณ ์ค๋ช ๐
์, ์ด์ ์ค์ ๋ก ์ด ์์คํ ์์ ํฌํ๊ฐ ์ด๋ป๊ฒ ์ด๋ฃจ์ด์ง๋์ง ๋จ๊ณ๋ณ๋ก ์ดํด๋ณผ๊ฒ. ๋ง์น ๋ค๊ฐ ์ง์ ํฌํ๋ฅผ ํ๋ ๊ฒ์ฒ๋ผ ์์ํด๋ด!
- ์ ๊ถ์ ๋ฑ๋ก ๐
- ๋จผ์ , ๋์ ์ ์์ ํ์ธํ๊ณ ํฌํ๊ถ์ด ์๋์ง ๊ฒ์ฆํด.
- ํ์ธ์ด ๋๋ฉด, ๋์๊ฒ ๊ณ ์ ํ ๋์งํธ ID๋ฅผ ๋ฐ๊ธํด์ค.
- ํฌํ ์์ฑ ๐
- ์ ๊ฑฐ ๊ด๋ฆฌ์๊ฐ ์ค๋งํธ ์ปจํธ๋ํธ๋ฅผ ํตํด ์๋ก์ด ํฌํ๋ฅผ ์์ฑํด.
- ํฌํ ๊ธฐ๊ฐ, ํ๋ณด์ ๋ชฉ๋ก, ํฌํ ๊ท์น ๋ฑ์ ์ค์ ํด.
- ํฌํ ์งํ โ๏ธ
- ๋๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ํตํด ํฌํ ํ์ด์ง์ ์ ์ํด.
- ๋์ ๋์งํธ ID๋ก ๋ก๊ทธ์ธํ๊ณ , ์ํ๋ ํ๋ณด๋ฅผ ์ ํํด.
- ํฌํ ๋ด์ฉ์ ์ํธํ๋์ด ๋ธ๋ก์ฒด์ธ ๋คํธ์ํฌ๋ก ์ ์ก๋ผ.
- ํฌํ ๊ฒ์ฆ ๐ต๏ธ
- ๋คํธ์ํฌ์ ๋ ธ๋๋ค์ด ๋์ ํฌํ๊ฐ ์ ํจํ์ง ๊ฒ์ฆํด.
- ํฉ์ ๋ฉ์ปค๋์ฆ์ ํตํด ๋ชจ๋ ๋ ธ๋๊ฐ ํฌํ์ ์ ํจ์ฑ์ ๋์ํด์ผ ํด.
- ๋ธ๋ก ์์ฑ ๋ฐ ์ฐ๊ฒฐ ๐
- ์ ํจํ ํฌํ๋ค์ ๋ชจ์ ์๋ก์ด ๋ธ๋ก์ ์์ฑํด.
- ์ด ๋ธ๋ก์ ๊ธฐ์กด์ ๋ธ๋ก์ฒด์ธ์ ์ฐ๊ฒฐ๋์ด ์๊ตฌ์ ์ผ๋ก ์ ์ฅ๋ผ.
- ๊ฒฐ๊ณผ ์ง๊ณ ๐
- ํฌํ ๊ธฐ๊ฐ์ด ๋๋๋ฉด, ์ค๋งํธ ์ปจํธ๋ํธ๊ฐ ์๋์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ์ง๊ณํด.
- ๋ชจ๋ ์ฌ๋์ด ์ค์๊ฐ์ผ๋ก ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์์ด.
์, ์ ๋ง ๋ฉ์ง์ง ์์? ์ด๋ ๊ฒ ํ๋ฉด ํฌํ ๊ณผ์ ์ ๋ชจ๋ ๋จ๊ณ๊ฐ ํฌ๋ช ํ๊ฒ ๊ณต๊ฐ๋๊ณ , ๋๊ตฌ๋ ๋ถ์ ํ ์ ์๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ด. ๐
๐ก ์ฌ๋ฏธ์๋ ์ฌ์ค: ๋ธ๋ก์ฒด์ธ ๊ธฐ์ ์ ์ด์ฉํ ํฌํ ์์คํ ์ ๋จ์ํ ์ ์น ์ ๊ฑฐ๋ฟ๋ง ์๋๋ผ ๋ค์ํ ๋ถ์ผ์์ ํ์ฉ๋ ์ ์์ด. ์๋ฅผ ๋ค์ด, ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์ ์ฌ์ฉ์๋ค์ ์๊ฒฌ์ ๋ชจ์ผ๊ฑฐ๋ ์๋ก์ด ๊ธฐ๋ฅ์ ํฌํ๋ก ๊ฒฐ์ ํ ๋๋ ์ฌ์ฉํ ์ ์์ง. ์ด๋ค ์์ด๋์ด๊ฐ ๋ ์ค๋ฅด๋?
์, ์ด์ ์ฐ๋ฆฌ ๋ธ๋ก์ฒด์ธ ํฌํ ์์คํ ์ ๊ตฌ์กฐ์ ์๋ ์๋ฆฌ์ ๋ํด ์์๋ดค์ด. ๋ค์ ์น์ ์์๋ ์ด๋ฐ ์์คํ ์ ์ค์ ๋ก ์ด๋ป๊ฒ ๊ฐ๋ฐํ๋์ง ์ดํด๋ณผ ๊ฑฐ์ผ. ์ฝ๋ฉ์ ์ข์ํ๋ ์น๊ตฌ๋ค์ ํนํ ๊ธฐ๋ํด๋ ์ข์! ๐ค๐ป
3. ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ๊ฐ๋ฐํ๊ธฐ ๐จโ๐ป
์, ์ด์ ์ง์ง ์ฌ๋ฏธ์๋ ๋ถ๋ถ์ด ์์ด! ์ฐ๋ฆฌ๊ฐ ์ง์ ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ์ ๋ง๋ค์ด๋ณผ ๊ฑฐ์ผ. ๊ฑฑ์ ๋ง, ์ฒ์๋ถํฐ ์๋ฒฝํ ์์คํ ์ ๋ง๋ค ํ์๋ ์์ด. ์ฐ๋ฆฌ๋ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋ฅ์ ๊ฐ์ง ๊ฐ๋จํ ๋ฒ์ ๋ถํฐ ์์ํ ๊ฑฐ์ผ. ๊ทธ๋ผ ์์ํด๋ณผ๊น? ๐
3.1 ๊ฐ๋ฐ ํ๊ฒฝ ์ค์ ๐ ๏ธ
๋จผ์ , ์ฐ๋ฆฌ์ ๊ฐ๋ฐ ํ๊ฒฝ์ ์ค์ ํด์ผ ํด. ์ฌ๊ธฐ์๋ ์ด๋๋ฆฌ์ ๋ธ๋ก์ฒด์ธ์ ์ฌ์ฉํ ๊ฑฐ์ผ. ์๋ํ๋ฉด ์ด๋๋ฆฌ์์ ์ค๋งํธ ์ปจํธ๋ํธ๋ฅผ ์ฝ๊ฒ ๋ง๋ค ์ ์๊ฒ ํด์ฃผ๊ฑฐ๋ .
- Node.js ์ค์น: ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์ ํ๊ฒฝ์ด์ผ. Node.js ๊ณต์ ์ฌ์ดํธ์์ ๋ค์ด๋ก๋ ๋ฐ์ ์ ์์ด.
- Truffle ์ค์น: ์ด๋๋ฆฌ์ ๊ฐ๋ฐ ํ๋ ์์ํฌ์ผ. ํฐ๋ฏธ๋์์ ๋ค์ ๋ช
๋ น์ด๋ก ์ค์นํ ์ ์์ด:
npm install -g truffle
- Ganache ์ค์น: ๋ก์ปฌ ์ด๋๋ฆฌ์ ๋คํธ์ํฌ๋ฅผ ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ๋๊ตฌ์ผ. Ganache ๋ค์ด๋ก๋ ํ์ด์ง์์ ๋ฐ์ ์ ์์ด.
- MetaMask ์ค์น: ๋ธ๋ผ์ฐ์ ํ์ฅ ํ๋ก๊ทธ๋จ์ผ๋ก, ์ด๋๋ฆฌ์ ์ง๊ฐ ์ญํ ์ ํด. MetaMask ๊ณต์ ์ฌ์ดํธ์์ ์ค์นํด.
์ด๋ ๊ฒ ํ๋ฉด ๊ธฐ๋ณธ์ ์ธ ๊ฐ๋ฐ ํ๊ฒฝ ์ค์ ์ ๋์ด์ผ. ์ด๋, ์๊ฐ๋ณด๋ค ๊ฐ๋จํ์ง? ๐
3.2 ํ๋ก์ ํธ ๊ตฌ์กฐ ๋ง๋ค๊ธฐ ๐
์, ์ด์ ์ฐ๋ฆฌ์ ํ๋ก์ ํธ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด๋ณผ ๊ฑฐ์ผ. ํฐ๋ฏธ๋์ ์ด๊ณ ๋ค์ ๋ช ๋ น์ด๋ค์ ์ฐจ๋ก๋ก ์ ๋ ฅํด๋ด:
mkdir blockchain-voting
cd blockchain-voting
truffle init
npm init -y
npm install @openzeppelin/contracts
์ด๋ ๊ฒ ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ์ ํ๋ก์ ํธ ํด๋๊ฐ ๋ง๋ค์ด์ง ๊ฑฐ์ผ:
blockchain-voting/
โโโ contracts/
โโโ migrations/
โโโ test/
โโโ truffle-config.js
โโโ package.json
๊ฐ ํด๋์ ํ์ผ์ ์ญํ ์ ๊ฐ๋จํ ์ค๋ช ํด์ค๊ฒ:
- contracts/: ์ค๋งํธ ์ปจํธ๋ํธ ์ฝ๋๊ฐ ๋ค์ด๊ฐ ํด๋์ผ.
- migrations/: ์ค๋งํธ ์ปจํธ๋ํธ๋ฅผ ๋ฐฐํฌํ๋ ์คํฌ๋ฆฝํธ๊ฐ ๋ค์ด๊ฐ ํด๋์ผ.
- test/: ํ ์คํธ ์ฝ๋๊ฐ ๋ค์ด๊ฐ ํด๋์ผ.
- truffle-config.js: Truffle ์ค์ ํ์ผ์ด์ผ.
- package.json: ํ๋ก์ ํธ ์ ๋ณด์ ์์กด์ฑ ํจํค์ง ๋ชฉ๋ก์ด ๋ค์ด์๋ ํ์ผ์ด์ผ.
3.3 ์ค๋งํธ ์ปจํธ๋ํธ ์์ฑํ๊ธฐ โ๏ธ
์ด์ ์ง์ง ๊ฟ์ผ ํํธ๊ฐ ์์ด! ์ฐ๋ฆฌ์ ํฌํ ์์คํ
ํต์ฌ์ธ ์ค๋งํธ ์ปจํธ๋ํธ๋ฅผ ์์ฑํด๋ณผ ๊ฑฐ์ผ. contracts
ํด๋์ Voting.sol
์ด๋ผ๋ ์ ํ์ผ์ ๋ง๋ค๊ณ , ๋ค์ ์ฝ๋๋ฅผ ์
๋ ฅํด๋ด:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Voting is Ownable {
struct Candidate {
string name;
uint256 voteCount;
}
mapping(address => bool) public voters;
Candidate[] public candidates;
uint256 public votingStart;
uint256 public votingEnd;
event VoteCast(address indexed voter, uint256 candidateIndex);
constructor(string[] memory candidateNames, uint256 durationInMinutes) {
for (uint256 i = 0; i < candidateNames.length; i++) {
candidates.push(Candidate({
name: candidateNames[i],
voteCount: 0
}));
}
votingStart = block.timestamp;
votingEnd = block.timestamp + (durationInMinutes * 1 minutes);
}
function vote(uint256 candidateIndex) external {
require(block.timestamp >= votingStart && block.timestamp < votingEnd, "Voting is not active");
require(!voters[msg.sender], "You have already voted");
require(candidateIndex < candidates.length, "Invalid candidate index");
voters[msg.sender] = true;
candidates[candidateIndex].voteCount++;
emit VoteCast(msg.sender, candidateIndex);
}
function getVoteCount(uint256 candidateIndex) external view returns (uint256) {
require(candidateIndex < candidates.length, "Invalid candidate index");
return candidates[candidateIndex].voteCount;
}
function getCandidateCount() external view returns (uint256) {
return candidates.length;
}
}
์ฐ์, ๊ฝค ๊ธด ์ฝ๋์ง? ๐ ํ๋์ฉ ์ค๋ช ํด์ค๊ฒ:
Candidate
๊ตฌ์กฐ์ฒด๋ ํ๋ณด์์ ์ด๋ฆ๊ณผ ๋ํ ์๋ฅผ ์ ์ฅํด.voters
๋งคํ์ ๋๊ฐ ํฌํํ๋์ง ๊ธฐ๋กํด.candidates
๋ฐฐ์ด์ ๋ชจ๋ ํ๋ณด์ ์ ๋ณด๋ฅผ ์ ์ฅํด.votingStart
์votingEnd
๋ ํฌํ ๊ธฐ๊ฐ์ ์ ์ํด.vote
ํจ์๋ฅผ ํตํด ์ ๊ถ์๊ฐ ํฌํํ ์ ์์ด.getVoteCount
์getCandidateCount
ํจ์๋ก ํฌํ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์์ด.
์ด ์ฝ๋๋ ๊ธฐ๋ณธ์ ์ธ ํฌํ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ์์ด. ๋ฌผ๋ก ์ค์ ์์คํ ์์๋ ๋ ๋ง์ ๋ณด์ ์ฅ์น์ ๊ธฐ๋ฅ์ด ํ์ํ๊ฒ ์ง๋ง, ์ฐ๋ฆฌ์ ํ์ต ๋ชฉ์ ์ผ๋ก๋ ์ถฉ๋ถํด! ๐
3.4 ์ค๋งํธ ์ปจํธ๋ํธ ๋ฐฐํฌํ๊ธฐ ๐
์, ์ด์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ์ค๋งํธ ์ปจํธ๋ํธ๋ฅผ ๋ธ๋ก์ฒด์ธ์ ๋ฐฐํฌํด๋ณผ ๊ฑฐ์ผ. migrations
ํด๋์ 2_deploy_voting.js
ํ์ผ์ ๋ง๋ค๊ณ ๋ค์ ์ฝ๋๋ฅผ ์
๋ ฅํด:
const Voting = artifacts.require("Voting");
module.exports = function (deployer) {
const candidateNames = ["Alice", "Bob", "Charlie"];
const votingDuration = 60; // 60 minutes
deployer.deploy(Voting, candidateNames, votingDuration);
};
์ด์ ํฐ๋ฏธ๋์์ ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํด ์ปจํธ๋ํธ๋ฅผ ๋ฐฐํฌํด๋ด:
truffle migrate --network development
์, ์ถํํด! ๐ ์ด์ ๋์ ์ฒซ ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ์ด ๋ก์ปฌ ๋ธ๋ก์ฒด์ธ์ ๋ฐฐํฌ๋์ด!
3.5 ํ๋ก ํธ์๋ ๊ฐ๋ฐํ๊ธฐ ๐ฅ๏ธ
๋ง์ง๋ง์ผ๋ก, ์ฌ์ฉ์๋ค์ด ์ฝ๊ฒ ํฌํํ ์ ์๋๋ก ๊ฐ๋จํ ์น ์ธํฐํ์ด์ค๋ฅผ ๋ง๋ค์ด๋ณผ๊ฒ. ์ฌ๊ธฐ์๋ ๊ฐ๋จํ HTML, JavaScript, ๊ทธ๋ฆฌ๊ณ Web3.js๋ฅผ ์ฌ์ฉํ ๊ฑฐ์ผ.
ํ๋ก์ ํธ ๋ฃจํธ์ index.html
ํ์ผ์ ๋ง๋ค๊ณ ๋ค์ ์ฝ๋๋ฅผ ์
๋ ฅํด:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blockchain Voting</title>
<script src="https://cdn.jsdelivr.net/npm/web3@1.5.2/dist/web3.min.js"></script>
</head>
<body>
<h1>Blockchain Voting System</h1>
<div id="candidates"></div>
<button onclick="vote()">Vote</button>
<div id="result"></div>
<script>
let web3;
let votingContract;
async function init() {
if (typeof window.ethereum !== 'undefined') {
web3 = new Web3(window.ethereum);
try {
await window.ethereum.enable();
const networkId = await web3.eth.net.getId();
const deployedNetwork = Voting.networks[networkId];
votingContract = new web3.eth.Contract(
Voting.abi,
deployedNetwork && deployedNetwork.address,
);
loadCandidates();
} catch (error) {
console.error("User denied account access")
}
} else {
console.log('Please install MetaMask!');
}
}
async function loadCandidates() {
const candidateCount = await votingContract.methods.getCandidateCount().call();
const candidatesDiv = document.getElementById('candidates');
for (let i = 0; i < candidateCount; i++) {
const candidate = await votingContract.methods.candidates(i).call();
const radio = document.createElement('input');
radio.type = 'radio';
radio.name = 'candidate';
radio.value = i;
const label = document.createElement('label');
label.appendChild(radio);
label.append(candidate.name);
candidatesDiv.appendChild(label);
}
}
async function vote() {
const selectedCandidate = document.querySelector('input[name="candidate"]:checked').value;
const accounts = await web3.eth.getAccounts();
await votingContract.methods.vote(selectedCandidate).send({ from: accounts[0] });
alert('Vote cast successfully!');
showResults();
}
async function showResults() {
const candidateCount = await votingContract.methods.getCandidateCount().call();
const resultDiv = document.getElementById('result');
resultDiv.innerHTML = '<h2>Results:</h2>';
for (let i = 0; i < candidateCount; i++) {
const candidate = await votingContract.methods.candidates(i).call();
const voteCount = await votingContract.methods.getVoteCount(i).call();
resultDiv.innerHTML += `<p>${candidate.name}: ${voteCount } votes</p>`;
}
}
window.addEventListener('load', init);
</script>
</body>
</html>
์ด HTML ํ์ผ์ ๊ฐ๋จํ ํฌํ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํด. ์ฌ์ฉ์๋ ํ๋ณด๋ฅผ ์ ํํ๊ณ ํฌํํ ์ ์์ผ๋ฉฐ, ๊ฒฐ๊ณผ๋ ๋ณผ ์ ์์ด. Web3.js๋ฅผ ์ฌ์ฉํด์ ์ฐ๋ฆฌ์ ์ค๋งํธ ์ปจํธ๋ํธ์ ์ํธ์์ฉํ๊ณ ์์ง.
์, ์ด์ ์ฐ๋ฆฌ์ ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ์ด ์์ฑ๋์ด! ๐ ๋ฌผ๋ก ์ด๊ฑด ์์ฃผ ๊ธฐ๋ณธ์ ์ธ ๋ฒ์ ์ด๊ณ , ์ค์ ์ฌ์ฉ์ ์ํด์๋ ๋ ๋ง์ ๊ธฐ๋ฅ๊ณผ ๋ณด์ ์กฐ์น๊ฐ ํ์ํ๊ฒ ์ง๋ง, ๋ธ๋ก์ฒด์ธ ํฌํ ์์คํ ์ ๊ธฐ๋ณธ ๊ฐ๋ ์ ์ดํดํ๋ ๋ฐ๋ ์ถฉ๋ถํด.
๐ ๋์ ๊ณผ์ : ์ด ๊ธฐ๋ณธ ๋ฒ์ ์ ์ด๋ค ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ฉด ์ข์๊น? ์๋ฅผ ๋ค์ด, ํฌํ ๊ธฐ๊ฐ์ ํ์ํ๊ฑฐ๋, ํฌํ์์ ์๊ฒฉ์ ํ์ธํ๋ ๊ธฐ๋ฅ์ ์ด๋จ๊น? ํ๋ฒ ์๊ฐํด๋ณด๊ณ ๊ตฌํํด๋ด!
์ฌ๊ธฐ๊น์ง ๋ฐ๋ผ์๋ค๋ฉด ์ ๋ง ๋๋จํด! ๐ ๋๋ ์ด์ ๋ธ๋ก์ฒด์ธ ๊ธฐ๋ฐ ํฌํ ์์คํ ์ ๊ธฐ๋ณธ์ ์ดํดํ๊ณ , ์ฌ์ง์ด ๊ฐ๋จํ ๋ฒ์ ์ ์ง์ ๋ง๋ค์ด๋ดค์ด. ์ด๋ฐ ๊ฒฝํ์ ์์ผ๋ก ๋ ๋ณต์กํ ๋ธ๋ก์ฒด์ธ ํ๋ก์ ํธ๋ฅผ ํ ๋ ํฐ ๋์์ด ๋ ๊ฑฐ์ผ.
๊ทธ๋ฆฌ๊ณ ๊ธฐ์ตํด, ์ด๋ฐ ๊ธฐ์ ์ ๊ณ์ ๋ฐ์ ํ๊ณ ์์ด. ๋ง์ฝ ๋ ๊น์ด ๊ณต๋ถํ๊ณ ์ถ๋ค๋ฉด, ์ฌ๋ฅ๋ท(https://www.jaenung.net) ๊ฐ์ ํ๋ซํผ์์ ๊ด๋ จ ๊ฐ์๋ฅผ ์ฐพ์๋ณด๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์ผ. ๊ฑฐ๊ธฐ์ ์ต์ ๋ธ๋ก์ฒด์ธ ๊ธฐ์ ์ ๋ํด ๋ฐฐ์ฐ๊ฑฐ๋, ์ฌ์ง์ด ๋ค๊ฐ ๋ฐฐ์ด ๊ฑธ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ๊ฐ๋ฅด์น ์๋ ์์ด!
๋ธ๋ก์ฒด์ธ ๊ธฐ์ ์ ํฌํ ์์คํ ์ธ์๋ ๋ค์ํ ๋ถ์ผ์์ ํ์ ์ ์ผ์ผํค๊ณ ์์ด. ๊ธ์ต, ๊ณต๊ธ๋ง ๊ด๋ฆฌ, ๋์งํธ ์ ์ ํ์ธ ๋ฑ ์ ๋ง ๋ง์ ๊ณณ์์ ์ฌ์ฉ๋๊ณ ์์ง. ์์ผ๋ก ์ด๋ค ๋ถ์ผ์์ ๋ธ๋ก์ฒด์ธ์ ํ์ฉํ ์ ์์์ง, ํ๋ฒ ์์ํด๋ด. ์ด์ฉ๋ฉด ๋ค๊ฐ ๊ทธ ํ์ ์ ์ฃผ์ธ๊ณต์ด ๋ ์๋ ์์ด!
์, ์ด์ ์ฐ๋ฆฌ์ ๋ธ๋ก์ฒด์ธ ํฌํ ์์คํ ์ฌํ์ด ๋๋ฌ์ด. ์ด๋ ์ จ๋์? ์ฌ๋ฏธ์์๊ธธ ๋ฐ๋ผ์! ๐ ์์ผ๋ก๋ ๊ณ์ํด์ ์๋ก์ด ๊ธฐ์ ์ ๋ฐฐ์ฐ๊ณ ๋์ ํ๋ ๊ฑธ ์์ง ๋ง์ธ์. ๊ธฐ์ ์ ์ธ๊ณ๋ ๋์์ด ๋๊ณ ํฅ๋ฏธ์ง์งํ๋๊น์. ํ์ดํ ! ๐
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ