Profile img

Hi, I'm who's behind Fedify, Hollo, BotKit, and this website, Hackers' Pub! My main account is at @hongminhee洪 民憙 (Hong Minhee) :nonbinary:.

Fedify, Hollo, BotKit, 그리고 보고 계신 이 사이트 Hackers' Pub을 만들고 있습니다. 제 메인 계정은: @hongminhee洪 民憙 (Hong Minhee) :nonbinary:.

FedifyHolloBotKit、そしてこのサイト、Hackers' Pubを作っています。私のメインアカウントは「@hongminhee洪 民憙 (Hong Minhee) :nonbinary:」に。

Website
hongminhee.org
GitHub
@dahlia
Hollo
@hongminhee@hollo.social
DEV
@hongminhee
velog
@hongminhee
Qiita
@hongminhee
Zenn
@hongminhee
Matrix
@hongminhee:matrix.org
X
@hongminhee
1

요즘 심심할때 굴리고 있는 VCS에 대한 나이브한 아이디어가 있는데

  • 각 커밋에 대해 메타데이터를 줄수 있어야 한다

    레포 내의 metadata.json 같은 파일을 인식해도 되고, 아니면 Commit -> Metadata를 해주는 프로그램을 hook으로 등록하게 해줘도 된다. 이를 통해 package.json, cargol.toml 같은 파일을 읽어서 거기에 버전 의존성을 커밋의 메타데이터로 추출한다.

  • 메타데이터에 대해 인덱싱을 한다

    가령 version이라는 메타데이터가 있을때 2 <= version < 3를 만족하는 커밋의 범위를 인덱스를 활용해 빠르게 알아낼수 있게 한다.

  • 메타데이터로 커밋을 찾는 표현식을 제공한다

    max(2 <= version < 3 and has(fix-bug-foo) and has(add-feature-bar) 이런식으로 하면, 구간 내의 버전에서 foo 버그가 해결되고 bar 피쳐가 추가된 커밋중 가장 최신의 커밋을 구한다. git에서는 fix-bug-foo, add-feature-bar 각각의 브랜치로는 쉽게 갈수 있지만, 해당 브랜치가 main에 머지되기 전까지 그 브랜치 밖을 벗어나 작업하기가 까다로워진다.

  • 이런 레포들을 모아서 모노레포를 모은다음, 메타데이터에 상호 의존성을 기술한다

    그리고 dependency resolve를 해서(메타데이터 검색의 일종일 뿐임) 조건을 만족하는 모노레포 스냅샷을 구한다. 이제 우린 패키지 매니저를 공짜로 얻었다.

이 아이디어는, 현재 패키지 매니저와 VCS가 분리되어있는데 사실 그래선 안된다는 생각에서 나온것이다. 기존의 비슷한 아이디어를 찾아봤는데 gitman 이런게 있더라. 근데 내가 원하는만큼 일반적이진 못하다.

5
1
2
2
2

洪 民憙 (Hong Minhee) shared the below article:

도커로 구축한 랩에서 혼자 실습하며 배우는 네트워크 프로토콜 입문 #2

자손킴 @jasonkim@hackers.pub

이 글은 동일 네트워크 내 장비들이 L2 스위치를 통해 통신하는 방식에 대해 설명합니다. MAC 주소를 기반으로 통신하는 L2 계층은 통신 시작 시 IP 주소만 알고 MAC 주소를 모르는 상황을 해결하기 위해 ARP를 사용합니다. MAC 주소와 IP 주소의 역할, 이더넷 프레임 구조, 그리고 ARP의 동작 방식과 한계점을 상세히 다룹니다. 또한 L2 스위칭의 핵심인 MAC 주소 테이블과 flooding 과정을 설명하고, MAC 주소 중복 문제와 VLAN 기술을 소개합니다. 마지막으로, OVS 환경에서 VLAN 설정 시 vlan_mode와 tag의 의미를 명확히 구분하여 네트워크 구성에 대한 이해를 돕습니다.

Read more →
4
4
1
1
1

🐍 .NET에서 Python을 가장 가볍게 실행하는 방법

Python 코드를 C# 애플리케이션에서 실행해야 하는데  복잡한 설정과 보일러플레이트 코드가 부담되셨나요?

DotNetPy를 만들었습니다: ✅ Zero Boilerplate - GIL 관리나 Source Generator 불필요 ✅ AOT 친화적 - Native AOT 시나리오를 위해 설계 ✅ 최소한의 러닝 커브 - 몇 줄로 Python 실행 ✅ Apache 2.0 라이선스

Python 표현식 평가부터 복잡한 데이터 교환까지,  pythonnet이나 CSnakes보다 훨씬 가벼운 대안입니다.

사용 예시: Python.Initialize(pythonLibraryPath); var executor = Python.GetInstance(); var result = executor.Evaluate("sum([1,2,3,4,5])"); Console.WriteLine(result?.GetInt32()); // 15

🔗 GitHub: https://github.com/rkttu/dotnetpy

2
6
3
3
2

洪 民憙 (Hong Minhee) shared the below article:

Migrate to Misskey from Iceshrimp

AmaseCocoa @cocoa@hackers.pub

This post outlines the process of migrating from Iceshrimp, a fork of Firefish (itself a fork of Misskey v12), to Misskey, starting from v13. The author details their reasons for migrating, including ongoing reimplementation efforts in .NET, issues with media rendering, and a general preference for Misskey. A comparison table highlights key differences between Iceshrimp and Misskey, such as translation API, note editing capabilities, MOTD, note length limits, search engine options, FTT, and social login. The guide provides a step-by-step walkthrough, including backing up and rolling back the database, running specific SQL commands to align the database schema with Misskey, and installing Misskey without initializing it to prevent data corruption. Troubleshooting tips are included for common issues like login failures and client loading problems. This migration guide offers valuable insights for those looking to transition from Iceshrimp to Misskey, ensuring a smoother process.

Read more →
2
4
1
4
5

슬슬 맥미니의 용량 부족 압박이 발생하여, gdu-go[1]를 설치하고 용량 확인을 했더니 Cursor가 100GB, VSCode 가 75GB를 차지하고 있었던 건에 대하여

  • 정확히는 User Library/Application Support폴더안에 있는 Cursor 폴더와 Code 폴더
 --- /Users/arkjun/Library/Application Support ---
                         /..
  100.9 GiB █████▏    ▏/Cursor
   74.4 GiB ███▊      ▏/Code
    7.3 GiB ▎         ▏/Google
    2.2 GiB           ▏/Microsoft
    1.8 GiB           ▏/Comet

덧) 범인은 Java 프로젝트 당시에 생겨난 hprof 확장자파일들 때문이었다. (파일 하나에 9기가 정도하는 파일들이 여럿 확인되었다)


  1. About Fast disk usage analyzer with console interface written in Go https://github.com/dundee/gdu ↩︎

