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

System.IO.readFile 쓰지 마세요.

System.IO.readFile 쓰지 마세요.

System.IO.readFile 쓰지 마세요.

첫째, System.IO.readFileString 을 반환합니다. 이건 심각한 문제입니다. String 을 쓰지 마세요. 외부 세계와 I/O 를 할 때에는 ByteString 을 써야 합니다. 유니코드 문자열을 다룰 때에는 Text 를 쓸 수 있습니다. String 은 시간적으로도 공간적으로 비효율적입니다. 이건 어쩔 수 없습니다. 하스켈은 리눅스 커널보다 오래됐습니다. 그리고 하스켈이 String 을 만들 때에는 아직 하스켈에 모나드도 없던 시절이며, 타입 클래스가 과연 유용하겠는가를 두고 의견이 분분하던 시절이며, 파일 하나가 100 메가바이트가 넘어간다는 것이 과대망상으로 여겨지던 시절입니다. 특히 유니코드보다 더 먼저 나온 언어에 적절한 유니코드 문자열 타입이 있을 수는 없었습니다. 아무튼 String 은 레거시입니다. System.IO.readFile 로 그림 파일을 읽는 프로그래머는 사후세계에서 JPEG XL 파일을 십육진법 표기로 1 바이트씩 읽은 뒤 종이에 그려 내는 형벌에 처해집니다. String 을 쓰지 마세요.

둘째, System.IO.readFileFilePath 를 요구합니다. FilePath 도 사실 String 입니다. 그냥 별명(type synonym)이에요. 이것은 String 이기 때문에 비효율적이며, String 은 문자열이지 바이트열이 아니기 때문에 (인코딩을 전혀 통제할 수 없기 때문에) 파일 경로를 표현하는 타입으로 부적절합니다.

해결책: 먼저 System.OsPath 의 설명을 읽어 보세요. 그리고, file-io 패키지의 System.File.OsPath 모듈을 읽어 보세요. 여기 있는 함수들의 설명을 openBinaryFile 부터 하나씩 읽어보고 쓰세요. 이것들은 파일 경로에 OsPath 를 쓰기 때문에 String 의 비효율이 없고 인코딩도 올바르게 처리할 수 있습니다. 입출력 데이터에는 ByteString 을 씁니다. 바이트열을 유니코드 문자열로 변환할 때에는 예를 들어 Data.Text.Encoding.decodeUtf8Lenient 를 쓸 수 있습니다. 그럼 이제

  • 간단히 System.File.OsPath.readFile' 에게 OsPath 를 넘기고 ByteString 을 효율적으로 받아 와서 국밥처럼 든든하게 메모리에 올려 두고 작업을 하든지
  • 전국구 마법사라면 복대는 기본이라고 외치며 withBinaryFile앙갓썸Iteratee I/O 로 절묘하게 엮어서 뭔가 개멋있게 하든지
  • 하스켈 갓고수이기 때문에 흑마법사답게 보일러실 문을 따고 지하로 들어가 포… 포… 으악! P 로 시작하는 그것을 획득하여 누구도 예상할 수 없는 타이밍에 hGetBuf 의 암기를 슉. 슈슉. 슈슈슉. 슉. 날리든지

아무튼 이제는 String 을 놓아주어야 합니다.

1
3

12() ()에 할 Optique 發表(발표)()한 슬라이드 資料(자료)를 만들고 있는데, Optique具顯(구현) 細部事項(세부사항)까지 다뤄야 할 지, 아니면 使用者(사용자) 立場(입장)에서의 콘셉트나 API 같은 걸 爲主(위주)로 다뤄야 할 지 苦悶(고민)이네… 具顯(구현) 디테일을 다루려고 하면 주어진 發表(발표) 時間(시간)인 30() 안에 못 끝낼 것 같다는 느낌도 들어가지고…

3
1
3

Vim에서 Quickfix List라는 걸 처음 알게 되었다.

기존 코딩 흐름은

