Hi, I'm who's behind Fedify, Hollo, BotKit, and this website, Hackers' Pub!

Fedify, Hollo, BotKit, 그리고 보고 계신 이 사이트 Hackers' Pub을 만들고 있습니다.

FedifyHolloBotKit、そしてこのサイト、Hackers' Pubを作っています。

嗨,我是 FedifyHolloBotKit 以及這個網站 Hackers' Pub 的開發者!

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

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

Vim이랑 Neovim은 어떻게 다를까?

Jaeyeol Lee @kodingwarrior@hackers.pub

주변에서 하도 계속 물어봐서 Vim과 Neovim의 결정적인 차이점을 문서로 남긴다. 당장은 생각나는대로 나열했기 때문에, 추후에 내용이 더 추가될 순 있다.

사용하는 언어부터 다르다 (VimScript / Lua)

Vim을 커스터마이징할때는 VimScript를 쓰지만, Neovim을 커스터마이징할때는 lua를 사용한다.

개인적으론 VimScript를 선호하진 않는데, vimscript 기반으로 짜여져 있는 플러그인의 소스코드를 읽는 것 자체가 고통스러웠던 경험이기도 했고, vimscript라는 언어 자체가 그닥 가독성이 좋은 편은 아니라고 생각한다. 기능적으로는 모자람이 없을 순 있으나, 읽을때도 고통스러운데 이걸로 스크립트를 짜라면 어지간하면 피할 것 같다.

반면. lua는 vimscript에 비하면 가독성이 적당히 나쁜 편은 아니다. 언어 자체의 기능으로 보자면 Python/Ruby/Javascript 등의 언어와 비교했을때 굉장히 좀 난해하게 느껴질 수는 있다.[1] 다만, lua는 macOS에서 사용하는 자동화 툴인 hammerspoon이라던가, 터미널 에뮬레이터인 wezterm이라던가 Unix 계열의 CLI 프로그램의 configuration을 작성하는데 있어서 사실상 De facto의 역할을 하고 있다. 언어 자체가 마음에 들지 않는 부분은 어느 정도 있긴 하지만, 가독성이나 개발편의성이 엄청 나쁜 것은 아니기 때문에 거부할 이유는 딱히 없다고 생각하고 쓰고 있다.

luarocks 패키지와 호환이 된다

Neovim을 커스터마이징할때 활용하는 lua는 luarocks라는 패키지매니저가 있기 때문에, 필요하다면 얼마든지 가져다 쓸 수 있다.

luarocks를 이용하는 Neovim 플러그인은 그렇게 많지는 않지만, (실질적인 쓸모의 유무를 떠나서) luarocks를 활용한 플러그인도 종종 보이긴 한다. 확실한건, lua 기반으로 개발되어 온 ecosystem을 등에 업고 언제든지 활용할 수 있다.

플러그인 생태계도 제법 괜찮은 편이다.

telescope / nvim-cmp / treesitter 같은 키워드 위주로만 찾아봐도 이걸 응용한 괜찮은 기능의 플러그인들을 많이 살펴볼 수 있다.

telescope

Neovim에서 사용할 수 있는 검색엔진이라고 생각해봐도 될 것 같다. 자세한 내용은 :help telescope 만 봐도 알 수 있겠지만, 파일 검색/패턴 검색 뿐만이 아니라 query를 넣을 수 있는 것이라면 어떤 것이든 다 해낼 수 있는 요술봉이라 생각한다.

예를 들면, git log를 검색한다던가, 현재 열어놓은 파일의 git history를 열람한다던가, 각각의 브랜치에 대한 git history를 표시하는 등의 git과 관련된 유용한 기능은 이미 네이티브로 들어가 있다.

여기서 좀 더 응용한다면, 아래의 예시와 같이 이용할 수 있다.

  • 프로젝트를 구성하는 소스코드의 클래스/모듈/함수/상수 검색
  • formatter/linter 오류 검색 (diagnostics)
  • GitHub 리포지토리의 issue/PR 검색 -- pwntester/octo.nvim 참고
  • throttling만 잘한다면 웹 요청이랑도 연결할 수 있다. 개인적으론 알라딘 검색 API와 연동하는 실험을 하고 있다.

nvim-cmp

이름에서 알 수 있듯이, 말 그대로 자동완성 기능을 위해 만들어진 플러그인 ecosystem이다. Neovim에서 자동완성 기능을 커스터마이징 해야 한다면, 바로 이 친구를 이용한다면 아주 간단한 문제가 된다.

