본문으로 바로가기

[바미] Go언어 소개

category 프로그래밍(Basic)/Golang 2020. 12. 16. 15:46
728x90
반응형
728x170

이 글은 주기적으로 수정하고 있습니다. 글을 읽으실 때 참고하시기 바랍니다.

1. Go언어의 탄생


“Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.”

 

이 문구는 golang의 정식 웹사이트에서 golang을 설명할 때 사용한 문구인데 해석하면

Go는 간결하고 신뢰성 있으며 효율적인 소프트웨어를 손쉽게 만들기 위한 오픈소스 프로그래밍 언어이다. 라는 의미입니다.

 

Go언어는 2009년 구글이 개발한 프로그래밍 언어로 빠른 성능, 안정성, 편의성, 쉬운 프로그래밍을 목표로 한 범용

프로그래밍 언어 입니다. 이는 C나 자바와 같이 다양한 소프트웨어 개발에 사용된다는 의미입니다.

 

 

 

다음은 Go언어 개발에 참여했던 개발자들입니다. 나중의 인터뷰에서 언어 설계자 3명 모두 자신들이 C++의 복잡성을 싫어하며 이로 인해 새로운 언어를 설계하는 계기가 되었다고 언급하였고, 현재도 어떠한 패키지에 무엇을 포함할지는 이 세 사람이 만장일치로 합의해야 이루어진다고 합니다.

 

2. Go언어의 특징


 

그 다음은 Go언어의 특징입니다. 많은 특징들을 가지고 있지만 아래의 4가지만 살펴보려고 합니다.

  • 컴파일 언어
  • 가비지 컬렉션
  • 동시성
  • 문법

첫 번째는 컴파일언어라는 점입니다.


컴파일 언어와 인터프리터 언어의 차이로는 이러한 차이가 있는데 Go는 컴파일 언어지만 C, C++과 달리 헤더 파일을 없애고, 소스코드를 패키지화하여 변경된 부분만 컴파일하여 컴파일 속도를 줄였습니다. 그래서 컴파일 언어의 성능을 가지면서도 빠른 컴파일 속도로 생산성을 높여 인터프리터 언어 처럼 사용할 수 있게 되었습니다.

 

컴파일 언어 : 기계어로 번역해 실행파일로 만드는 언어.
Ex) C, C++, C#, Go

인터프리터 언어: 기계어로 변환하는 과정 없이 한줄 한줄 해석하여 바로 명령어를 실행하는 언어.
Ex)R, Python, Ruby

 

go run main.go

로 보통 실행을 하는데 이는 컴파일을 하지 않고 인터프리터 언어처럼 사용하는 방법으로

보통 테스트 시 많이 사용합니다. 예를 들면 내부적으로 프로그램을 돌릴 때 라던지 주로 사용하죠.

Go의 빠른 속도를 느끼시려면 컴파일하셔서 사용을 하셔야 합니다.

 

go bulid

./main.go

 

를 통해 컴파일을 해주신 뒤에 ./main.go문구를 사용하여 exe파일을 실행시켜 주시면 됩니다.

저 같은 경우 이 부분을 깨닫지 못했을 때 무식하게 개발 서버에 띄어 올릴 때도 'go run main.go'를 사용하여 실행시켰는데 이 글을 보시는 분들은 저와 같은 실수를 하지 않길 바랍니다. (저 방법이 틀렸다는게 아니라 컴파일을 사용하여 쓰지 않으면 Go를 쓰는 이유는 없기 때문입니다.)

 

인터프리터 언어 중 Javascript 와 컴파일 언어 중 Go 사용 시 서버에 올릴 때 차이점이라면 Javascript는 코드까지

주어야 하는데 Go는 컴파일 된 exe파일만 넘겨주면 되서 코드를 보여주지 않아도 됩니다.

 

우리에겐 보여주고 싶지 않은 부끄러운 그런게 있잖아요....ㅎㅎㅎ...

 

"역컴파일러로 코드를 유출 할 수 있지 않냐?" 하실 수 있는데 Java나 Javascript 같은 경우 역컴파일러 했을 시 주석까지도 복구 되서 설령 코드들이 제대로 복구가 안되더라도 주석으로 짜맞추기가 가능합니다.