G 코딩 코딩 Vim을 닫는다. Vim을 닫는다. 코딩->Vim을 닫는다. cabal build cabal build Vim을 닫는다.->cabal build 에러 확인 에러 확인 cabal build->에러 확인 Vim을 연다. Vim을 연다. 에러 확인->Vim을 연다. 에러가 발생한 행(row)으로 간다. 에러가 발생한 행(row)으로 간다. Vim을 연다.->에러가 발생한 행(row)으로 간다. 에러가 발생한 행(row)으로 간다.->코딩

이랬는데 Quickfix List를 이용하면

G 코딩 코딩 :make :make 코딩->:make :copen :copen :make->:copen Enter를 눌러서 에러가 발생한 행으로 이동 Enter를 눌러서 에러가 발생한 행으로 이동 :copen->Enter를 눌러서 에러가 발생한 행으로 이동 Enter를 눌러서 에러가 발생한 행으로 이동->코딩

이렇게 Vim을 나가지 않고도 빌드 결과를 확인하고 에러가 발생하면 그곳으로 바로 점프할 수 있다!

.vimrc에 이렇게만 적으면 된다.

set makeprg=cabal\ build
6
2
2
1
3
10

하스켈에서 다음과 같은 에러를 만날 경우에

withFile: resource busy (file is locked)

readFile 대신 readFile'을 써보셔요!

  • readFile은 lazy 버전이고
  • readFile'은 strict 버전입니다!

System.IO 모듈 문서에 다음과 같은 설명이 있습니다.

경고: readFile 연산은 파일의 전체 내용을 모두 소비할 때까지 그 파일에 대해 부분적으로 닫힌(semi-closed) 핸들을 유지한다. 따라서 이전에 readFile로 연 파일에 대해(writeFile 등을 사용하여) 쓰기를 시도하면, 일반적으로 isAlreadyInUseError 오류와 함께 실패하게 된다.

3

사실 아직 이전한건 많이 없지만... 일단은 기존 DB랑 Redis를 tailnet으로 연결하고 클러스터에 사이드킥을 띄웠다 그리고 사이드킥 오토스케일링 기준을 CPU로 잡는게 조금 부적절하다고 생각했었는데 Prometheus로 사이드킥 큐 크기를 측정해서 그거 기반으로 스케일링하는게 좋을것같다 (내일)

1
Y = forall A. λf.
    let g = thunk (λx. (force f) ((force (unroll x)) x)) : thunk ((μX. thunk (X -> A)) -> A)
    in g (roll g : μX. thunk (X -> A))

를 타입 검사한 게 지난 일이었다.

(Y[λ⟨ isEven: nat -> bool, isOdd: nat -> bool ⟩]) (λm.
    λ⟨
        isEven: λn. match n {
            Nat.zero as n => return true
            Nat.succ as n => return (force m::isOdd) (n.0)
        }
        isOdd: λn. match n {
            Nat.zero as n => return false
            Nat.succ as n => return (force m::isEven) (n.0)
        }

)

이제 위 코드를 대충 타입 검사할 수 있는 거 같다.

이제 시맨틱은 필요한 만큼 구현했으니 드디어 신택스나 코드젠으로 넘어갈 수 있겠다.

3
5
4
2

하스켈에서 다음과 같은 에러를 만날 경우에

withFile: resource busy (file is locked)

readFile 대신 readFile'을 써보셔요!

  • readFile은 lazy 버전이고
  • readFile'은 strict 버전입니다!

System.IO 모듈 문서에 다음과 같은 설명이 있습니다.

경고: readFile 연산은 파일의 전체 내용을 모두 소비할 때까지 그 파일에 대해 부분적으로 닫힌(semi-closed) 핸들을 유지한다. 따라서 이전에 readFile로 연 파일에 대해(writeFile 등을 사용하여) 쓰기를 시도하면, 일반적으로 isAlreadyInUseError 오류와 함께 실패하게 된다.

4

방금 보이스피싱을 당할뻔 한거 같은데, 내가 법원등기서류를 수령 못했다면서 온라인으로 받아보라고

http://온라인검찰민원.kr/ 이 사이트로 들어가도록 유도했다. 보다시피 인증서가 없는 페이지이다. 그래서 바로 전화를 끊고 보이스피싱 신고사이트에 신고했다.

근데 나야 인증서 확인하고 이렇게 했지, 만약 우리 엄마였으면 그대로 당했을거같아서 기분이 안좋네..