pwd 기준의 경로 자동 완성 / emoji / 버퍼 내에서 반복적으로 사용되는 단어 위주의 자동완성 같은 사소한 것부터 Code Snippet / git commit sha1 해쉬 / GitHub author 자동 완성 / Language Server와 연동된 auto import 까지 입맛대로 자동완성 기능을 커스터마이징할 수 있다. 위에서 설명했던 telescope와 마찬가지로 쿼리할 수 있는 것이라면 어떻게든 활용할 수 있기 때문에 가능성은 무궁무진하다.

treesitter

사실 이게 왜 좋냐고 하냐면 많은 사람들에게 설득하는게 약간 어려운 난제이기도 하다. "굳이?" 라는 생각이 들 수도 있기 때문이다.

treesitter 자체는 파서를 만들어주는 제네레이터일 뿐이지만, 트리시터 기반으로 만들어진 파서가 활용도가 높기 때문에 유용함을 알고 있는 사람들은 잘 쓰고 있는 것 같다.

예를 들면, 커스텀 룰을 지정해주면 내가 탐험하고자 하는 소스코드의 범위를 탐색하는 것이 간단해진다. 왜냐면, scheme으로 커스텀 룰을 추가하는 것 자체가 일종의 트리 자료구조를 탐색하는 쿼리이기 때문이다.

알고리즘에 대한 배경지식이 있는 사람들한테는 좀 더 단순하게 설명하기도 하는데, "treesitter는 2차원 배열로 바라봐야 하는 소스코드를 트리로 바꿔서 생각할 수 있게 해준다." 이런 표현을 즐겨쓰는 편이다.

이에 대해 좀 더 직관적으로 와닿을 수 있는 예시는 ziontee113/syntax-tree-surfer인데, 함수가 정의되어 있는 위치를 바꾸는 demo 영상을 살펴보자. Syntax tree로 나타내면 두 함수의 위치는 Tree의 관점에서 보면 sibling으로 볼 수 있다. 두 함수가 정의되어 있는 위치를 바꾸는것은 사실상 트리 노드의 위치를 바꾸는 아주 간단한 문제로 환원이 된다.

그 외에도 두드러지는 점들

language server 지원도 나름 나쁘지는 않은 편인데, 제대로 세팅하려면 각각 language server마다 걸맞는 configuration을 해줘야 하는 수고로움이 생길 순 있지만, coc-nvim 세팅해놔도 개인적으론 크게 문제가 없었다.

Helix라는 신흥강자도 생기고 있는 모양이지만, 2023년 11월 기준, 2025년 3월으로는 크게 확 와닿을 정도로 삶에 혁신을 가져다 줄 만한 변화가 없기 때문에 당문간 관심을 가지는 건 보류


  1. lua라는 언어의 불편함에 대해서는 따로 글로 작성하게 될 것 같다. 그렇다고 아예 못 쓰겠다라고 느낄 수준은 아니지만, 여러가지 면에서 인지 부조화를 느끼게 하는 부분이 있다는 것은 부정할 여지가 없다. ↩︎

Read more →
0
1

10년간 프로그래밍 하면서 제가 프로그래밍을 좋아한다는 것은 확실히 알았습니다. 그런데, 좋아한다고 해서 아무 프로그래밍 관련 직업을 얻으면 되는지 항상 의문이었습니다.

저는 프로그래밍을 정말 좋아합니다만, 프로그래밍의 과정 자체를 즐기는 것이지, 프로그래밍을 사용하는 목적에 대해 생각해본 적이 거의 없었어요. 10년 동안!

심지어 대학생 때에는 프로그래밍이 너무 지긋지긋해서 그만 두어야 하나 고민도 했구요.

그런데, 졸업 후에 부트캠프에서 교육을 받기 시작하면서 역시 저는 프로그래밍을 그만둘 수 없다는 걸 알았습니다. 뿐만 아니라, 제가 좋아하는 것을 더 발견했습니다.

저는 제가 가진 지식을 공유하는 것에 보람을 느낍니다. 누군가에게 더 나은 방향을 제시하고, 더 좋은 방법을 고민하는 것이 즐겁습니다. 역시 저는 개발자가 되어야 한다고 생각하는 요즘이네요.

C2S보다 훨씬 간소화된 마이크로펍 스펙이 있는데 역시 아무도 지어ㅜㄴ하지 않는다는 것이 특징

다만 인증에 관련한 부분까지 제대로 언급돼 있고 q=config이라는 간소하지만 서버 기능을 알 수 있는 기능도 존재

