/img/avatar.jpg

vcpkg를 cgo에 사용하기

vcpkg?

vcpkg는 Microsoft에서 발표한 C/C++ 패키지 매니저입니다.
vcpkg의 레포에 등록된 패키지들을 install을 통해 손쉽게 설치하고 이용할 수 있습니다.

vcpkg 설치

vcpkg는 전역으로 사용할 수 있지만 이번 글에서는 프로젝트 내에서 사용하도록 설정하겠습니다.

mkdir prac
git clone https://github.com/microsoft/vcpkg.git

prac 폴더를 생성한 후, vcpkg를 클론합니다.
클론하면 vcpkg 폴더가 생성되고, 최초 1회 bootstrap-vcpkg.sh(or 윈도우의 경우, bootstrp-vcpkg.bat)을 실행해야 합니다.

제티

제티 (Jetti)

제티는 제가 프로젝트를 구조적으로 관리하고, 생산성을 조금이라도 높이기 위해 만든 코드 생성기입니다.

제티의 지향점

제티는 다음과 같은 지향점을 가지고 있습니다.

  1. 고 언어 프로젝트 구조에 대해 어느 정도 강제성을 부여합니다.
  2. 코드를 작성할 때, 귀찮은 부분을 최대한 코드 생성을 통해 줄여줍니다.
  3. 까먹고 하지 못 했다는 이유로 해야할 것을 하지 못하는 일을 최대한 줄여줍니다.
  4. cgo 의존성이나 외부 툴 설치에 대한 간단한 지원을 제공합니다.

설치

제티는 go install을 통해 설치할 수 있습니다.

구조체 임베딩과 프로모션, 그리고 상속

구조체 임베딩

구조체 임베딩은 구조체를 다른 구조체의 필드로 사용하는 것을 말합니다. 예를 들어 다음과 같은 구조체가 있다고 가정해봅시다.

type Person struct {
    Name string
    Age int
}

그리고 이 구조체를 다른 구조체의 필드로 사용한다면 다음과 같이 사용할 수 있습니다.

type Student struct {
    Person
    Grade int
}

그러면 마치 Student 구조체에 Person 구조체의 필드가 포함된 것처럼 사용할 수 있습니다.

Context 패키지 (실전)

기능 복기

TODO 컨텍스트의 경우에 특이 케이스이므로 여기에 포함시키지 않겠습니다.

컨텍스트 생성

package main

import "context"

func main() {
	ctx := context.Background()
}

context.Background() 를 통해 새로운 컨텍스트를 생성할 수 있습니다.
반드시 이 컨텍스트를 생성할 때는, 모든 작업의 최상단에서 생성해야 합니다.

취소 가능한 컨텍스트 생성

  1. context.WithCancel()
package main

import "context"

func main() {
	ctx := context.Background()

	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
}

context.WithCancel() 을 통해 취소 가능한 컨텍스트를 생성할 수 있습니다.
이 함수는 새로운 컨텍스트와 취소 함수를 반환합니다.
취소 함수를 통해 현재 컨텍스트를 포함한 하위 컨텍스트들에게 취소 시그널을 줄 수 있습니다.
시그널은 ctx.Done() 메서드에서 반환된 <-chan struct{}에서 받을 수 있습니다.

Context 패키지 (이론)

패키지 구성

Package context defines the Context type, which carries deadlines, cancellation signals, and other request-scoped values across API boundaries and between processes.

컨텍스트 패키지는 Context 타입을 구현하고 있는 패키지입니다. 이 컨텍스트 타입은 인터페이스로 실제로는 하부에 크게 5가지 타입의 컨텍스트 구현체가 존재합니다.

컨텍스트 종류

  1. 아무 상태도 가지지 않은, backgroundCtxtodoCtx
  2. 취소 시그널을 보내거나 무시할 수 있는, cancelCtxwithoutCancelCtx
  3. 특정 시간만 동작하거나 특정 시각까지만 동작하는, timerCtx
  4. 키와 값을 저장하는, valueCtx
  5. 사후 처리를 담당하는, afterFuncCtx

