Profile img

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

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

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

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

유시지(usage) 출력까지는 어떻게 구현 했다. 그런데 이건 쉬운 문제고, 도움말이 정말 어려운 문제인데…

optique <main?> $ deno run example.ts 
Usage: example.ts one [-a/--allow] -v/--value INTEGER ARG
       example.ts two [-f/--foo] -b/--bar VALUE
       example.ts three [-d/--deny] -t/--test INTEGER [-z/--baz] -q/--qux QUX
       example.ts nest foo [-a/--allow] -v/--value INTEGER ARG
       example.ts nest bar [-f/--foo] -b/--bar VALUE
Error: No parser matched.
2
2
4
4
2
3
2
4

news.hada.io/topic?id=22140

이 글에서 "switch network 쓰지 말고 hash map 쓰세요 그쪽이 더 빠릅니다" 해서 정말 그런가? 했는데 그런듯 하다.

지금 진행하던 개인 프로젝트의 디버깅을 찍어보는데 특정 토큰/명령어에 대해서 한 조각씩 들어오는 것에 대해 분기 네트워크를 타면 CPU의 분기예측 캐시가 제대로 쌓이질 않아서 case문 내의 모든 case를 중구난방으로 분기하면서 모두 체크하고 있다. (예를 들어 TOKEN_DEFINE을 찾기 위해서 ase TOKEN_BRACKET_OPEN.. case TOKEN_ALLOCATE... case TOKEN_EQUAL.... 같이 전부 중구난방으로 점프해가며 하나씩 체크한다. O(n)과 같은 최악의 케이스는 아니지만 10개의 케이스가 있으면 적어도 5개는 검색해버리는 짓을 벌임)

후반부로 갈수록 캐시가 쌓여서 바로 점프하는 모습은 보이지만 O(1)으로 바로 분기 없이 점프할수 있는 해시맵이 엄청나게 빠른건 사실인듯하다.

재귀하향식 파서로 구현했기 때문에 파서는 어쩔수 없이 switch network를 타버리긴 하지만 case가 극히 적어 분기 점프에 있어 큰 문제는 아니고 최대한 해시 맵 기반으로 짜는 것이 빠르다는 교훈은 얻은듯 하다.

3

밑바닥에서부터 연합우주 서비스를 만들고 있는데, 기능을 만들고 연합우주 연동을 붙이는 방식으로 접근하려니 자꾸 막히는 것 같음. 연합우주에서 어떻게 호환할지 먼저 생각해서 인터페이스를 만들고 거기에 기능을 갖다 붙이는 방식으로 접근해야 한다... 초기 단계는 수제코딩이 불가피한....

3
4
6
3
6

유시지(usage) 출력까지는 어떻게 구현 했다. 그런데 이건 쉬운 문제고, 도움말이 정말 어려운 문제인데…

optique <main?> $ deno run example.ts 
Usage: example.ts one [-a/--allow] -v/--value INTEGER ARG
       example.ts two [-f/--foo] -b/--bar VALUE
       example.ts three [-d/--deny] -t/--test INTEGER [-z/--baz] -q/--qux QUX
       example.ts nest foo [-a/--allow] -v/--value INTEGER ARG
       example.ts nest bar [-f/--foo] -b/--bar VALUE
Error: No parser matched.
2
6
2
2
1

이번 주말........ 파이콘으로 한참 바쁠 예정입니다.....

  • 파이콘 내내 한국 연합우주 개발자 모임 부스 지키기
  • 일요일 파이콘 발표
  • OSTEP xv6 H2 스타트 끊기...
3

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

파서 콤비네이터: 하스켈 초보자를 위한 파싱

박준규 @curry@hackers.pub