하지만 Go와 같은 컴파일러 언어들은 주석은 복구가 되지 않습니다.

 

두 번째는 가비지 컬렉션입니다.


C언어 같은 경우 메모리를 할당하면 반드시 해제하는 과정이 필요하며, 이 과정을 제대로 처리해주지 않으면 메모리만 차지하게 되고, 부족해져 프로그램이 종료되는 상황인 메모리 릭 현상이 발생하게 되는 반면에 Go는 이 것을 가비지 컬렉터가 이 부분을 처리해주기 때문에 메모리 릭 현상에 대해 대비 할 수 있습니다.

(하지만 가비지 컬렉션이 있다고 해서 메모리 릭 현상이 발생 안하는건 아닙니다!)

가비지 컬렉션 : 메모리 관리 기법 중의 하나로, 개발자가 동적으로 할당한 메모리 영역 중 더 이상 쓰이지 않는 영역자동으로  찾아내어 해제하는 기능.

가상 머신 위에서 실행되는 Java와 다르게 가상머신 없이도 가비지 컬렉션을 할 수 있다는 것이 장점.

추가적으로 가비지 컬렉션으로 인한 단점이 있는데 세밀성, 실시간성의 성향을 가진 프로그램 개발에는 독이 될 수 있습니다. 가비지 컬렉션이 프로그램이 실행되는 중간중간 돌면서 움직이는데 이 때의 시간이 최근까지 본 Go언어 스펙에선 50㎳로 알고 있습니다. 

 

만약에 어떤 날아오는 물체를 맞추는 미사일 시스템에 들어가는 개발 언어가 가비지 컬렉션이 있다고 가정해봅시다.

미사일이 그 물체를 맞추려고 하는데 50㎳가 가다가 멈춥니다. 그 물체를 정확히 맞출 수 있을까요? 

 

그렇기 때문에 가비지 컬렉션이 있는 언어가 좋은거고, 가비지 컬렉션 언어가 없는 언어는 안 좋은 언어가 아닙니다.

 

세 번째는 동시성입니다.


동시 처리의 논리적인 개념인데 Go에서 고루틴과 고루틴간 메시지를 주고 받을 수 있는

채널을 통해 동시에 여러개를 처리하는 병렬 프로그래밍 작성을 하기가 쉽습니다.

운영체제의 커널에서 제공하는 일반적인 스레드는 많이 생성할수록 부담이 커지지만, 고루틴은 수천개를 한 번에 생성해도 스레드에 비해 무리없이 처리합니다. 고루틴에 대해서는 다음에 더 알아보도록 하겠습니다.

동시성 : 동시 처리의 논리적인 개념.

단일 코어에서 스레드를 여러 개 생성하면 동시에 실행되는 것이 아니라 실제로는 스레드 여러 개가 시간을 쪼개어 순차적(시분할)으로 실행된다.

네 번째는 Go언어만의 문법입니다.


1. 사라진 세미콜론

  package main

  import (
      "fmt"
  )

  func main() {
      fmt.Println("Hello World")
  }

첫 번째로 세미콜론이 사라졌습니다. Go컴파일러가 컴파일을 할 때 세미콜론을 자동으로 달아주는데 이 세미콜론을 제외한 선택 때문에 제약이 하나 생겼는데

if(x) { // 가능
  todo
}

if(x) // 불가능
{
  todo
}

이렇게 한칸 띄고 괄호를 넣는 스타일의 방법을 사용하지 못합니다.

흔히 개발자들은 이런 형태의 개발자들로 나뉜다는 밈이 있는데Go에서는 강제로 위의 스타일을 따라야 합니다.

 

 

 

 

2. 변수 선언

  var a int = 1
  var b [10] int

세 번째로 변수 선언 방법입니다. 보통 이런식으로 선언을 하지만

a := 1

위와 같이 변수를 선언함과 동시에 값을 할당하는 방법도 있습니다. 이를 선언대입문이라고 하는데

1이 들어갔기 때문에a가 int타입의 변수라는 것으로 타입추론이 됩니다.

 

자동으로 초기화 되는 값들은 다음과 같습니다.

또한 타입마다 초기화 값이 존재합니다. int는 0, String은 "", pointer는 nil, float는 0.0, bool은 false입니다.

 