3

오! 클로드 코드 사용량을 잠자는 동안 사용하지 못하는게 아까워서 이슈 7개 정도를 잠자기전에 일단 돌려두고 커밋까지 하라고 시켜놨다. 아침에 일어나서 워크트리에 커밋되어있는거 하나씩 머지하면서 테스트하고 코드 리뷰하고 있는데 엄청 좋은것 같다?!

container use를 써봐야겠다

4

사용 이틀째.

딱히 불편함은 없고 빠릿빠릿해서 좋다. iTerm2에 있던 그 많은 설정은 거의 필요 없었다는걸 새삼 느꼈다. Ghostty에서 설정을 열면(cmd+,) config 파일 고치라고 편집기가 뜬다 🤣

새 창이나 탭을 띄울 때 현재 위치에서 띄우지 못 하는데, 셀 통합이 불안정해서란다. iTerm2용 통합 스크립트를 다 막아도 "invalid OSC command: 1337;ShellIntegrationVersion=14;shell=zsh"가 찍히는 중. 공식 설명서 따라서 수동으로 읽었는데 되다 말다 그럼.

2

제품(타이피)의 기술부채와 타협하지 않고 위지윅 에디팅의 끝을 보려고 하시나 보네요. 기술 역량 면에서 참 대단하십니다.

구현체는 Rust로 작성되어 웹에서는 상술한 바와 같이 WASM으로 빌드 후 캔버스에 출력하며, 모바일에서는 각 플랫폼으로 네이티브 빌드되어 각 플랫폼의 윈도우 핸들을 통해 텍스쳐 버퍼에 바로 출력합니다. 이를 통해 웹뷰 없는 모바일 위지윅 에디터를 구현하고자 합니다.

— finn (@devunt) November 7, 2025
5
3

anyway just learned python typing invented a new kind of voldemort type -- one which when named doesn't actually name it

`float` and `int` are two distinct types in the type system

but if you write `x: float` that actually means `x: float | int`. but if you write `x: float | int` that means `x: float | int | int`.

anyway that's why `ty` has a `JustFloat` extension that is an actual alias for actual `float` that doesn't expand to `float | int`, so you can actual refer to... just float

play.ty.dev/a8714369-9b4c-4028

1
0
0
2
2
3
2
1

12() 6() 서울에서 開催(개최)되는 liftIO 2025에서 〈Optique: TypeScript에서 CLI 파서 컴비네이터를 만들어 보았다〉(假題(가제))라는 主題(주제)發表(발표)를 하게 되었습니다. 아직 liftIO 2025 티켓은 팔고 있으니, 函數型(함수형) 프로그래밍에 關心(관심) 있으신 분들의 많은 參與(참여) 바랍니다!

11
5
4

2025년 터미널 에뮬레이터 현황: 방랑하는 챔피언들 1위 Ghostty, 2위 Foot, 3위 Kitty가 상위권을 차지함 세 터미널 모두 Unicode 처리 정확도(WIDE/LANG/ZJW/VS16) 항목에서 최고 점수 기록 VTE 기반 터미널(GNOME Terminal, Terminator, LXTerminal 등) 은 하위권 유지 성능(Elapsed time) 측면에서 Foot, WezTerm, tmux, Konsole 등이 빠름 (100초 미만) iTerm2와 Extraterm은 CPU를 과도하게 사용하며, 테스트 시간을 단축해야 했음

과연 이번에도 "돌고 돌아 iTerm2로 돌아옴"이 될 것인가?

https://news.hada.io/topic?id=24130 https://www.jeffquast.com/post/state-of-terminal-emulation-2025/

1
1
1

근데 이전에 HN에서 codex가 뭔가 복잡하고 길게 해야하는 일을 더 잘 수행한다고 올린 글 때문에 테스트를 진행해본거라... 오히려 codex는 중간중간에 안껴들어도 일을 잘하고 claude code는 중간에 껴들어야 일을 잘하게되는 차이가 생길 수 도 있음.

