/img/avatar.jpg

logstream

이 글은 제 로그 라이브러리를 작성하며 생각한 것을 작성한 것입니다.

개요

logstream 라이브러리는 로그를 생성하고 소비하는 패턴을 구현하기 위해 만든 일종의 고 프로그램 전역에서 돌아가는 메시지 큐입니다. 다른 메시지 큐와 마찬가지로 여러 생산자가 토픽에 값을 추가하고 소비자가 토픽에서 값을 꺼내서 사용합니다.

/img/006/logstream.png

생산자(producer)는 코드 상 어디라도 될 수 있으며 스트림을 내포하고 있는 객체는 글로벌큐(global queue)로 전역 객체로 생성될 것입니다. 소비자(customer)는 글로벌큐 내부 스트림을 통해 순차적으로 생산자가 만들어낸 로그를 받아서 소비합니다. 소비는 가급적이면 모든 소비자 중 하나가 한번 소비하면 로그가 사라지는 게 아니라 모든 소비자에게 돌아가는 걸 목표로 합니다.

스마트폰 파괴 방법과 매개변수 덕타핑

개요

인터페이스 비교로 에러를 처리하는 방식에 기반하여 인터페이스로 매개변수를 덕타이핑하는 건 어떨까 해서 한번 시도해봤습니다.

아이디어

아이디어는 쉽습니다. 베이스가 되는 인터페이스와 구조체를 작성합니다. 이후 필요에 따라 매개변수를 얻을 수 있는 새로운 인터페이스를 제공하고 해당 인터페이스에 대한 구조체를 작성합니다. 그렇다면 동일한 함수 원형에 여러가지 타입의 매개변수를 넘겨줄 수 있을 것입니다.

구현

스마트폰을 파괴하는 코드를 작성해보겠습니다.

PhoneBreaker

package phonebreaker

type PhoneBreakable interface {
	Break(PhoneBreakingTool) int
}

type PhoneBreakingTool interface {
	Hand() int
}

간단하게 PhoneBreakable 인터페이스로 휴대폰을 파괴할 수 있는 행위를 정의해 놓았습니다.
그리고 가장 간단한 파괴 도구로 Hand()를 가지는 툴 인터페이스도 만들어 놓았습니다.

Option과 default parameter

option

option 패키지는 직전 포스트에 작성한 result 패키지에서 에러 메시지가 빠진 형태입니다.

구조체

type Option[T any] struct {
	value any
}

func Some[T any](value T) *Option[T] {
	return &Option[T]{value: value}
}

func None[T any]() *Option[T] {
	return &Option[T]{value: nil}
}

구조체는 result와같이 any 타입을 가진 멤버 하나만 존재합니다. Some 생성자는 인자의 타입에 따른 Option 구조체를 생성하고 멤버 변수에 인자를 대입합니다. None 생성자는 타입 인자만 하나 받으며 해당 타입에 대한 Option 구조체를 반환하지만 멤버 변수는 nil이 대입됩니다.

Result를 활용한 에러처리

이 글은 제가 작성한 레포인 generics-for-go를 기반으로 쓰여졌습니다.

개요

예전 고 1.18 dev 버전이 나왔을 때 한 레포를 만들어서 제네릭 관련 함수를 찍어낸 적이 있습니다. 그 이후 한동안 잊고 지내다가 1.18 beta가 나오게 되고 이제 큰 피처의 변화는 없을 거라 판단해서 제네릭으로 몇가지 장난을 하던 도중, 러스트같은 언어에서 자주 보이는 Option과 Result를 만들어 보고 싶었습니다.

예전에도 당연히 interface{}만으로 구현에 도전해봤지만 사실 타입 단언(Type Assertion)을 해야한다는 것에서 그다지 사용성이 좋지 못 했고 이로 인해 코드 수만 늘어났습니다. 하지만 제네릭이라는 수단이 추가되니 생각할 폭이 넓어지고 재밌는 문법이 떠올랐습니다.

에러 처리 in go

쉬운 에러 처리

package main

import (
	"errors"
)

func NewError() error {
	return errors.New("this is new error!")
}

func ThrowError() error {
	_, err := os.Open("not-exist")
	return err
}

func main() {
	err := NewError()
	if err != nil {
		log.Println(err)
	}

	err = ThrowError()
	if err != nil {
		log.Println(err)
	}
}

가장 쉬운 에러 처리 방법은 errors.New 함수로 에러 메시지를 담은 error 인터페이스 인스턴스를 직접 만드는 것과 반환된 에러를 그대로 상위 스택에 넘겨주는 방법이 있습니다. 하지만 이 2가지 방식은 각기 다른 문제점이 있습니다.

더 나은 제안, Kemtls

본 문서는 https://blog.cloudflare.com/kemtls-post-quantum-tls-without-signatures/ 의 번역이 일부 포함되어 있습니다.


더 나은 제안: KEMTLS

서명이 외에 인증에 사용되는 다른 메커니즘에는 긴 역사가 있습니다. Signal 프로토콜, Noise 프레임워크 또는 WireGuard와 같은 최신 프로토콜은 인증을 위해 키 교환 매커니즘에 의존합니다. 하지만 이런 것들은 길게보면 중요한 키가 이해관계자 사이에 알려지기 때문에 TLS 1.3에 적합하지 않습니다.

(중략)

Krawczyk와 Wee의 OPTLS 제안은 NIKE(Non-Interactive Key Exchange)를 통해 악수 없이 TLS 핸드셰이크를 합니다. 그러나 포스트 퀀텀 NIKE를 위한 다소 효율적인 유일한 선택지는 CSIDH이며, 보안은 현재 진행 중인 논의 내용입니다. 하지만 우리는 이 아이디어를 바탕으로 KEM을 인증에 사용할 수 있습니다. 현재 실험 단계인 KEMTLS는 포스트 퀀텀 KEM 핸드셰이크를 대체합니다. 이 내용은 ‘Post-Quantum TLS Without Handshake Signatures’에서 Peter Schwabe, Douglas Stebila 그리고 Thom Wiggers가 디자인 및 소개했습니다.

snowmerak

안녕하세요.

누구나 안전하고 편리한 네트워크를 꿈꾸는 백엔드 개발자, snowmerak입니다.

project

skill

languages

https://img.shields.io/badge/-Go-eaeff9?style=flat&logo=GO https://img.shields.io/badge/-Python-eaeff9?style=flat&logo=PYTHON

frameworks

https://img.shields.io/badge/-Svelte-eaeff9?style=flat&logo=SVELTE

tools

https://img.shields.io/badge/-Docker-eaeff9?style=flat&logo=DOCKER https://img.shields.io/badge/-VSCode-eaeff9?style=flat&logo=VISUAL-STUDIO-CODE https://img.shields.io/badge/-Git-eaeff9?style=flat&logo=GIT

Database

https://img.shields.io/badge/-PostgreSQL-eaeff9?style=flat&logo=POSTGRESQL