gdu 로 용량 확인한 화면
2
3
4
2

(위 트윗의 koka 코드도 그렇고 이 트윗의 effekt 코드도 그렇고 귀찮아서 대충 Gemini 시켰다. 틀려도 양해 바란다)

반면 Effekt의 Capability Passing Style 멘탈 모델로 생각하면 약간 양상이 달라지는데, Capability는 값 주입의 관점으로 보기 때문에 Effect를 it happens가 아니라 it requires로 본다. 그래서 named handler 같은 코드를 이렇게 쓴다. 걍 computation을 받는 함수인 것.

fun swap[A]() {h1: State[A]} {h2: State[A]}: Unit = {
  val a = h1.get();
  val b = h2.get();
  h1.set(a);
  h2.set(b);
}

koka는 happens지만 effekt는 requires다. 하지만 named handler에서는 둘 다 그냥 computation을 인자로 넘기는 모양새에 수렴했다.

2

swap :: State a (State a ()) 같은 함수를 algebraic effect로 기술하려면 같은 효과가 두번 나오기에 koka는 named handlers를 실험하고 있다. 옳은 방향이라고 생각한다. 기존에 koka는 masked effect라는 복잡한 개념을 사용해 outer effect에 접근했다.

fun swap-with-mask() : <state<a>, state<a>> () {
  val inner-val = get() // innermost
  val outer-val = mask<state<a>> { get() } // skip the innermost
  set(outer-val) // innermost
  mask<state<a>> { set(inner-val) } // skip the innermost
}