I received a heartwarming about today!

@bglbgl gwyng shared in the FediDev KR Discord server:

I had trouble finding good resources explaining ActivityPub, but after reading through the Fedify docs from start to finish, I feel like I've actually digested it.

They also posted on their Hackers' Pub:

If you want to learn ActivityPub efficiently, just read the Fedify docs from beginning to end.

This makes all the documentation work worthwhile. Glad our docs are helping people understand not just Fedify, but itself.

0
0

@saschanazKAGAMI🏳️‍🌈🏳️‍⚧️ @makguksu막국수 네, ActivityPub에 S2S 인터랙션이 있고 C2S 인터랙션이 있는데요. 전자는 우리가 이미 잘 알고 있는 그것인데, 후자는 스펙에 언급만 되어 있을 뿐, 실제로 쓰이진 않고 있네요. Mastodon API가 그 역할을 가로채서 발전이 더딘 것 같습니다. 실제로 쓰려고 해봐도 인증이라든가 스펙에서 다루지 않는 부분이 아직 정해지지 않아서 뭘 어떻게 해야 할지 막막하기도 하고요…

네이버에서 이런 걸 왜 만들었을까?

Tamgu는 Prolog에서 영감을 받은 술어 엔진과 Haskell 언어에서 영감을 받은 기능적 기능을 갖춘 명령형 언어입니다. 이 세 가지 프로그래밍 스타일을 자유롭게 혼합할 수 있습니다.

https://github.com/naver/tamgu/tree/master

해커스펍 계정은 쓰기 전용으로, 우리인생은 읽기전용으로 사용하고 있다. 또는 기술 관련 콘텐츠는 해커스펍에 올리고 일상은 우리인생에 올리려고 한다.

클라이언트는 팬피를 쓰고 있는데 해커스펍은 마스토돈 API 구현이 안 되어 있어서 팬피에는 우리인생 계정을 연동했다.

그런데 팬피에서 재밌게 글을 읽다 보면 무심코 팬피에서(우리인생 계정으로) 해커스펍 글에 댓글을 달아서 뭔가 곤란하다⋯

그리고 해커스펍에 오신 분들은 거의 다 팔로우를 하고 있는데 동시에 우리인생에서도 팔로우를 해야해서(팬피에서 읽어야 하니까) 불편하다.

0
1

파워쉘 스크립트를 외부에서 콜하는 방법으로 ps2exe를 쓰다가 그냥 bat 파일 하나 만들어서 거기서 pwsh.exe 호출하면 된다는 사실을 발견... 쿨럭;; 레거시가 이렇게 쓰이나. ㅋㅋ;

네이버에서 이런 걸 왜 만들었을까?

Tamgu는 Prolog에서 영감을 받은 술어 엔진과 Haskell 언어에서 영감을 받은 기능적 기능을 갖춘 명령형 언어입니다. 이 세 가지 프로그래밍 스타일을 자유롭게 혼합할 수 있습니다.

https://github.com/naver/tamgu/tree/master

소프트웨어 개발자들이 자주 틀리는 외래어 표기법.

영어 틀린 표기 올바른 표기
app 어플
application 플리케이션 플리케이션
directory 디렉 디렉
front-end 트엔드 트엔드
message
method
release 릴리 릴리
repository 포지 포지

또 있을까요?

@hongminhee洪 民憙 (Hong Minhee) 꼭 외래어만 그런 건 아니지만 ㅐ와 ㅔ의 혼선이 제법 있는데, 이를테면 lag 랙("렉"으로 틀림) 같은 사례가 있습니다. 그 밖에는 daemon 다이먼(동계어인 demon에 이끌려 "데몬"이 널리 쓰이지만, 애초에 demon의 올바른 표기는 "디먼"임) 같은 게 생각나네요. 뭐 알아도 그렇게 안 쓰는 사람이 너무 많아서 대부분 틀린 표기로 쓰게 되지만...

We're excited to announce the release of Fedify 1.5.0! This version brings several significant improvements to performance, configurability, and developer experience. Let's dive into what's new:

Two-Stage Fan-out Architecture for Efficient Activity Delivery

now implements a smart fan-out mechanism for delivering activities to large audiences. This change is particularly valuable for accounts with many followers. When sending activities to many recipients, Fedify now creates a single consolidated message containing the activity payload and recipient list, which a background worker then processes to re-enqueue individual delivery tasks.