안드로이드나JS같은 경우엔 사용하지 않는 패키지를 따로 표시하여 프로그램을 실행시키지만Go같은 경우엔 사용하는 개발환경마다 다르다는 것을 알 수 있고,사용하지 않는 변수를 선언 시 에러가 납니다.

 

3. 사용하지 않는 패키지 import시.

안드로이드나JS같은 경우엔 사용하지 않는 패키지를 따로 표시하여 프로그램을 실행시키지만Go같은 경우엔 사용하는 개발환경마다 다르다는 것을 알 수 있고,사용하지 않는 변수를 선언 시 에러가 납니다.

예를 들어

  package main

  import (
    "fmt"
    "reflect"
  )

  func main() {

    a := 1

    fmt.Println(a)

  }

reflect패키지는 변수의 타입을 알고 싶을 때 사용하는 패키지인데 Android나 javascript 같은 경우 사용하지 않는 패키지에 따로 표시하지만 VScode의 경우엔 사용하지 않는 패키지를 없애주지만

LiteIDE라는 Tool 같은 경우엔 imported and not used:"reflect"라는 컴파일 에러가 뜹니다.

 

또한 사용하지 않는 변수를 사용했을 때 아래와 같이 a,b를 선언했을 때 b를 사용하지 않으면

오류표시가 뜨는 것을 확인할 수 있는데

에러 명은 다음과 같습니다.

 

이로써 개발환경마다 다르다는 것을 알 수 있고, 사용하지 않는 변수를 선언 시 에러가 나는 것을 알 수 있습니다.

4. 반복문

Go에서는 for문으로만 반복문을 사용 할 수 있습니다.

(실제로 for문으로만 반복문을 해결 할 수 있다는 것을 증명을 했다더군요.)

  for i := 0; i < 100; i++ {

  }

대신 이와 같은 형식으로while문처럼 사용 할 수 있게 했고, for문으로 무한 루프를 걸 수 있게 하여 이 무한루프를 빠져나올 때는break를 사용합니다.

  for n < 100 {
    todo...

    break
  }

5. 접근 제어

객체지향 프로그래밍 언어에서 함수의 접근 제어하는 public, privete을 쓴다 할 때

  class codesk {
    private a
    public b

    public void f1() {
    }

    private void f2() {
    }

  }

이런식으로 쓰였는데 Go언어에서는 객체지향 프로그래밍 언어는 아니지만 public, private를 쓸 수 있습니다.

func A1() { // public
    todos...
}

func a2() { // private
    todos...
}

함수의 이름이 대문자로 시작하면 public, 함수의 이름이 소문자로 시작하면 private입니다.

6. Try-Catch가 없다.

Go는 error타입의 nil 검사를 통해 확인해야 합니다. 기존 try-catch가 있는 구문은 위와 같이 표현합니다.

 

 

 

반면에 Go에서는 대부분의 함수들의 로직 뒤에 에러도 반환하게 되어 있어 항상 에러를 반환하여 위의 코드처럼 계속 에러를 체크해야합니다.

 

 

그렇게 되면 코드가 길어지는 일이 발생하게 되지만 따로 에러처리를 해주는 함수를 만들어 놓으면 이 문제는 해결됩니다.

 

3. Go언어의 장점


그 다음은 Go언어 장점입니다. 많은 장점이 있지만 4개지만 알아보려 합니다.

  • Go 루틴
  • 상대적으로 적은 키워드.
  • 풍부한 기본 모듈을 제공.
  • 신뢰할 수 있는 제작사, 대기업들의 사용.

 

첫 번째는 Go루틴을 가지고 있다는 점입니다.


Go루틴 : Go 프로그램에서 동시에 실행할 수 있는 최소 단위로 스레드와 비슷한 개념.

 

java, javascript에는 스레드가 있다면 Go에서는 Go루틴을 가지고 있다고 생각하시면 됩니다스레드라는 것을 명시적으로 주지 않고 고루틴을 생성하면 알아서 스레드를 생성해주고 적절한 스레드에 고루틴을 할당합니다

 

 

 

 