하지만 named handler와 함께라면 이렇게 쓸 수 있다

fun swap-with-named-handlers(h1, h2) : <state<a>> () {
  val val1 = perform get() at h1
  val val2 = perform get() at h2
  perform set(val2) at h1
  perform set(val1) at h2
}

seealso: https://dl.acm.org/doi/10.1145/3563289

(위 트윗의 koka 코드도 그렇고 이 트윗의 effekt 코드도 그렇고 귀찮아서 대충 Gemini 시켰다. 틀려도 양해 바란다)

반면 Effekt의 Capability Passing Style 멘탈 모델로 생각하면 약간 양상이 달라지는데, Capability는 값 주입의 관점으로 보기 때문에 Effect를 it happens가 아니라 it requires로 본다. 그래서 named handler 같은 코드를 이렇게 쓴다. 걍 computation을 받는 함수인 것.

fun swap[A]() {h1: State[A]} {h2: State[A]}: Unit = {
  val a = h1.get();
  val b = h2.get();
  h1.set(a);
  h2.set(b);
}

koka는 happens지만 effekt는 requires다. 하지만 named handler에서는 둘 다 그냥 computation을 인자로 넘기는 모양새에 수렴했다.

2

swap :: State a (State a ()) 같은 함수를 algebraic effect로 기술하려면 같은 효과가 두번 나오기에 koka는 named handlers를 실험하고 있다. 옳은 방향이라고 생각한다. 기존에 koka는 masked effect라는 복잡한 개념을 사용해 outer effect에 접근했다.

fun swap-with-mask() : <state<a>, state<a>> () {
  val inner-val = get() // innermost
  val outer-val = mask<state<a>> { get() } // skip the innermost
  set(outer-val) // innermost
  mask<state<a>> { set(inner-val) } // skip the innermost
}

하지만 named handler와 함께라면 이렇게 쓸 수 있다

fun swap-with-named-handlers(h1, h2) : <state<a>> () {
  val val1 = perform get() at h1
  val val2 = perform get() at h2
  perform set(val2) at h1
  perform set(val1) at h2
}

seealso: https://dl.acm.org/doi/10.1145/3563289

1
1
1
5
2
2
1
4
1
1
0
0
3
1
4
3
2
1

Gleam 언어는 뭔가 별다른 복잡한 요소가 없어서 오히려 재밌는 구석이 있는 것 같다. 제네릭 말고는 별다른 다형성 기능이 없어서 오히려 설계를 고민하게 만든다던지. 서브타입도 타입클래스도 없으니까 제네릭 인자로 넘긴 타입에 뭔가 연산을 하고 싶으면 반드시 호출하는 쪽에서 연산에 필요한 함수를 그때그때 전달해야 한다. TypeScript의 any 타입처럼 gradual typing이 지원되는 것도 아니라서 정 타입시스템을 우회하고 싶으면 그때그때 Dynamic 타입으로 인코딩과 디코딩을 거쳐야 한다. Erlang 기반이니까 액터를 끌어다 쓸 수 있기는 하지만 아무래도 다른 언어에서 그냥 객체를 정의하고 메서드를 부르는 것보다는 무겁게 느껴진다. 액터라고 해서 타입이 아예 없는 것도 아니고.

2
3
2
1