이렇게 되면 병렬로 여러 일을 시키기에 codex가 더 적합할 수 도 있겠다는 가정을 해봄. 그래도 claude code가 결국 편할것 같은건 요즘 코딩하면서 테스트해본 결과 내 머리로는 최대 3개 이상의 작업을 동시에 병렬로 진행하는게 부하가 있음. 그래서 간단한 작업들 claude code web처럼 샌드박스에서 자동으로 돌려두는걸 codex로 해두고 내가 직접 상호작용하는 제품은 claude code를 사용하게 되지 않을까 싶음…

물론 어려운 작업들에서 작업 퀄리티 차이가 눈에 보일만큼 크다면 또 다르겠지만...

나중에 더 써보고 후기를 남겨보겠습니다.

2

codex에 비해서 claude code가 엄청 빠르다고 느꼈는데, 녹화해서 동시에 보면서 분석해봤는데 흥미롭다. gpt API 응답 속도나 claude API 응답 속도가 비슷했던 경험 때문에 인지 편향이 생겼을거라고 가정하고 녹화했다.

아주 간단한 테스트를 통해서 알게된 사실은 UX에서 오는 체감이 있는듯함. 동일한 코드베이스, 일, 프롬프트로 진행했는데 모든 일을 끝마치는데 걸린 속도는 비슷했음.

  1. 다만 Claude Code는 TODO 리스트를 통해서 일감 관리되고 있는 상호작용을 눈으로 확인할 수 있음
  2. 각 TODO 리스트가 끝났을때 중간 결과 같은것을 바로 알려줌
  3. 이 중간 결과를 보고 다음 명령어를 큐잉하게 되니 실질적으로 일 진행이 더 빠른 "느낌"을 받게됨.

두 제품 다 중간에 끼어들어서 일 방향을 수정하거나 일감을 큐잉하는등의 액션은 수행할 수 있는 것처럼 보여서 중간 결과를 알 수 있는게 복잡한 일을 하면 할 수록 큰 차이를 만들 수 있을것이라고 생각함.

이런 차이라면 학습하지 못한 자료에서 수행해야하는 일을 할때 조금 더 유의미한 차이가 생길것 같은데 나중에 테스트 해봐야겠다.

2
2
[Mon Nov 10 14:09:39 2025] Out of memory: Killed process 29426 (syncthing) total-vm:2418416kB, anon-rss:784kB, file-rss:3584kB, shmem-rss:0kB, UID:1000 pgtables:516kB oom_score_adj:200

1GB 짜리 SBC 에서 싱크싱을 systemd 유저 서비스로 띄워 두고 매일 몇 GB 정도 싱크를 하게 했더니 하루에 한 번씩 OOM 킬 당한다. 스와프 2GB 줘 봤지만 소용이 없다. 게다가 dmesg -T | grep "Out of memory" 에서 정확히 싱크싱만 잡히는 걸 보면 진짜로 싱크싱의 메모리 프레셔만 문제인 것 같다(스와프 아웃 속도가 문제가 아닌 것). 근데 다른 해결책도 보이지 않고, 또 저렇게 정기적으로 재시작당하게 냅둬도 아무 문제가 없어서, 냅두는 중…

2
2
1

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

⌨️ Mac에서 Karabiner로 외부 키보드 오른쪽 Alt 한/영 전환하기

조내일 @tomorrowcho@hackers.pub

맥북에서 윈도우 키보드의 오른쪽 Alt 키를 한/영 전환 키로 사용하기 위한 설정 과정을 소개합니다. macOS 기본 설정으로는 왼쪽과 오른쪽 Option 키를 개별적으로 제어할 수 없어 Karabiner-Elements를 사용한 사용자 정의 키 매핑이 필요합니다. Karabiner 설치 후, Simple Modifications을 통해 right_option 키를 F18로 매핑하고, macOS 키보드 단축키 설정에서 '입력 소스 선택'을 F18로 지정해야 합니다. 만약 F18 키가 제대로 등록되지 않는다면, Karabiner의 드라이버 확장 프로그램 권한이 허용되었는지, 그리고 Devices 탭에서 외부 키보드의 'Ignore vendor events' 옵션이 활성화되었는지 확인해야 합니다. 이 설정을 통해 윈도우 환경에 익숙한 사용자도 맥에서 편리하게 키보드를 사용할 수 있습니다.

Read more →
2
1
2
2