본문 바로가기

D.S/ETC

220308화 - Go 언어

728x90

다른 언어도 슬슬 써봐야지. 뭐든 레이더에서 거르면 안 되는군... 할 게 많아서 현재로서 중요도는 좀 떨어지곘지만..
해야하는 게 많으니 프로젝트를 (목표를) 작게 잡아서 여러 개를 만들고 필요할 때마다 불러내서 덧붙이고 이래야 할 듯. 크고 복잡한(?) 걸 한번에 오랫동안 만드는 것보다는 작게 만든 다음 필요할 때 계속 업데이트 가능하게 만드는 게 맞는 것 같다.

기술 트렌드 파악할 수 있는 대표적인 사이트를 좀 알면 좋겠는데.
사실 주변에 사람이 있다면 같이 공유하는 게 제일 좋긴할거 같다. 혼자 하는 건 물론 할 수 있지만 시간이 더 걸리는 듯. 스터디를 찾아야 하나 만들어야 하나;


참조

→ 개인공부를 위해 밑의 주소의 내용을 많이 참조했으며 밑의 원문을 읽으시는 것을 추천.

GO

  • C++을 사용하면서 서버 빌드하는데 시간이 너무 걸려 구글 엔지니어 3명이 모여 만들기 시작한 언어..(진짜 구글은 머하는 곳이여;)
  • 시스템 프로그래밍에 적합하도록 설계되었으며 C와 구문이 비슷
  • C와 C++에 비해 간결하고 복잡함을 줄였음. C언어에 경험이 있는 개발자라면 쉽게 배울 수 있음
  • 컴파일 속도 향상을 위해 기존에 사용했던 헤더 파일을 정의하는 방식 대신 소스 자체를 패키지화하는 방식을 채택. 소스 코드 자체를 패키지화하여 변경된 부분만 컴파일 함으로써 컴파일 속도를 향상시킴.
  • 소스 내에 사용하지 않는 변수나 패키지가 있을 경우 컴파일 시 오류를 발생. 불필요한 패키지 가져오기에 따른 지연 시간을 줄이고 사용하지 않는 변수 및 패키지 선언으로 인해 향후에 발생할 수 있는 버그를 줄이고자 함.
  • 개발자의 생산성 향상에 초점을 두고 설계되어 기존 개발자들이 사용하던 IDE에서 쉽게 환경을 구성할 수 있음
  • Go 언어로 작성된 파일을 컴파일,실행, 관리할 수 있는 go 바이너리를 다운로드 → 소수의 환경변수 $GOROOT, $GOPATH($GOPATH를 $PATH에 추가)를 설정하는 것만으로 개발 환경을 구성 가능
  • 유틸리티 Go 파일은 Go 언어로 작성한 소스파일을 컴파일(build)하여 실행 가능한 바이너리를 생성하는 것은 물론, 컴파일 후 바로 실행(run)하는 기능을 제공
  • 소스에 기술된 패키지 단위로 관리되며 Go 소스로 작성할 수도 있고, 이미 정의되어 있는 패키지를 import문으로 가져와서 사용가능. 필요한 외부 패키지가 있을 경우엔 get 커맨드로 패키지를 받아와 사용함
  • 그 외에도 Go 소스 파일의 형식을 맞춰주는 포맷팅(fmt), 사용되는 패키지 리스트업(list), 테스트 코드 수행 등 Go 언어로 패키지를 작성 및 사용하기 위한 여러 가지 기능을 제공
  • Go 언어는 기본 패키지 이외에도 여러 벤더에서 다양한 패키지를 제공
    • 시스템 프로그램에 자주 사용되는 http 패키지는 물론 통신에 피룡한 암호화 모듈까지 기본 내장되어 있어 웹 서버를 쉽게 구축 가능
    • 파이썬의 flask, FastAPI같이 유명한 대표 프레임워크가 있진 않은걸까? 신기하네.
  • Go 소스 내에 cgo라는 별도 지시자(directives)를 설정함으로써 C 언어로 작성된 라이브러리를 직접 사용하는 것도 가능. 이러한 강점 떄문에 기존 인프라 소프트웨어를 대체할 수 있는 언어로 선택되며 대표적인 예로 SSH의 Go 언어 구현체인 텔레포트(Teleport)가 있음