이 글은 하스켈 초보자를 위한 파서 컴비네이터에 대한 입문 튜토리얼입니다. 파싱은 프로그래밍에서 흔히 발생하는 작업이지만, 정규 표현식이나 문자열 조작만으로는 복잡한 형식을 다루기 어렵습니다. 저자는 `Text.ParserCombinators.ReadP` 라이브러리를 사용하여 파서 컴비네이터를 소개하고, 이를 통해 더 읽기 쉽고 유지보수가 용이한 파서를 작성할 수 있음을 보여줍니다. METAR 보고서 파싱 예제를 통해 `satisfy`, `many1`, `<|>`, `option` 등의 기본적인 파서 콤비네이터 함수를 설명하고, 펑터와 모나드의 개념을 활용하여 파서를 구성하는 방법을 안내합니다. 또한, 파싱된 데이터의 유효성을 검사하고, 결과를 더 의미 있는 데이터 타입으로 변환하는 방법을 제시합니다. 이 튜토리얼을 통해 독자는 파서 컴비네이터의 기본 원리를 이해하고, 실제 데이터 파싱 작업에 적용할 수 있는 능력을 얻게 됩니다. 마지막으로, 저자는 독자들에게 배운 내용을 바탕으로 전체 METAR 보고서를 파싱하는 라이브러리를 만들어 Hackage에 제출해 볼 것을 권장하며, 파서가 없는 데이터를 만났을 때 `ReadP`를 자신 있게 사용할 수 있기를 바랍니다.

Read more →
11

이제 아래와 같이 CLI 파서를 선언하면:

const parser = or(
  object("Group 1", {
    type: constant("group1"),
    allow: option("-a", "--allow"),
    value: option("-v", "--value", integer()),
    arg: argument(string({ metavar: "ARG" })),
  }),
  object("Group 2", {
    type: constant("group2"),
    foo: option("-f", "--foo"),
    bar: option("-b", "--bar", string({ metavar: "VALUE" })),
  }),
  merge(
    object("Group 3", {
      type: constant("group34"),
      deny: option("-d", "--deny"),
      test: option("-t", "--test", integer()),
    }),
    object("Group 4", {
      baz: option("-z", "--baz"),
      qux: option("-q", "--qux", string({ metavar: "QUX" })),
    }),
  ),
);

InferValue<typeof parser> 타입 함수가 아래와 같은 타입을 반환한다:

const _:
  | {
    readonly type: "group1";
    readonly allow: boolean;
    readonly value: number;
    readonly arg: string;
  }
  | {
    readonly type: "group2";
    readonly foo: boolean;
    readonly bar: string;
  }
  | {
    readonly type: "group34";
    readonly deny: boolean;
    readonly test: number;
    readonly baz: boolean;
    readonly qux: string;
  };

현재 구현한 파서 프리미티브는 option()argument() 두 개, 그리고 파서 컴비네이터는 or(), object(), tuple(), merge(), optional(), multiple() 정도. 그 외에 concat() 같은 것도 구현하고 싶긴 한데, 일단 도움말 먼저 만들어 보자.

1

이제 아래와 같이 CLI 파서를 선언하면:

const parser = or(
  object("Group 1", {
    type: constant("group1"),
    allow: option("-a", "--allow"),
    value: option("-v", "--value", integer()),
    arg: argument(string({ metavar: "ARG" })),
  }),
  object("Group 2", {
    type: constant("group2"),
    foo: option("-f", "--foo"),
    bar: option("-b", "--bar", string({ metavar: "VALUE" })),
  }),
  merge(
    object("Group 3", {
      type: constant("group34"),
      deny: option("-d", "--deny"),
      test: option("-t", "--test", integer()),
    }),
    object("Group 4", {
      baz: option("-z", "--baz"),
      qux: option("-q", "--qux", string({ metavar: "QUX" })),
    }),
  ),
);

InferValue<typeof parser> 타입 함수가 아래와 같은 타입을 반환한다:

const _:
  | {
    readonly type: "group1";
    readonly allow: boolean;
    readonly value: number;
    readonly arg: string;
  }
  | {
    readonly type: "group2";
    readonly foo: boolean;
    readonly bar: string;
  }
  | {
    readonly type: "group34";
    readonly deny: boolean;
    readonly test: number;
    readonly baz: boolean;
    readonly qux: string;
  };

현재 구현한 파서 프리미티브는 option()argument() 두 개, 그리고 파서 컴비네이터는 or(), object(), tuple(), merge(), optional(), multiple() 정도. 그 외에 concat() 같은 것도 구현하고 싶긴 한데, 일단 도움말 먼저 만들어 보자.

5
8

이번에 Amazon SES 메일 발송 처리를 추가해야 해서, Upyo 를 써 볼 수 있는 좋은 기회가 왔습니다. (SMTP 연동이어도 써볼 생각이었지만...)

README.md 의 Caution 을 보니 조금은 조심스럽지만, 한번 써보겠습니다!

Caution

This project is in early development and subject to change without notice.