차이점이 있다면 스레드를 생성하는데 필요한 메모리가 1MB이지만 Go루틴은 2KB밖에 필요하지 않아 스레드보다 적은 용량으로 동작시킬 수 있고, 여러 개의 고루틴이 하나의 스레드에서 동작하며, 메모리를 공유하는 방식이 아니라

일종의 pipe인 채널로 데이터를 공유하고 실행 순서를 제어하고, Go루틴 사이에 커뮤니케이션을 전부 채널을 통해서

하기 때문에 동기화 문제를 신경 쓰지 않아도 됩니다.

 

그 덕에 스레드보다 시작 시간이 빠르고, 내장된 기본 요소로 안전하게 통신할 수 있게 되며 효율성이 좋아지게

됩니다.

 

Go에서 대표적인 고루틴 이용 예시는 net/http입니다. net/http는 Go에 있는 라이브러리인데 net/http는 고루틴을 이용한 동시성 기능을 자체적으로 지원하는데, 만약 서버로 유입된 각각의 요청들이 자동적으로 각자의 고루틴에서 동작하게 되며, go런타임이 설정한 논리 프로세스의 개수에 따라 자동적으로 Go루틴을 실행하게 된다고 합니다.

 

두 번째는 상대적으로 적은 키워드를 가지고 있다는 점입니다.


 

 

프로그래밍 언어에 대한 경험이 있다면 chan, defer, fallthrough 등을 제외한 키워드들의 이름과 용도를 미루어 짐작할 수 있을 것입니다. 키워드가 적은 만큼 복잡한 준비작업 없이 쉽게 시작 할 수 있으며, 몇 개의 키워드로 반복 사용

함으로써 프로그래밍 숙련도를 빠르게 높일 수 있다는 것도 큰 장점입니다.

 

세 번째는 풍부한 기본 모듈을 제공한다는 점입니다.


자체 제공하는 패키지들이 강력해서 별도의 웹 프레임워크를 사용하지 않아도 웹을 개발할 수 있습니다.

파이썬 같은 경우 순수 웹 개발이 힘들기에 장고, 플라스크 프레임워크를 사용하는 것에 대조됩니다.

package main

import (
    "net/http"
)
 
func main() {
    http.HandleFunc("/hello", func(w http.ResponseWriter, req *http.Request) {
        w.Write([]byte("Hello World"))
    })
 
    http.ListenAndServe(":5000", nil)
}

물론 Go언어도 프레임워크가 있지만 Go언어는 기본으로 제공하는 net/http 패키지로 충분합니다.

 

네 번째는 신뢰할 수 있는 제작사, 대기업들이 사용한다는 점입니다.


 

 

구글이 만들었고 YouTube 개발에 사용하는 언어입니다. 해외에는 우버, 넷플릭스, BBC가 사용하고 있으며

도커 또한 Go로 개발하였습니다. 국내는 카카오엔터프라이즈, 당근마켓, 왓차, 버즈빌 등 대기업, 스타트업이 사용하는 언어입니다.

 

 4. Go언어의 단점


다음은 Go언어의 단점인데 단점으로 들어가기 앞서서 한 가지 소개할 것이 있습니다. 소프트웨어 공학쪽에 맨먼스

미신이라는 책이 있는데 여기서 나온 유명한 문구를 소개하려고 합니다.

 

 

거기에 위와 같은 문구가 있습니다. 이 말을 해석하면 ‘은총알’은 없다는 의미인데

여기서 은총알은 늑대인간을 죽일 때 사용되는 총알로 모든 문제를 한방에 해결하는 솔루션을 의미합니다.

 

 

그래서 어떤 기술을 가져오더라도 그것이 한방에 해결되는 솔루션이 아니며 무조건 다 좋거나 장점만 가지고 있는 것은 없다는 의미입니다.

 

 

Go언어의 단점은 아래와 같이 구성되어져 있고, 역시 일부만 살펴 보려 합니다

1. 애매한 입지.
2. 아직 부족한 인기.

1. 애매한 입지.


Go언어는 난이도와 성능 사이에서 균형을 잘 잡은 언어이지만 반대로 말하면 난이도와 성능 둘 다 애매하다는 평이 있습니다. 

(하지만, 난이도와 성능의 균형을 잘 잡은 언어가 Go외에 많이 있을까요...?)