This architectural improvement delivers several benefits: Context.sendActivity() returns almost instantly even with thousands of recipients, memory consumption is dramatically reduced by avoiding payload duplication, UI responsiveness improves since web requests complete quickly, and the system maintains reliability with independent retry logic for each delivery.

For specific requirements, we've added a new fanout option with three settings:

// Configuring fan-out behavior
await ctx.sendActivity(
  { identifier: "alice" },
  recipients,
  activity,
  { fanout: "auto" }  // Default: automatic based on recipient count
  // Other options: "skip" (never use fan-out) or "force" (always use fan-out)
);

Canonical Origin Support for Multi-Domain Setups

You can now explicitly configure a canonical origin for your server, which is especially useful for multi-domain setups. This feature allows you to set different domains for WebFinger handles and URIs, configured through the new origin option in createFederation(). This enhancement prevents unexpected URL construction when requests bypass proxies and improves security by ensuring consistent domain usage.

const federation = createFederation({
  // Use example.com for handles but ap.example.com for ActivityPub URIs
  origin: {
    handleHost: "example.com",
    webOrigin: "https://ap.example.com",
  },
  // Other options...
});

Optional Followers Collection Synchronization

Followers collection synchronization (FEP-8fcf) is now opt-in rather than automatic. This feature must now be explicitly enabled through the syncCollection option, giving developers more control over when to include followers collection digests. This change improves network efficiency by reducing unnecessary synchronization traffic.

await ctx.sendActivity(
  { identifier: sender },
  "followers",
  activity,
  { 
    preferSharedInbox: true,
    syncCollection: true,  // Explicitly enable collection synchronization
  }
);

Enhanced Key Format Compatibility

Key format support has been expanded for better interoperability. Fedify now accepts PEM-PKCS format in addition to PEM-SPKI for RSA public keys. We've added importPkcs1() and importPem() functions for additional flexibility, which improves compatibility with a wider range of ActivityPub implementations.

Improved Key Selection Logic

The key selection process is now more intelligent. The fetchKey() function can now select the public key of an actor if keyId has no fragment and the actor has only one public key. This enhancement simplifies key handling in common scenarios and provides better compatibility with implementations that don't specify fragment identifiers.

New Authorization Options

Authorization handling has been enhanced with new options for the RequestContext.getSignedKey() and getSignedKeyOwner() methods. This provides more flexible control over authentication and authorization flows. We've deprecated older parameter-based approaches in favor of the more flexible method-based approach.

Efficient Bulk Message Queueing

Message queue performance is improved with bulk operations. We've added an optional enqueueMany() method to the MessageQueue interface, enabling efficient queueing of multiple messages in a single operation. This reduces overhead when processing batches of activities. All our message queue implementations have been updated to support this new operation:

If you're using any of these packages, make sure to update them alongside Fedify to take advantage of the more efficient bulk message queueing.

CLI Improvements

The Fedify command-line tools have been enhanced with an improved web interface for the fedify inbox command. We've added the Fedify logo with the cute dinosaur at the top of the page and made it easier to copy the fediverse handle of the ephemeral actor. We've also fixed issues with the web interface when installed via deno install from JSR.

Additional Improvements and Bug Fixes

  • Updated dependencies, including @js-temporal/polyfill to 0.5.0 for Node.js and Bun
  • Fixed bundler errors with uri-template-router on Rollup
  • Improved error handling and logging for document loader when KV store operations fail
  • Added more log messages using the LogTape library
  • Internalized the multibase package for better maintenance and compatibility

For the complete list of changes, please refer to the changelog.

To update to Fedify 1.5.0, run:

# For Deno
deno add jsr:@fedify/fedify@1.5.0

# For npm
npm  add     @fedify/fedify@1.5.0

# For Bun
bun  add     @fedify/fedify@1.5.0

Thank you to all contributors who helped make this release possible!

0
0

소프트웨어 개발자들이 자주 틀리는 외래어 표기법.

영어 틀린 표기 올바른 표기
app 어플
application 플리케이션 플리케이션
directory 디렉 디렉
front-end 트엔드 트엔드
message
method
release 릴리 릴리
repository 포지 포지

또 있을까요?

어제 타임라인에서 맥미니 서버로 어느정도 규모까지 버틸 수 있을지에 대한 고민이 지나가는걸 봤는데 1월부터 신형 맥미니로 이것저것 운영해본 경험 안에서는 오히려 문제는 서버 기계가 아니라 가정용 전원과 가정용 인터넷에서 터질 것 같다.