backgroud, todo

아마 세상에서 가장 많이 쓰이는 컨텍스트입니다.

테스트 가능한 코드

테스트 주도 개발

테스트 주도 개발을 하자는 이야기는 아닙니다. 테스트 주도 개발은 좋은 개발 방법론이라고 생각은 합니다. 하지만 제가 이번 글에서 말하고자 하는 것은 테스트 주도 개발이 아니라 테스트 가능한 코드를 작성하는 것입니다. 글이 끝나갈 때 쯤엔 마치 테스트 주도 개발이 옳다는 듯이 얘기하고 있을 가능성도 충분히 높습니다.

테스트 가능한 코드

테스트 가능한 코드는 충분히 우리가 컨트롤 할 수 있는 정도의 크기로 기능과 코드를 나누어 지고, 추상화되어 있어야 합니다. 그리고 이 작은 검증된 테스트들은 코드가 모여서 만들어진 더욱 상위의 테스트에 대한 검증을 수월하게 합니다. 그에 대한 몇가지 주제와 예시를 작성해보겠습니다.

고루틴과 채널을 활용한 유사 액터 모델

액터 모델?

액터 모델은 동시성 문제를 해결하기 위해 등장한 개념입니다. 각 액터는 독립된 스레드에서 실행되며, 메시지를 통해 상호작용합니다. 액터 모델은 다음과 같은 특징을 가집니다.

  1. 액터는 메모리를 공유하지 않습니다.
  2. 액터는 고유의 상태를 가질 수 있습니다.
  3. 액터 간의 통신은 메시지를 통해 이루어집니다.
  4. 액터 간의 통신은 비동기적입니다.
  5. 액터는 해당 메시지에 대응하는 동작을 수행합니다.

CSP와 너무 잘 맞지 않아?

고 언어는 기반 패러다임에 CSP가 있는 만큼, 고루틴과 채널이라는 강력한 도구가 있습니다. 이를 이용해 타 언어에 비해 손 쉽게 액터 모델을 구현할 수 있습니다. 액터는 고루틴으로 띄우고, 메시지는 채널로 주고 받습니다. 그러면 자연스럽게 액터 간의 통신은 비동기적으로 동작합니다. 해당 메시지에 대해 라우팅이 필요한 경우에도, 여러 채널을 이용하여 select 문법을 통해 처리할 수 있습니다.

고랭과 아레나

Arena?

고랭은 가비지 컬렉터를 쓰는 언어이고, 덕분에 사용자는 메모리를 관리하는 데에 크게 신경을 쓸 필요가 없습니다. 하지만 프로젝트 크기가 커지고, 사용해야할 힙 메모리가 커질수록 더욱 빈번하게, 그리고 한번에 많은 양의 메모리를 수집하여 처리하게 됩니다. 하나의 기능을 수행하고 난 후에는 물론이고, 수행하는 도중에도 GC가 동작하여 응답이 늦어지는 상황이 생겨날 확률이 늘어납니다.

그런 상황에서 유용하게 쓸 수 있는 아레나(arena)라는 개념이 등장했습니다. 아레나는 미리 사용할 힙 메모리를 할당 받아서 사용합니다. 이 때 할당받는 큰 힙 메모리 덩어리 하나를 페이지라고 합니다. 일반적인 경우는 IO 버퍼 사이즈로, 4096(4K) 혹은 8192(8K), 16384(16K) byte 중 하나입니다. 이 페이지들이 이중 연결리스트 형태로 이어지고, 필요한 메모리를 기존 페이지에서 충당할 수 없을 때마다 새로운 페이지를 추가합니다. 그리고 아레나를 활용한 모든 작업이 끝나면 마지막에 최종적으로 아레나 전체를 반환합니다.