쉽게 작성한다 : 모듈이나 프레임워크 등이 지원되어 기능을 구현하기 쉽다.

빠르게 작성한다 : C, C++ 등 같이 컴파일이 필요 없고 작성 즉시 실행시켜볼 수 있어 빠르게 작성할 수 있다.

 

Go언어는 Python, Javascript등의 동적 프로그래밍 언어만큼 쉽고 빠르게 프로그램을 작성하지 못하고,

그렇다고 C, C++ 만큼 성능을 극한으로 끌어올릴 수 있는 것도 아닙니다. C#, Swift, Kotlin처럼 특정 플랫폼을 이용하기 위해 써야하는 언어마저 아닙니다그렇기 때문에 Go언어를 쓸 수 있는 곳은 다른 언어로 대체할 수 있다는 점입니다.

 

2. 아직 부족한 인기.


 

2020년 11월 TIOBE Index

 

위의 항목과 일맥상통하는데 지금 보고 계신 것이 TIOBE Index라고 해서 프로그래밍 언어의 인기와 관련된 수치를 기반으로 프로그래밍 언어의 순위를 산정한 것입니다.

 

TIOBE Index에서는 해당 프로그래밍 언어가 과거부터 현재까지 얼마나 인기 있었는지를 종합적으로 판단하기 때문에

C와 Java 같이 오래전부터 인기 있었던 프로그래밍 언어의 순위가 높게 산정되는 경향이 있습니다.

 

 

2020년 11월 PYPL Index

 

그래서 과거보다는 현재의 인기를 기준으로 프로그래밍 언어의 순위를 산정하는 PYPL Index가 있습니다.

PYPL Index를 보시면 TIOBE Index와 다르게 몇몇 언어들이 순위가 변동 된 것을 알 수 있습니다.

아직은 Go가 C나 Java, JS보다는 순위가 밀리는 것을 알 수 있습니다.

 

그래서인지 레퍼런스도 ‘비교적’ 적습니다. (구글링 시) 한국어로 된 레퍼런스는 말할 것도 없고 외국어로 된 레퍼런스 역시 인기있는 언어들에 비해서 적습니다. 다만 웬만한 문제는 레퍼런스를 통해 해결할 수 있기에 다양한 대안이 없어서 아쉬운 정도라고 생각하시면 됩니다. 하지만 순위가 점점 올라가고 있는 추세라 이 부분은 시간이 지나면 해결 될 문제입니다.

 

추가적으로 Go개발자를 뽑는 회사도 아직은 많이 없습니다....ㅠㅠ 회사가 괜찮은데 뽑는 개발자 보면 Spring개발자를 주로 뽑는게 보여지더군요.. (자바민국...)

그 외에도 제네릭이 없다.는 점도 있는데 아직 제네릭에 대해 이해하고 있는 과정중에 있어 제가 설명해드리기 힘든 부분이 있기 때문에 여기에선 적지 않았습니다. 

추후 Go언어 업데이트 버전에 제네릭이 추가될 예정이라고 합니다. (21년도 기준 올해 여름 업데이트 예정)

이번 1.16릴리즈 업데이트를 통해 제네릭이 업데이트 되었습니다!

자세한 부분은 여기에!

5. Why Go?


그렇다면 Go언어를 왜 배워야 할까요? 다른 언어들이 있는데도 Go를 배워야 하는가?에 대해 나눠보려 합니다.

 

첫 번째로 아셔야 할 것이 무어의 법칙이 실패했다는 점입니다.

 

 

하드웨어에 제한이 걸렸고, 그 내용을 이해해야 왜 Go가 필요한지 알 수 있습니다. 1965년에 고든 무어 라고 하는 인텔의 공동설립자가 있습니다. 이 사람이 내놓은 법칙이 하나 있는데 인텔에서 나온 CPU는 성능이 24개월에 2배씩 좋아질 것이라는 법칙입니다. 그리고 이 법칙을 지키기 위해 인텔이 엄청난 노력을 했었습니다.

그래서인지 65년도부터 2000년대 이후까지는 급성장하게 됩니다.

 

