가자!
어딜..?
나도여행을 가고 싶지만
여기서 말하는 Go는 프로그래밍 언어다.
위에 굉장히 귀엽게 생긴 캐릭터가 Go 언어의 마스코트 캐릭터다.
캐릭터 마저 귀여운데 무려 Google 에서 운영 및 개발을 담당하고 있으며,
Stack Overflow에서 2020년에 조사한 개발자가 배우고 싶은 언어 3위를 기록하였다.
세상에 나온 지 10년이 조금 넘은 지금, Go 언어는 컨테이너와 클라우드 환경 구축에 없어선 안될 도커(Docker) 및 쿠버네티스(Kubernetes)를 비롯해 이더리움(Ethereum) 블록체인의 메인 클라이언트 Geth의 개발에 사용되는 등 성능과 안정성을 인정받으며 시장 입지를 다지고 있다.
왜 Go 일까?
한번 그 이유와 함께 간단한 문법을 알아보자.
2009년 11월, 구글은 Go 언어를 처음 발표한다.
이후, 2012년 3월에 정식 발표되었다.
C++의 복잡함이 싫었던 로버트 그리즈머, 롭 파이크, 케네스 톰슨이 디자인 하였으며, 지금까지도 패키지에 무엇을 포함할지는 세사람의 만장일치 합의가 있어야지만 이뤄질 수 있다고 한다.
Go 이름이 이름인 만큼, Golang(고랭, 나시고랭 아님) 이라고 검색하거나 발음하는 경우가 많다.
Go 언어 사용자들을 Gopher(고퍼) 라고 부르며, 고퍼들을 위한 연례행사 Gophercon(고퍼콘)이 세계 각국에서 열리고 있다고 한다.
매니아층을 위한 문화가 잘 이루어져 있다는 점에서 이런 문화를 좋아하는 나에게는 괜히 더 재밌어 보인다.
장점은 무엇이 있을까?
일단 C, C++ 과 비슷하지만 굉장히 간결하고 빠르다.
키워드는 25개만을 가지고 있으며, 복잡한 요소들을 최대한 줄이고 간결하게 만들어 졌다.
컴파일 언어 임에도 불구하고 컴파일러가 굉장히 빨라 인터프리터 언어처럼 사용할 수 있다는 것도 큰 특징이다.
접근하기 어렵지도 않고, 코드도 간결하고, 컴파일 언어답게 높은 성능을 낼 수 있다는 것.
이 세가지가 Golang 에서 가장 큰 장점으로 꼽히는 듯 하다.
Golang 을 설치하기 위해 위 사이트에 접속하면, 다양한 운영체제를 위한 다운로드 방식이 친절하게 안내 되어있다.
혹시나 설치하고, 셋팅하기 귀찮다면 아래 링크를 접속해보자.
간단한 문법을 바로 활용할 수 있도록 제공한다.
https://replit.com/languages/go
나는 IntelliJ IDEA를 주로 사용하기에,
IntelliJ에서 제공하는 Go Plugin을 설치 후 Go 언어로 새로운 프로젝트를 만들어 주었다.
설치가 완료 되었다면, 아래 구문을 치고 실행해보자.
package main
import "fmt"
func main() {
fmt.Println("Hello world!")
}
결과창에 Hello World! 가 정상적으로 출력되는 것을 볼수 있다!
항상 새로운 언어를 배우는 것은 여기까지가 가장 재미있다.
var i int = 0
위와 같이 var 키워드를 통해 변수를 선언하고,
const name string = "woong"
위와 같이 const 키워드를 통해 상수를 선언한다.
if i == 1 {
println("One")
} else if i == 2 {
println("Two")
} else {
println("Other")
}
개발자라면 언어는 많은 사이트에서 공부할 수 있을 것 같다.
더 보고 여기 를 들어가서 한번 훑어 보자.
크게 어렵지도 않고.. 굳이 이걸 하나하나 다 보기 쓰기보단 재미있는걸 실습하기로 마음을 바꾸었다.
이더리움의 메인 클라이언트 개발을 담당하고, 많은 블록체인 기술이 C/C++로 개발되어 있는데 Golang은 C/C++에서 발전한 만큼 블록체인 기술에서도 많이 이용할 수 있는 듯 하다.
이곳에 잘 번역되어있는 Building Blockchain in Go 시리즈의 한국어 번역본을 참고하여 따라해 보았다.
블록체인에서 블록이란 가치있는 정보를 저장하는 데이터 구조 이다.
비트코인 등에서 사용되는 블록은 굉장히 많은 정보를 포함하고 있지만,
이곳에서는 간단한 버전의 블록을 구현할 것이다.
type Block struct {
Timestamp int64
Data []byte
PrevBlockHash []byte
Hash []byte
}
Timestamp는 현재 시간의 타임스탬프 (블록 생성 시간), Data는 블록에 포함된 실제 가치를 지닌 정보, PrevBlockHash는 이전 블록의 해시값 그리고 Hash는 블록의 해시값이다.
해시 계산법은 블록체인에서 아주 중요한 부분이며, 블록체인을 안전하게 만드는 핵심 기능이다.
해시 계산은 계산적으로 아주 어려운 작업이며, 빠른 컴퓨터에서조차 시간이 다소 걸리는 작업이다 (이게 바로 사람들이 비트코인을 채굴하기 위해 강력한 GPU를 구매하는 이유이다).
이는 의도적인 설계로, 새로운 블록을 추가하기 어렵게 만들어 블록이 추가된 후에 블록의 수정을 방지하기 위함이다.
블록을 구성하는 필드들을 하나로 이은 뒤 이어진 문자열에 대해 SHA-256 해시를 계산하는 SetHash 함수를 만들어 보자.
func (b *Block) SetHash() {
timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
hash := sha256.Sum256(headers)
b.Hash = hash[:]
}
:= // var 선언 대신 사용 (func 내에서만 사용)
strconv // 문자열 변환을 위한 패키지
sha256 // sha256 해시 알고리즘을 통해 변환
sha256.Sum256 // 데이터의 sha256 체크섬 반환
* // 포인터를 인자로 받을 때 사용 (위 예시에서는 Block b 변수의 메모리 주소를 인자로 받음)
다음으로는 데이터와 이전 해시값을 받아, 새로운 블록을 생성하는 NewBlock 함수를 만들어 보자.
func NewBlock(data string, prevBlockHash []byte) *Block {
block := &Block{time.Now().Unix(), []byte(data), prevBlockHash, []byte{}}
block.SetHash()
return block
}
& // 포인터를 인자로 선언할 때 사용
SetHash 메서드를 통해 블록을 구성하는 필드들을 하나로 이은 뒤 이어진 문자열에 대해 SHA-256 해시를 계산할 것이다.
이제 블록체인을 구현해 보자.
본질적으로 블록체인은 특정한 구조를 가진 데이터베이스일 뿐이며 순서가 지정된 링크드 리스트이다.
즉, 블록은 삽입 순서대로 저장되며 각 블록은 이전 블록과 연결된다.
이러한 구조 덕분에 최신 블록을 빠르게 가져올 수 있고 해시로 블록을 (효율적으로) 검색할 수 있다.
Go에서는 배열과 맵을 활용해 이 구조를 구현할 수 있다.
배열은 정렬된 해시를 유지하고 맵은 해시-블록쌍을 유지한다.
그러나 지금 당장은 해시 검색 기능이 필요하지 않기 때문에 프로토타입 구현에서는 배열만 사용할 것이다.
type Blockchain struct {
blocks []*Block
}
이제는 블록 추가 기능이다.
func (bc *BlockChain) AddBlock(data string) {
prevBlock := bc.blocks[len(bc.blocks)-1]
newBlock := NewBlock(data, prevBlock.Hash)
bc.blocks = append(bc.blocks, newBlock)
}
새로운 블록을 추가하기 위해선 이전 블록이 필요하다.
하지만 우리의 블록체인에는 아무 블록도 존재하지 않기에 첫번째 블록을 생성해 주어야 한다.
블록체인의 첫 번째 블록은 제네시스 블록 이라고 하며, 이 블록을 생성하는 함수를 만들어 주자.
func NewGenesisBlock() *Block {
return NewBlock("Genesis Block", []byte{})
}
이제 제네시스 블록(첫번째 블록)이 생겼을 테니, 블록체인을 만드는 함수를 만들어 보자.
func NewBlockchain() *Blockchain {
return &Blockchain{[]*Block{NewGenesisBlock()}}
}
func main() {
bc := NewBlockchain() // bc 라는 변수 안에 NewBlockchain 함수를 통해 블록체인 생성
bc.AddBlock("My name is Ted")
bc.AddBlock("This is my first BlockChain")
bc.AddBlock("Here is Softsquared")
bc.AddBlock("우리 모두 화이팅!")
// AddBlock 을 통해 블록체인에 데이터 생성
for _, block := range bc.blocks {
fmt.Printf("Prev. hash: %x\n", block.PrevBlockHash)
fmt.Printf("Data: %s\n", block.Data)
fmt.Printf("Hash: %x\n", block.Hash)
fmt.Println()
}
}
// for 인덱스, 요소값 := range 컬렉션 - 컬렉션 요소를 하나씩 리턴하여 그 요소의 위치인덱스 와 요소 값을 for 키워드 다음의 2개의 변수에 각각 할당
// 여기선 인덱스 값이 쓰이지 않기 때문에 _ 로 표시
// Golang에선 쓰이지 않는 변수가 있으면 오류가 발생하기 때문에 _ 로 표시 해야함
main 함수를 실행해보자.
나만의 데이터가 담긴 첫 블록체인이 탄생하였다!
실제 블록체인은 이보다 훨씬 복잡하겠지만, 간단한 작업을 통해 블록체인이 무엇인지 맛정도는 볼수 있지 않았나 싶다.
앞으로 이것을 기반으로 한 디벨롭 하는 공부를 시간이 생기면 조금 더 해보고 싶다.
오늘 작성한 내용은 참고한 Github를 거의 그대로 따라 한거라서 누구든지 이 블로그를 보면 잘 따라하고 이해가 빠를 것 같다.
좋은글 잘봤읍니다,,, ^^