소프트웨어 개발자들이 자주 틀리는 외래어 표기법.

영어 틀린 표기 올바른 표기
app 어플
application 플리케이션 플리케이션
directory 디렉 디렉
front-end 트엔드 트엔드
message
method
release 릴리 릴리
repository 포지 포지

또 있을까요?

<Tracing the thoughts of a large language model>

LLM이 어떻게 생각하는지 추적하는 연구인데 아주 흥미롭다. LLM이 단순히 바로 다음에 올 높은 확률의 단어를 선택할 것이라고 생각했지만, 실제로는 미리 단어를 계획한 다음에 문장을 완성했다고. 다국어 구사와 암산 부분도 재미있다. 인간이 생각하는 방식과 크게 다르지 않은 것 같은데 기계가 정말 생각을 못한다고 할 수 있을까...

anthropic.com/research/tracing

GN⁺: 대형 언어 모델의 사고 과정을 추적하기
------------------------------
- Claude 같은 언어 모델은 사람이 직접 프로그램한 것이 아니라 방대한 데이터로 학습됨
- 학습 과정에서 문제 해결 전략을 스스로 학습하며, 이 전략은 수십억 개의 연산에 암호화되어 있음
- 결과적으로 모델 개발자조차도 Claude가 대부분의 작업을 어떻게 수행하는지 완전히 이해하지 못함
- Claude 같은 모…
------------------------------
https://news.hada.io/topic?id=20002&utm_source=googlechat&utm_medium=bot&utm_campaign=1834

better CSS에 대한 접근들(CSS-in-JS, Atomic CSS, Preprocessor)의 공통된 한계는 constraint solving 방식이 아니란 것이다.

다들 어떤 기존의 스타일을 '덮어쓰는' 방법, 근데 개중에 좀 잘 덮어쓰는 방법을 찾고 있다. 그런데 많은 경우, 뭔가를 덮어쓰려고 하고 있다면, 그건 사실 값을 덮어쓰는게 아니고 만족해야할 조건을 추가하고 싶은거다. 값을 덮어쓰는 것은 조건을 추가하는 방법 중 가장 강제적인 하나의 방법일 뿐이고. 즉, 디자인 시스템은 어떤 조건들의 합들로부터 실제 스타일을 구하는 방법이어야 하고, 개발자는 조건만 명시할 수 있어야 한다.

constraint solving을 잘 설계하고 구현하는게 어렵다 왜 이렇게 안 하냐고 하긴 좀 거시기하다. 그래서 나도 요즘 propagator를 공부중이다.

데이터에서 인과 관계를 아예 찾을 수 없냐면, 그렇지는 않습니다. 그 과정이 생각보다 조금 더 단계가 많을 뿐입니다. 인과 분석에 있어서, 인과 구조가 단순히 ‘뭐가 바뀌면 뭐가 바뀐다‘ 이상으로 다양하고, 어떤 식으로 다양할 수 있는지를 이해해야 인과 관계를 가정하고 조건적 사고를 진행할 수 있을 것입니다. 이를 고려하지 않고 너무 인과관계를 단순하게 보다보니 잘못된 내용을 호도하거나 아예 배제하는 경우가 종종 눈에 띄어 아쉽습니다. 관련하여 인과 관계 구조를 구분하고 각각의 분석법을 훑어볼 수 있게 정리해 보았습니다. https://cojette.github.io/posts/structureofcausation/

베이즈 확률론에서 사후 확률을 다룰 때 베타 분포를 가정한다. 베타 분포의 확률 밀도 함수는 다음과 같다.

f(x;α,β)=1B(α,β)xα1(1x)β1 f(x; \alpha, \beta) = \frac{1}{B(\alpha, \beta)} \cdot x^{\alpha-1}(1-x)^{\beta-1}

여기서 B(α,β)는 베타 함수이며 다음과 같이 정의된다.

B(α,β)=Γ(α)Γ(β)Γ(α+β) \mathrm{B}(\alpha,\beta) = \frac{\Gamma(\alpha)\Gamma(\beta)}{\Gamma(\alpha+\beta)}

해커스펍 계정을 만들었습니다. 권유와 초청 주신 분들 감사합니다.

저는 게임 기획자로 일하고 있습니다만, 요즘 몇년은 js/react로 제품에 들어갈 코드를 짜는 일이 많습니다. 최근에는 https://guji.jjme.me/ 에서 블로그를 쓰는 데 많은 에너지를 쓰고 있습니다.