오른쪽 그래프에 검은색 줄이 이렇게 있는데 자세히보면 CPU의 갯수인데 코어의 갯수가 하나로 유지되는 모습을 알 수 있습니다

 

그래도 나름 좋은 성능을 발휘하며 올라갔었는데 2005년도부터 해서 CPU의 성능이 개발 되는 게 점점 더뎌지는게 보입니다. 무어의 법칙이 깨져서 매년 인텔에서 2배이상 빠른 CPU를 만들어 내지 못하게 되었기 때문입니다.

 

그 이유는 이미 집적도가 너무 높아졌다는데에 있습니다.

이 집적도는 CPU의 같은 면적에 얼마나 많은 트랜지스터를 집어 넣느냐가 관건인데 이 트랜지스터가 나노 공정까지

굉장히 작게 만들었었는데 너무 작게 만들다보니 물리적 한계에 부딫히게 되었습니다.

 

대표적으로 열이 많이 발생하게 되었고, 전자방해라고 해서 너무 집적도가 높다 보니 서로간에 전기적신호,

자기장이 발생하게 되어 잘 컨트롤 하기가 어려워졌습니다.


그래서 이런 요소들로 인해서 CPU를 더 많이 집어 넣을 수가 없게 되었고, 그래서 현대의 CPU회사들(인텔, AMD)이

어떤 방식을 취했냐면 멀티코어로 가는 방향으로 취했습니다.
'하나의 코어를 더 빠르게 만들지 못하니까 여러개 만들자!'로 바뀌어서 쿼드, 헥사, 옥타코어 등의 들이 나오게 되었고, 2005년부터 코어의 개수가 증가 하는 것을 알 수 있습니다.

 

또한 이 때에 개발되었던 프로그래밍언어는 다수의 CPU를 컨트롤 할 수 있는 기능이 없었을 때 만들어진 언어들입니다. 자바나 파이썬 같은 경우도 1990년도 이전에 만들어졌던 언어들이라서 동시성의 프로그래밍을 완벽하게 지원할 수 있는 시스템을 위해서 설계가 돼서 만들어진 언어가 아닙니다. 그러다보니 하드웨어에 의존할 수 없는 상황이 와서 다수의 CPU 코어를 다룰 수 있는 소프트웨어를 만들어야 하는데 이 소프트웨어를 만들기에도 현대 프로그래밍 언어가 거기에 맞지 않는 프로그래밍 언어였기 때문에 조금 어려웠습니다.

 

그래서 이런 것들을 해결할 수 있는 언어가 Go언어 라고 볼 수 있습니다.

Go는 Go루틴을 가지고 있는데 Go루틴을 사용하면 멀티코어, 하이퍼스레딩을 사용해서 훨씬 더 성능을 높힐 수 있습니다.

 

고 루틴에서 4개의 코드가 동시에 시작한다. 동시에 프로그램을 진행하므로 다른 코드가 종료될 때까지 기다렸다가 실행할 필요가 없다. 멀티 코어에서는 이렇게 다수의 코드를 한 번에 돌릴 수 있다.

 

그래서 기존의 Node를 가지고 멀티쓰레드나 멀티프로세스 형태로 만들지 않으면 단일 쓰레드로 실행이 되는데

CPU코어가 아무리 많고, 할 일이 아무리 많아도 보통 일반적으로 생각했을 때는 프로그램의 할 일이 많으면 다수의 CPU를 다 써서 빨리 처리해야 맞는데 멀티쓰레딩이나 멀티프로세싱을 지원하지 않는 프로그램들은 CPU를 하나만 사용합니다. 그래서 앞에 있는거 다 처리한 뒤 그 다음 것을 처리하는 절차적인 형태로 처리되는 반면에 Go루틴을 사용하게 되면

멀티 코어 환경을 쉽게 쓸 수 있도록 만든다는 장점이 있습니다. 동시에 다수의 쓰레드를 돌릴 수 가 있게 됩니다.

그림을 보면 4가지의 Go루틴이 시작을 하는데 선들 하나하나가 하나의 쓰레드라고 생각하시면 됩니다.

 