개인적인 소망으로 https://unstable.upyo.org/logo.svg 로고에 한글도 들어가면 더욱 더 이쁠 것 같습니다!

4
5
0

안녕하세요. 개발자느님들에게 한가지 도움을 요청드립니다. 개발 1도 모르는 초초초초보가 독학으로 공부할 리액트 네이티브(앱 개발)와 파이썬 책을 추천 해주시면 감사하겠습니다. 참고로 파이썬은 https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=308908446 이 책을 생각하고 있습니다. 미리 감사드립니다~

2

feature-info?

まぁこれはnodeinfoのmeta使ってある程度決まったjsonを埋め込むようにすれば良さそうだけども。

こんな感じにするとか?

[
 "fep:8b32",
 "rfc:9421",
 "protocol:activitypub"
]
1
3
3

ast-grep 알듯 모를듯.. 아래같이 하면 innerHTML prop를 넘겨주고, 여닫는 사이에 내용은 없지만 self-closing 안 하는 케이스들을 잡을 수 있겠다.

id: innerhtml-not-self-closed
language: tsx
severity: error
rule:
  all:
  - kind: jsx_element
    pattern: <$TAG $$$ARGS></$TAG>
    all:
    - has:
        kind: jsx_opening_element
        has:
          kind: jsx_attribute
          regex: innerHTML
    - has:
        kind: jsx_closing_element
fix: "<$TAG $$$ARGS />"
1

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

OSTEP 독학 일지 - H.1

Jaeyeol Lee @kodingwarrior@hackers.pub

본 기술 포스팅은 OSTEP(Operating Systems: Three Easy Pieces) 교재를 독학하며 xv6 커널 환경에서 시스템 콜을 구현하는 과정을 담고 있습니다. xv6 개발 환경 설정부터 시작하여, Hello World를 띄우고, 나아가 H.1 Intro Project 과제인 `getreadcount` 시스템 콜 구현에 대한 여정을 상세히 다룹니다. 시스템 콜 정의 방법과, 유저 모드와 커널 모드 간의 전환 과정, 그리고 각 코드 파일들이 어떻게 유기적으로 연결되는지를 `write` 시스템 콜을 예시로 들어 설명합니다. 특히, `readcount` 변수의 원자성을 보장하기 위해 `_Atomic` 지시어를 사용하고, 다중 프로세스 환경에서의 테스트를 통해 그 효과를 검증합니다. 이 글은 xv6 커널의 시스템 콜 구조를 이해하고, 실제 시스템 콜을 구현하며 발생할 수 있는 문제점을 해결하는 과정을 통해 운영체제에 대한 깊이 있는 이해를 제공합니다.

Read more →
8

sap 백엔드 쪽 디벼보다 알게 된 점: 노드 의존도가 정말정말정말정말 높다. 트라이얼판이라 그런거 같긴 한데...

SAP BTP의 CAP 환경은 백엔드·프론트 모두 Node.js 생태계에 강하게 의존한다. 백엔드는 @sap/cds 같은 Node 모듈을 통해 서비스·DB·브로커를 다루고, 프론트는 SAP UI5/Fiori Elements 모듈을 가져다 쓰는 구조다. 실질적으로는 프론트와 백 모두 Node.js 기반으로 구성된다고 보는 게 편할듯.

실무에선 자바로 구축한다고들 하는데 일단은 대충 트라이얼만 돌려보면 백에 자바로 간다는 정도지 노드 비중이 딱히 줄어들 거 같진 않은.

1
1
1
1
4

LLM에게 코딩 시키기, 요즘 바이브 코딩이라 불리는 일을 해 봤다. 동기는, 리니어 공간에서의 이미지 리사이즈 작업이 ImageMagick 같은 전문? 툴 없이 파이썬 라이브러리로만으로 가능한가? 라는 호기심.

의외로, 알려진 알고리즘을 적용하라는 지시에는 LLM이 매우 효과적으로 대응했다. 정형화되어 있는 작업은 그게 조금? 전문적이라고 해도 찰떡 같이 알아듣고 탬플릿처럼 코드를 만들어냈다. 거대 LLM은 지식의 범위가 매우 넓다고 절감했다.