동시성

  • Go 언어는 시스템 프로그램, 특히 서버 개발용으로 설계되었음
  • 고루틴(goroutine)과 채널(channel)을 제공함. 고루틴은 Go 런타임에서 관리되는 일종의 경량 스레드이며 채널을 통해 고루틴(스레드) 간에 메세지를 주고 받을 수 있는 매커니즘을 제공
  • 고루틴과 채널을 활용해 멀티 코어 환경에서 병렬처리를 쉽게 구현할 수 있음
  • 고루틴:
    • 자체 Go 런타임 스케줄러에 의해 관리되며 OS 스레드에 비해서도 경량. OS 스레드를 생성하는데 필요한 메모리가 1MB인 반면, 고루틴은 2KB입니다. 또한 일반 스레드와 달리 메모리의 스택 영역을 사용하며 자체 스케줄러에 의해 관리하므로 컨텍스트 스위칭 비용을 줄인다. (스레드는 원래 프로세스에게 메모리의 스택영역을 할당받아 독립적으로 가지지않남? 스케줄러로 관리하니 스레드간 컨텍스트 스위칭.)
    • Go 런타임에서 사용하는 CPU 코어수를 지정하는 환경변수 GOMAXPROC를 지정함으로써 병렬적으로 고루틴을 실행할 수 있음. 하나의 프로세스에서 보통 1만개의 고루틴을 실행시킬 수 있느며 몇십만 단위의 고루틴도 실행 가능하도록 스케줄러가 구현되어 있음. (스택메모리가 부족하면 힙영역까지 확장)


에러처리, 함수 흐름 제어

  • 함수는 복수 개의 값을 반환할 수 있음. 이를 통해 에러가 발생했을 때 일반적인 리턴과 함꼐 오류 메세지를 반환할 수 있고 이 기능은 에러처리를 쉽게 함.
    • ex. Go기본 패키지 os의 Write함수는 다음과 같이 정의되며 write에 성공한 바이트 수와 에러 메시지를 함꼐 반환합니다. (Go 언어에서 함수 선언 시 반환값은 제일 마지막에 변수명, 타입 순으로 정의)
    • 200바이트 데이터를 파일에 쓰게 했을 떄 100바이트는 성공적으로 쓰였지만 공간이 없어서 나머지는 실패한 것을 감지함
      •  
  • 복수 개의 반환을 통해 에러를 감지하더라도 어떤 에러는 발생할 경우 더 이상 프로세스가 실행되는 것이 의미가 없어질 수 있으며 이때 Go 언어는 패닉(Panic)을 발생시켜 에러 후 종료하는 것을 권고
  • 프로그램이 패닉 발생 → 현재 함수의 실행을 즉시 중지 → 실행 중인 스택 상의 고루틴을 하나씩 종료 → 고루틴이 모두 종료되면 최종적으로 프로그램이 종료
  • 고루틴 내에서 발생한 에러에 대해 조피 후 정상 복구가 가능한 겨우에는 고루틴 종료 전에 호출되는 recover 함수에 조치 사항을 정의함으로써 프로그램 자체를 종료하지 않고 정상 재개할 수 있음
  • recover 문과 비슷하게 Go 언어의 defer문은 함수가 종료되기 직전에 수행되는 문장으로 함수 내에서 사용한 리소스 반환 처리와 같은 상황에 유용


제약사항

  • 설계 철학에 어긋나는 generic 같은 일부 기능은 의도적으로 빠짐
  • C구문을 따랐지만 포인터 연산을 없앴음
  • C와 다른 부분이 분명 존재하기 때문에 커널이나 장치 드라이버, 임베디드 소프트웨어 같은 저수준 프로그램엔 적합하지 않음
  • 상용 하드웨어 전용으로 설계되어 있어 하드웨어 가속을 사용할 수 없음( 그래픽스 분야에 맞지 않음)
  • 틸리티나 네트워크 서비스와 같은 프로그램을 만들 때 유용

Go스러움?

      • 타입을 통해 안정적으로 개발 (interface{}와 같은 빈 인터페이스를 이용하면서 type assertion 이나 reflect를 이용하는 것을 지양)
      • 가볍고 간결함 (Spring MVC와 같은 많은걸 지원하는 무거운 프레임워크 지양)
      • 빠름
      • 동시성을 고루틴과 채널을 이용해 잘 사용

프레임워크들

      • fiber
      • echo
      • gin
반응형