이걸 절차대로 하나씩 처리하면 훨씬 더 많은 시간이 걸릴텐데 이걸 4개의 프로그램 흐름을 따로 만들어 한꺼번에 실행하니까 훨씬 더 빠르게 처리 할 수 있습니다. 그래서 어떤 개발자는 단일 쓰레드로 설계했던 그 프로그램을 Go를 사용해서 멀티쓰레드 환경으로 만드는데 5분밖에 걸리지 않아서 굉장히 획기적인 언어라는 의견도 있었습니다.

 

Go 루틴은 스레드보다 시작 시간이 빠르고, 자체적으로 안전한 통신을 사용하기 위해서 채널이라는 걸 사용합니다.

내부의 어떤 스트림 구조 같은거라고 보시면 되고, 데이터 구조를 공유할 때 뮤텍스 같은 잠금장치를 해놓습니다.

잠금을 하지 않으면 공유를 하면서 데이터가 손실되거나 또는 쓰레드가 서로 같이 경쟁 하면서 문제들이 발생하는데

Go루틴은 그런 부분도 잘 처리 할 수 있도록 만들어진 것 같습니다. 그리고 OS 쓰레드에는 1:1 매핑이 없다고 써 있는데 이것은 어떤 의미냐면 쓰레드가 3개가 있고, CPU랑 1:1 매핑이 되어있으면 얘가 실행하다가 CPU랑 놀때가 있습니다. 무한정 실행되는게 아니고 어떤 요청이 들어오거나 뭐가 있을 때만 실행이 되는 건데 얘는 그 동안 놉니다.

1:1 매핑이 되어 있으면 이런식으로 노는 CPU가 생길 수 있는데 이렇게 놀지 않고 코어가 일을 빌려줘서 다른 애것도 처리해주는 식으로 좀 더 원활한 스케줄링이 가능한 형태를 지원해준다고 합니다.

 

한가지 짚고 넘어가자면 코어들이 노는건 지극히 정상입니다. Go로 간단한 프로그램 돌리는데 CPU점유율이 90%, 100%면 그게 더 문제가 되죠. 여기서 말하는 건 바쁠 때 코어들이 같이 일을 처리해주면 더 빨리, 원활하게 처리가 가능하기 때문에 원활한 스케줄링이 가능한 형태를 지원해준다고 볼 수 있습니다.

 

또 그 다음에 보시는 이 그림은 동시성 프로그램이 얼마나 효과적인가?를 나타내주는 부분인데 C, C++, JAVA가 굉장히 좋다라고 되어 있고, 반면에 파이썬, JS, 등의 언어들은 엔진이 인터프리터 언어를 사용하기 때문에 좋지 않은 형태를 보여주는 것 같고, 이 부분은 직관적이고, 아름다운 코드를 나타내는데 개인마다 느끼는 부분이 다를 수 있겠지만 이 그림에서는 멀티쓰레드 환경을 만들 때 Go를 사용하면 굉장히 깔끔한 처리가 가능하다고 얘기하고 있습니다.

 

 

X : 직관적이고, 아름다운 코드인가? Y : 동시성 프로그램에 얼마나 효과적인가?

 

두 번째는 자바나 파이썬과 같이 중간에 다리를 거치는 언어에 비해서 성능이 월등히 좋다는 점입니다.

 

 

자바는 JVM 파이썬은 인터프리터가 들어가서 느릴 수 밖에 없는 환경입니다. 물론 다수의 운영체제를 지원하긴 하지만

이런 것이 문제가 있었습니다. 하지만 Go는 다양한 운영체제에서 편리하게 돌아가면서 굉장히 빠르고 언어도 다른 언어에 비해서 쉬워서 접근에도 용이합니다.

 

세 번째는 Go로 작성된 코드는 유지 관리가 쉽다는 점입니다. 

 

X : 인간에게 빠르고 즐거운 언어 Y :  컴퓨터에게 빠르고 효과적인 언어

 

매우 깔끔한 구문을 사용하고 있는데 혼란이 있을 만한 Class나 상속, 생성자(Getter, Setter)들을 다 없앴습니다.

대신에 C에서 사용하는 스트럭트나 맵을 지원하여 OOP처럼 구현 할 수 있게 했지만 사용자가 이런 것들(Class나 상속, 생성자)을 직접 만들 수 있게 함으로써 어떻게 보면 좀 더 직관적으로 만들 수 있게 하여 오해의 소지나 혼란의 소지를 피하도록 그렇게 만들었다고 합니다.

 