오히려 문제는 쉽다고 예측했던 색영역 프로필 처리에서 일어났다. 존재하지 않는 메소드들을 계속 있다고 하며 라이브러리 버전 문제라고 우겼다. 제미나이도, chatgpt도 동일했다. 해당 라이브러리 문서를 직접 찾아보니, LLM들이 가져온 오브젝트는 유저에게 노출되지 않은 내부 C 코드에 있는 것들이었다.; 오브젝트는 내부를, 메소드는 문서화 되어 있는 API의 것을 조합해서 코드를 만들어 낸 것이었다.

인간 개발자는, 자기 전문 영역이 아닌 한 라이브러리의 내부 코드까지는 잘 보지 않는다. 즉 API 문서를 기반으로 작업을 해 나간다. LLM은 정반대였다. 오픈소스 라이브러리라면, 오히려 문서보다도 외부 문서화되지 않은 소스 코드가 더 잘 학습 되는 자료였던 것이다. 그 과정에서 라이브러리의 전체 동작 과정을 잘 파악할 정도는 아니었기에 동작하지 않는 코드들을 계속 만들어 냈고.

매우 흥미로운 경험이었다. LLM은 인간과는 전혀 다른 학습, 구성 과정을 통해 코딩한다. 요구-설계-개념-문서-코드 라는 단계는 LLM에게는 의미가 없다. 프로그래머들은 이제 이세돌 이후 바둑 기사들이 겪었던 충격과 비슷한 변화를 나름? 받게 된 듯 하다.

4

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

Rust 컴파일러 개발 관련 명령어 모음집

notJoon @joonnot@hackers.pub

이 글은 러스트 컴파일러에 기여할 때 자주 사용하는 명령어와 작업 흐름을 소개합니다. 기본적인 빌드 명령어부터 특정 컴포넌트만 빌드하는 방법, 테스트 실행 및 `--bless`, `--force-rerun` 플래그 활용법을 설명합니다. Stage 시스템(Stage 0, 1, 2)을 구분하여 각 Stage의 역할과 사용법을 안내하고, UI 테스트 작성 규칙과 에러 주석 문법을 상세히 다룹니다. 또한, 직접 컴파일러 실행, 디버그 어설션 활성화, 백트레이스 활성화 등 디버깅 명령어와 컴파일러 버그 수정 워크플로우를 예시와 함께 제시합니다. 마지막으로, 자주 발생하는 문제와 해결법, 빌드 시간 단축 방법, 디버깅용 환경 변수 설정까지 다루어 러스트 컴파일러 개발에 실질적인 도움을 제공합니다. 이 글을 통해 러스트 컴파일러 기여자들이 효율적으로 개발하고 디버깅하는 데 필요한 지식을 얻을 수 있습니다.

Read more →
11
1
6

We'd like to recognize the valuable contributions from two developers who participated in Korea's (Open Source Contribution Academy) program. Both contributors identified important gaps in 's functionality and documentation, providing thoughtful solutions that benefit the broader ecosystem.

@gaebalgom개발곰 contributed PR #365, addressing issue #353 regarding NodeInfo parser compatibility, originally reported by @andypiper. The issue arose when Fedify incorrectly rejected documents from snac instances due to overly strict version string parsing that required semantic versioning compliance. Their solution improves the fallback behavior in the parseSoftware() function to handle non-SemVer version strings by parsing dot-separated numbers and defaulting to zero for missing components. The implementation includes thorough test coverage for various edge cases, including single numbers (3), two-part versions (2.81), and malformed version strings. This fix provides immediate compatibility improvements across the fediverse while maintaining backward compatibility, and will be included in Fedify 1.9. The contribution serves as an interim solution, with a more comprehensive fix planned for Fedify 2.0 (issue #366), where the NodeInfo software.version field will be changed from the SemVer type to a plain string to fully comply with the NodeInfo specification.

@z9mb1wwj contributed PR #364, resolving issue #337 by adding practical examples for Fedify's custom collection dispatchers feature. Custom collections were introduced in Fedify 1.8 but lacked clear documentation for developers seeking to implement them. Their contribution provides a comprehensive example demonstrating how to set up custom collections for tagged posts, including proper routing patterns, pagination handling, and counter functionality. The example includes mock data structures, shows how to configure collection dispatchers with URL patterns like /users/{userId}/tags/{tag}, and demonstrates the complete request/response cycle using federation.fetch(). This work provides developers with a clear, runnable reference that reduces the complexity of implementing custom collections in ActivityPub applications.

We appreciate these meaningful contributions that help make Fedify more accessible and robust for the entire ActivityPub community.

3
0
0