추가적으로 예외처리 시스템도 없앴는데 예외처리가 가는 부분들을 개발자가 일일이 다 예상해라 라는 메시지가

있지 않을까 생각이 듭니다. 트라이-익셉션으로 묶어 놓으면 어떤 예외가 발생하든 처리 할 수 있지만 어떤 예외가

발생하였는지 개발자가 모르고 지나칠 수 있기 때문에 이 부분을 없애지 않았나 싶습니다.

 

네 번째 이유로 커뮤니티가 있다는 점입니다.

 

 

Go는 구글에서 만든 것으로 유명합니다. 

Go언어가 만들어지고 사용된 지 얼마 안됐음에도 불구하고 굉장히 많은 프로젝트가 이 언어를 가지고 진행하고 있습니다.

 

6. Todo


다음은 제가 Go언어를 공부하면서 만들었던 부분입니다.

최종적으로 Heroku라는 클라우드 플랫폼에 Todos 앱을 배포했습니다. 로그인 부분은 구글OAuth를 사용했습니다.

 

로그인 화면
Todos 앱 화면.

 

사내 log 시스템을 구축했을 때도 Go언어를 사용하였습니다.

 

입력받은 Data 수집 화면
입력받은 Data 수집 화면

 

입력받은 service와 task, trade에 맞게 path가 생성되어 jsondata에 입력한 날짜파일로 생성되어 해당 data가 저장됩니다.

 

이것을 하면서 하나 소스를 공유해보자면

	logStruct := &lumberjack.Logger{
		Filename:   "/home/bos/logs/logweb.log",
		MaxSize:    100,
		MaxBackups: 200,
		MaxAge:     30,
		Compress:   false,
	}
	log.SetOutput(logStruct)

내부에서 Data를 받았을 때 Data를 저장하는 log 파일을 생성할 때 사용한 코드입니다.

lumberjack이라는 라이브러리가 파일들을 관리해주는데 내부적으로 log 파일을 저장할 때 상당히 편리 했습니다.

lumberjack에 대해 자세히 알고 싶으시다면 이 곳에서 확인하시면 됩니다.

 

지금은 log 파일 시스템에서 Kafka 시스템으로 변경하였습니다. 

여기에서 확인 하시면 됩니다.

 

 

Kafka로 바꾼 후..

 

 

추가적으로 Go 웹 프레임 워크 중 'Gin'과 리액트를 사용하여 쇼핑몰 Page도 구현 하였습니다.

 

일반 상품 페이지
프로모션 상품 Page
로그인 후 생기는 주문 목록 Page
카드 결제 창
회원 가입 창

 

7. 느낀점 


이 것을 하면서 작은 서버 컴퓨터에 배포 경험만 있었던 저에겐 좋은 경험이였습니다.

소규모 서버 컴퓨터로 배포 했을 때와 다른 점은 셋팅의 차이에서 많이 느꼈습니다.

서버 컴퓨터를 사용 했을 때는 외부에서도 배포한 웹페이지에 접속할 수 있도록 포트포워딩 문제에서 막힌 적이 있었다면 Heroku에서는 환경변수 설정하는 부분에서 막혔었고, 파일의 변동이 있을때는 서버 컴퓨터의 경우 파일질라를 통해 파일을 주고 받았다면 Heroku는 Git으로 주고 받았었습니다.

 

Go를 사용하면서 분명히 Go로 코딩하고 있는데 C를 코딩하는 느낌이 들기도 했고, 타 언어에 비해 워낙 적은 키워드를 갖고 있다 보니까 이거 말고 또 있지 않을까? 하며 공부하기도 했었습니다. 현재 국내 기업보다는 해외 기업에서 더 많이 Go를 사용하고 있는데 국내에서도 지금 보다 더 많이 사용 했으면 하는 바램입니다.

 

이 글을 봐주셔서 감사합니다 ㅎㅎ 궁금한 점 있으면 댓글 달아주시면 답변 달아 드리겠습니다! ㅎㅎ 도움 되셨길 바랍니다.

 

참고자료

728x90
반응형
그리드형

댓글을 달아 주세요