fedify-dev/hollo#56가 남아 있다면 해결하고, Hollo 패키지를 nixpkgs에 올릴 예정이다. 할 수 있다면 모듈도..
https://hackers.pub/@hongminhee/0196b961-2b85-7b25-b6cf-9900405d52eb
@bgl@hackers.pub · 81 following · 90 followers
슈티를 함께 만들 팀을 만들고 있습니다. 관심 있으신 분, 또는 잘 모르겠지만 이야기를 나눠보고 싶은 분도 bgl@gwyng.com으로 편하게 연락주세요.
fedify-dev/hollo#56가 남아 있다면 해결하고, Hollo 패키지를 nixpkgs에 올릴 예정이다. 할 수 있다면 모듈도..
https://hackers.pub/@hongminhee/0196b961-2b85-7b25-b6cf-9900405d52eb
Re: https://github.com/TryGhost/ActivityPub/issues/570#issuecomment-2873773122
@julian I believe you can use only its signature generation/verification functions without depending on Fedify's other features right now, e.g.:
import {
createProof, // Create OIP
createSignature, // Create LDS
signRequest, // Create HS
verifyObject, // Verify OIP
verifyRequest, // Verify HS
verifySignature, // Verify LDS
} from "@fedify/fedify/sig";
Also, Fedify is available on npm, and is used with Node.js or Bun!
Finally got to build this. Quick UI toggles to see all possible permutations of a post.
Previously was trying out Storybook.js but it's a bit too much for my needs (too many files, too many clicks).
CSS view transitions are pretty cool. More permutations need to be added later. And it's fun building this.
Every mathematical model of reality starts by introducing redundancy and ends by removing it.
5월 24일.... FediDev KR 스프린트 두번째 모임이 있을 예정입니다...
臺灣에서는 乖乖라는 菓子를 서버 같은 컴퓨터 옆에 符籍처럼 두는 風習이 있는데요. 乖乖는 中國語로 「말을 잘 듣는다」는 뜻인데다, 草綠色 封套가 順航을 象徵한다고 합니다. (그래서 여러 色 封套 中에서도 草綠色 封套만 效果가 있다고 여겨집니다.)
그런데 아내가 지난 臺北 出張에서 乖乖를 한 封紙 사 왔더라고요. 그래서 저도 이 인스턴스 hollo.social과 Hackers' Pub이 돌아가는 Mac mini 옆에 두기로 했습니다. 乖乖 封套에는 「請〈乖乖〉,不要當機」(말 잘 듣고, 다운되지 말아라)라고 썼습니다.
乖乖의 效驗은 流通期限까지 持續된다고 하는데요, 제가 둔 封紙는 2026年 4月 11日까지입니다. 그 때까지 다운이 안 되는지 한 番 지켜보도록 합시다. 🤣
I'm looking for a Markdown formatter, and I'm quite particular about my Markdown style. I don't want it to be formatted in a generic Markdown style. For instance, I prefer a style that adheres to rules such as:
~~~~
), and specify the language with a single space after the opening tildes (e.g., ~~~~ bash
).Are there any Markdown formatters that allow for such detailed customization of these elements? Or would I have to build one myself?
같은 이유로 Neovim을 못 쓰고 있다.
요즘은 #helix 에디터를 쓰고 있는데, .helix/languages.toml
파일로 프로젝트 별 구성을 쉽게 할 수 있어서 맘에 든다:
[language-server]
deno = { command = "deno", args = ["lsp"], config.deno.enable = true }
[[language]]
name = "javascript"
language-servers = ["deno"]
formatter = { command = "biome", args = [ "format", "--stdin-file-path", "buffer.js" ]
https://hackers.pub/@hongminhee/0196c20f-71e3-7a7c-920c-2f4cf8790b13
해커스펍이 파이콘 커뮤니티 후원사로 선정이 되어서 이번엔 진짜 해커스펍 로고가 필요해졌다는 소식입니다..... 파이콘 홈페이지에 로고랑 같이 커뮤니티 소개가 올라갈 예정임....
Cursor 탭 자동완성의 짧은 역사
------------------------------
- Cursor의 *최고 수준 탭 자동완성 기능* 은 Supermaven의 Babble 모델 인수로 가능해졌으며, 이 모델은 *최대 100만 토큰 컨텍스트 창* 과 *250ms의 낮은 지연 시간* 을 자랑함
- 기존 LLM 기반 자동완성은 caret 위치 이후 코드만 예측하는 한계가 있었으나, Babble은 *git diff 기반 편집 시퀀스 학습* 을 통해…
------------------------------
https://news.hada.io/topic?id=20845&utm_source=googlechat&utm_medium=bot&utm_campaign=1834
中學生 때 내가 컴퓨터를 잘 안다고 생각해서 先生님들이 나에게 學校 電算室을 맡겼는데, 어릴 때 公私를 모르고 學校 서버를 私用했던 것이 생각난다. Windows 서버였어서 IIS에 PHP를 붙여서 썼었다.
그럼 PCB 크기가 달라지면 케이스도 내가 만들어야함
→ 手作り 케이스 내 손으로 만들 자신 없어서 ergogen으로 선언형으로 우회
roBa랑 겹쳐보면 이정도 차이
<1945년 해방 직후사>를 읽었다.
1945년 8월부터 12월까지를 중점적으로 다룬다. 현대 한국이 기원하는 결정적인 시기였음에도 불구하고, 해방 직후 어떤 일이 있었는지는 잘 알려져 있지 않다. 고립된 조선총독부와 무능한 미군정, 그리고 친미-반공-기독교-엘리트 조선인들이 빚어낸 역사. 오늘날 한국의 보수주의가 이들로부터 출발했다는 사실과 아직도 이들로부터 정통성을 찾고 있다는 사실이 비극이다.
https://pedia.parksb.xyz/history-immediately-after-liberation-in-1945 #독서
bgl gwyng shared the below article:
정진명의 굳이 써서 남기는 생각 @index@guji.jjme.me
서명: 도둑의 도시 가이드
저자: 제프 마노(Geoff Manaugh)
역자: 김주양
출판사: 열림원
출간일: 2018년 6월 20일
원서명: A Burglar's Guide to the City
원서 출간일: 2016년
은평구립도서관에서 장기대여한 39권의 책 중, 『궁극의 문자를 찾아서』에 이어 두 번째로 읽는 책입니다. 도시 설계와 건축에 관심이 있어서 그것을 범죄자의 입장에서 다룬 책이라고 하여 읽게 되었습니다.
책의 핵심 아이디어는 다음과 같습니다. 건축물을 설계하는 사람들은, 다소의 예외는 있을 수 있지만, 건축물을 이용하는 사람들이 이용하는 목적을 효율적으로 달성할 수 있도록 설계합니다. 그런데 도둑, 혹은 침입절도자(burglar)들은 설계자들이 상정하지 않고, 이용자들이 상상하지 못한 방법으로 건물을 이용한다는 것이죠.
맺는말에 가까운 성격인 마지막 장까지 총 일곱 장에 걸쳐 다양한 사람들을 만나며 여러 일화를 소개하는 구성으로, LA를 헬리콥터로 순찰하는 대원, 자물쇠 풀기 스포츠 관련자, 유명한 도둑을 검거한 경찰, 심지어는 게임 『시프』를 만든 디렉터나 『범죄의 재구성』, 『도둑들』의 최동훈까지 인터뷰하거나 업무에 동행하며(최동훈의 인터뷰는 책에 반영되지 않았습니다) 다양한 이야기를 보고 듣는 것이 이 책의 강점이라고 할 수 있겠습니다.
저는 게임을 하면서 게임의 진행 상태를 개조해서 플레이하곤 하는데, 이 책을 읽으면서 그런 행동들과의 유사성을 생각하기도 했습니다. 제가 진행상태나 게임 데이터를 개조하는 것은 대개 이 게임의 개발자가 의도를 가지고 어떤 경험을 주려고 했지만 도무지 그 목적을 달성하기 어려워보이는 게임 디자인에 항의하는 성격에(다음 단계로 넘어가려면 결과가 달라지지 않는 행동을 너무 많은 회수 반복해야 한다거나 하는 경우가 여전히 많은 게임에 있습니다) 가깝습니다만, 아무튼 목적 면에서는 일치한다고 생각합니다. 제가 하는 건 백화점에 들어가서 1층부터 8층까지 아무것도 안 보고 9층까지 순간이동해서 푸드코트에서 밥만 사 먹고 건물 밖으로 순간이동하는 행동에 가깝다고 생각합니다. 이 책에서 다루고 있는 것과는 다소 성향이 다르지요. 멀티플레이어 게임에서 핵을 쓰는 행위는 좀 더 명확하게 누군가에게 피해를 주기 때문에 좀 더 침입절도와 비슷하다고 할 수 있을까요? 음, 그런 기준으로 비교를 해도 될지 잘 모르겠습니다.
이것저것 생각나는 바가 많은 책이었습니다. 서울시가 광화문광장과 시청광장을 무력화하는 것도 생각이 나고, (무허가로) 마천루의 벽면을 오르거나 파쿠르를 하는 사람들 생각도 나고, 게임 『와치 독스』 생각도 나고요. 프로그래밍 쪽에서부터 관심을 가지게 된 『패턴 랭귀지: 도시, 건축, 시공』 생각도 나고요. 이 책은 다른 도서관에 있어서 빌리자면 빌릴 수는 있겠는데, 두께를 생각하면 완독하기 위해 빌릴 수는 없을 것 같네요. 반체제적이고 저항적인 건축/건축 오용(책의 표현을 빌림)을 다룬 책이 더 있으면 읽어보고 싶습니다.
안녕하세요, 업으로 프로그래밍을 하고 있는 컴퓨터 학부생 김무훈입니다.
현재 3년차 웹 프론트엔드 개발자로서, 다가오는 7월부터 함께할 정규직 포지션을 적극적으로 찾고 있습니다.
최근 학과 사무실에서 졸업 요건을 확인한 결과, 전공 필수 한 과목과 전공 선택 2학점(총 5학점)이 남아있음을 확인했습니다.
본래는 다음 2학기까지 수료 후 내년 2월에 졸업할 예정이었으나, 교수진과 상의한 결과 취업 및 재직이 확정된다면 수업 이수 방식을 보다 유연하게 결정할 수 있다는 긍정적인 답변을 받아 적극적으로 조기 취업을 추진하게 되었습니다.
이는 전공 필수 과목의 경우에만 해당이 되는 문제이고, 전공 선택 2학점의 경우 앞으로의 여름 학기 현장 실습 또는 다음 학기에 개설되는 하나의 원격 강의로 대체하여 문제가 없는 상태입니다.
지금까지의 업무 경험과 프로젝트는 아래의 포트폴리오에서 확인하실 수 있습니다.
📌 경력기술서 겸 포트폴리오 페이지: https://www.frontend.moe/portfolio/
좋은 인연을 찾을 수 있도록, 많은 관심과 연락 부탁드립니다!
I recently set myself the exercise of using modern automated tools - in particular, a combination of the #GithubCopilot large language model and the dependent type matching tactic #canonical - to try to semi-automatically formalize in #Lean a one-page proof provided by a collaborator of the #EquationalTheoriesProject (Bruno Le Floch). With these tools, I was able to more or less blindly do the formalization in 33 minutes, withou any real high level conception of how the proof proceeded. It was a very different style to how I usually formalize results, but was workable for this type of technical, non-conceptual argument where the main issue is to get the details correct rather than the "big picture".
I recorded my attempt at https://www.youtube.com/watch?v=cyyR7j2ChCI . See also additional discussion at https://leanprover.zulipchat.com/#narrow/channel/458659-Equational/topic/Alternative.20proofs.20of.20E1689.E2.8A.A2E2 . The final proof (which is far from optimized, but got the job done) can be found at https://github.com/teorth/estimate_tools/blob/master/EstimateTools/test/equational.lean
개발하는 연친분들이 페디버스에 기여한다는 명목으로 어셈블할 수 있는 절호의 기회!
https://social.silicon.moe/@kodingwarrior/114482624739936977
오픈소스 장점: 고쳐쓸 수 있다 🔨
5월 24일(土) 한국 연합우주 개발자 모임(FediDev KR)에서 두 번째 스프린트 모임을 개최합니다! 장소는 뚝섬역 5번 출구쪽에 위치한 튜링의 사과(@TuringAppleDev튜링의 사과)입니다.
참고로 스프린트 모임이란 함께 모여서 오픈 소스 코딩을 하는 자리인데, 한국 연합우주 개발자 모임의 스프린트에서는 새로운 연합우주 서비스나 앱을 개발하거나, 번역이나 문서에 기여하는 등 연합우주와 관련된 다양한 오픈 소스 활동을 모여서 함께 합니다. 지난 스프린트 모임의 기록을 스프린트 블로그(@sprints.fedidev.kr한국 페디버스 개발자 모임)에서 살펴보실 수 있습니다.
저는 그날 Fedify, Hollo, Hackers' Pub에 기여하시고자 하는 분들을 옆에서 도와드릴 예정입니다. Fedify, Hollo, Hackers' Pub에 기여해보고 싶었던 분들이 계시다면 모임에 참가하여 저와 함께 스프린트를 해보는 것도 좋을 것 같습니다.
이번 모임에 관심이 있으신 분은 행사 신청 페이지를 참고하시기 바랍니다.
추천사 썼던 책이 집에 도착은 했는데,
제.. 제가요..?
모드 됨...
예전부터 생각하던 건데, git reset --hard
를 인자 없이 쓰면 git stash
로 동작하거나, 아니면 적어도 인자 없이 썼을 때 오류가 나게끔 설정할 수 있었으면 좋겠다. 별 생각 없이 날려도 괜찮겠지 싶어서 git reset --hard
쳤다가 몇 분 뒤에 후회하는 경우가 종종 있다.
너무 편하다.......
The abbreviation #a11y itself is not very accessible. #accessibility
국산 코드에서 gubun
같은 식별자를 볼 때, 우리는 그게 왜 type
내지는 discriminator
가 아닌지 물을 것이 아니라, 어째서 구분
이 될 수 없는지를 물어야 한다.
아니 뭐 다 좋은데, 투자금을 "쓸어 담았다" 라고 표현하면 어떡하냐. 기자 양반님아...
bgl gwyng shared the below article:
정진명의 굳이 써서 남기는 생각 @index@guji.jjme.me
"유머는 그 유머가 왜 웃긴지를 설명해야 하는 순간 실패"라는 말이 있다. 나는 이 말을 별로 좋아하지 않는다. 일단 그 말이 틀렸다고 말하고 싶은 건 아니다. 유머를 설명해야 한다면, 많은 사람들이 그걸 바로 받아들이거나 동의하는 데 실패했다는 이야기이고, 대화의 흐름이 끊어지고, 유머를 발화함으로 달성하고자 했던 여러 목표들이 달성되지 않는 경우가 많은 것은 부정할 수 없기 때문이다.
하지만 피터의 법칙과 유사하게, 대부분의 유의미한 말은 그 말을 적용하는 것이 적절하지 않은 지점까지 재생산된다. 이 말의 경우 적절하지 않은 지점은 어디일까? 유머에도 피터의 법칙 같은 건 존재한다. 잘 작동하던 유머가 있으면, 그 유머는 퍼지게 되어 있다. 리트윗과 좋아요가 있고 밈 재생산에 적합한 매체에서는 특히 쉽다. 처음에는 잘 작동하는 유머 또한 피터의 법칙처럼 실패하는 지점까지 퍼질 수 있고, 그 지점에서 '설명'해야 하는 유머가 된다. 그 시점에서 누군가는 이런 말을 할 수 있다. "(나한테) 설명이 필요한 유머라니, 이것은 (객관적으로) 실패한 유머이다." 나는 이 지점이 싫다. 그냥 널리 퍼진 유머를 발신한 사람이 자연 현상처럼 받아들여야하는 일일지도 모르겠지만.
반대 방향의 이야기이지만, 나는 xkcd, SMBC가 왜 재미있는지, 일본어로 올라오는 수많은 팬아트가 왜 재미있는지를 알기 위해서 그 유머를 가능하게 하는 기반 지식을 찾아보는 편이다. 나만 그런 것은 아니다― 세상에는 explain xkcd같은 사이트도 있다. 나는 유머를 삶에서 분리해낼 수 없는 사람이다. 그런 나한테는 설명이 필요한 유머야말로, 내가 모르는 세상을 향해 열린 창이다.
JetBrains사의 C/C++ IDE인 CLion은 이제 비상업적 용도로는 무료로 쓸 수 있다고 한다.
CLion Is Now Free for Non-Commercial Use - https://blog.jetbrains.com/clion/2025/05/clion-is-now-free-for-non-commercial-use/
우리나라 남자 양궁 대표들이 세계 신기록을 세웠는데...3명이서 24발의 화살을 모두 10점에 쏘아 240점으로 세계 신기록을 세웠다고...ㅎㅎㅎㅎㅎㅎㅎㅎ
여태까지 地下鐵에서 다음 驛이 어딘지 알 수 없을 때마다 머릿속에서 온갖 陰謀論을 떠올렸었는데… 이제라도 다음 驛이 常時 表示된다니 多幸이네. (내가 주로 떠올렸던 陰謀論은 廣告를 더 많이 보게 하려고 다음 驛을 가끔만 表示한다는 것이었다.)
GitHub 저장소 코드를 분석해 AI로 문서화하는 도구. 다이어그램을 적극적으로 활용해 아키텍처를 쉽게 이해할 수 있고, 문서의 깊이와 정확도도 높다. 여러모로 <오픈 소스 소프트웨어 아키텍처>를 읽으며 아쉬웠던 부분들을 커버해주는 프로젝트. https://deepwiki.com/
개발자의 저주: 고치는 능력을 가진 자의 무한한 책임감
------------------------------
- 사소한 자동화를 반복하다 보면 어느 순간 모든 도구와 시스템이 *고쳐야 할 대상* 으로 보이게 되는 *인지의 임계점* 에 도달하게 됨
- 기술력이 쌓일수록 문제를 단순히 인식하는 것을 넘어 *책임처럼 느끼게 되는 감정의 무게* 를 가지게 됨
- *고치고자 하는 욕구* 는 단순한 생산성 향상을 넘어서 감정…
------------------------------
https://news.hada.io/topic?id=20735&utm_source=googlechat&utm_medium=bot&utm_campaign=1834
안녕하세요, 숫자상입니다.
먼 미래에는 어떻게 될 지 잘 모르겠지만, 일단 코딩 에이전트한테 LSP를 툴로 쥐어 줘야 하는 게 아닌가 하는 생각이 요즘 많이 든다.
AI에 대한 SW 엔지니어들의 자신감은 "어쨌거나 업계 내에서 만드는거라서-" 인거 같다. 손바닥 위에 있다는 감각(얼추 맞긴 하다).
타 직업군은 AI나 LLM 솔루션 자체를 다루는데도 한계가 있거니와(아무래도 fork떠서 고친다거나 할순 없으니까) 결과물도 자기 의사와 관계 없이 학습당하고 있기 때문에…
아예 거스를 수 없는 것이기 때문에, 타 분야에서는 오히려 공격적으로 자기 분야에 특화된 모델을 만들고, 기존 저작물들을 학습으로 부터 보호해서 우선권을 선점 하는게 그나마 좀 더 낫지 않을까?
근데 후자는… 테크기업이 양아치라서 잘 안될거같다.
Hackers' Pub은 기본 Markdown 문법 외에 다양한 확장 문법을 지원합니다. TeX을 통한 수식, 각주, 경고 박스(admonitions), 표, Graphviz를 통한 도표, 코드 블록에서 특정 줄만 강조하기 등…
마땅한 기술 블로깅 플랫폼을 못 찾았다면, Hackers' Pub도 고려해 보세요!
bgl gwyng shared the below article:
Ailrun (UTC-5/-4) @ailrun@hackers.pub
이 글은 "논리적"이 되는 두 번째 방법인 논건 대수를 재조명하며, 특히 컴퓨터 공학적 해석에 초점을 맞춥니다. 기존 논건 대수의 한계를 극복하기 위해, 컷 규칙을 적극 활용하는 반(半)공리적 논건 대수(SAX)를 소개합니다. SAX는 추론 규칙의 절반을 공리로 대체하여, 메모리 주소와 접근자를 활용한 저수준 자료 표현과의 커리-하워드 대응을 가능하게 합니다. 글에서는 랜드(∧)와 로어(∨)를 "양의 방법", 임플리케이션(→)을 "음의 방법"으로 구분하고, 각 논리 연산에 대한 메모리 구조와 연산 방식을 상세히 설명합니다. 특히, init 규칙은 메모리 복사, cut 규칙은 메모리 할당과 초기화에 대응됨을 보여줍니다. 이러한 SAX의 컴퓨터 공학적 해석은 함수형 언어의 저수준 컴파일에 응용될 수 있으며, 논리와 컴퓨터 공학의 연결고리를 더욱 강화합니다. 프랭크 페닝 교수의 연구를 바탕으로 한 SAX는 현재도 활발히 연구 중인 체계로, ML 계열 언어 컴파일러 개발에도 기여할 수 있을 것으로 기대됩니다.
Read more →After reviewing FEP-5624: Per-object reply control policies and GoToSocial's interaction policy spec, I find myself leaning toward the latter for long-term considerations, though both have merit.
FEP-5624 is admirably focused and simpler to implement, which I appreciate. However, #GoToSocial's approach seems to offer some architectural advantages:
I wonder if creating an #FEP that extracts GoToSocial's interaction policy design into a standalone standard might be worthwhile. It could potentially serve as a more comprehensive foundation for access control in #ActivityPub.
This is merely my initial impression though. I'd be curious to hear other developers' perspectives on these approaches.
#FEP5624 #fedidev #fediverse #replycontrol #interactionpolicy
@ailrunAilrun (UTC-5/-4) LLM 요약 대신 글 앞 부분을 보여주는 옵션을 설정에 만들어 보도록 하겠습니다. 😅
@ailrunAilrun (UTC-5/-4) 옵션을 추가했습니다! 설정 → 환경 설정 → AI가 생성한 요약 선호 옵션을 해제하시면 됩니다.
<section>
버리고 <article>
써야 하는 이유 #a11y
〈section〉
태그 안의 글에 헤딩(제목)을 포함하면 화면상에서는 그 헤딩들이 논리적인 순차 구조를 가지고 있는 것처럼 보인다. 하지만 이는 순전히 시각적인 것일 뿐 보조 기술과 연동된 구조 정보가 아니다.〈section〉
태그의 용도는 무엇이고, 헤딩을 어떻게 코딩해야 보조 기술 사용자에게 정말 중요한 구조 정보를 전달할 수 있을까?
세상엔 재미있는 사람들이 많아 제트엔진 내부의 공기 흐름을 직접 볼 수도 있다. ....... 아니 세상에 너무 재밌잖아!
SolidJS는 React처럼 Reactivity 코어가 분리되어 있지않은거 같다? solid-three, solid-native 등의 프로젝트들이 있는데 2년넘게 관리되고 있지않다.
@bglbgl gwyng 커스텀 렌더러 (Solid에선 Universal Rendering이라고 부름) 지원 자체는 잘 되어 있는데 그냥 커뮤니티 망치가 부족해서 유지보수가 안 되는 것에 가깝고 😅 이런 물건은
왜인진 도저히 모르겠지만 나름 관리가 잘 되고 있습니다
프로젝트 이름 예쁘게 짓는 방법 구합니다
프로젝트 이름 예쁘게 짓는 방법 구합니다
캘린더 이벤트로 변환이 가능한 데이터들 (예약 서비스의 예약 내역, 캘린더 양식이 아니어서 변환이 필요한 데이터, 매우 낮은 에러 레이트 리밋(?) 같은 이유로 인하여 일반적인 캘린더 동기화에 넣기 불안한 출처)를 모아다가 주로 사용하는 캘린더 서비스로 보내주는 서비스를 만들려고 합니다.
현재 Hackers' Pub은 Fresh 2.0 알파 버전을 사용하고 있는데, Fresh 자체의 한계점도 많이 느꼈고 무엇보다 최근 몇 달 사이에 정식 릴리스를 향한 진전이 보이지 않기에 GraphQL 준비가 끝나면 프런트엔드를 SolidStart로 점진적으로 옮겨가고자 한다.
아재들을 노리는 곳인가하고 들어가 봤습니다. 함수랑산악회. 여기에, 소속된 분이 계실 수도 있겠습니다. 곳곳에 소규모 조직들이 있네요.
bgl gwyng shared the below article:
洪 民憙 (Hong Minhee) @hongminhee@hackers.pub
TypeScript로 백엔드 서버를 개발하면서 적절한 ORM 선택은 항상 중요한 결정 중 하나입니다. 최근 제 프로젝트에서 Drizzle ORM과 Kysely를 모두 사용해 볼 기회가 있었는데, 개인적으로는 Drizzle ORM이 더 편리하고 생산성이 높았던 경험을 공유하고자 합니다.
Drizzle ORM은 TypeScript용 ORM으로, 타입 안전성과 직관적인 API를 강점으로 내세우고 있습니다. 스키마 정의부터 마이그레이션, 쿼리 빌더까지 풀스택 개발 경험을 제공합니다.
Kysely는 “타입 안전한 SQL 쿼리 빌더”로 자신을 소개하며, 타입스크립트의 타입 시스템을 활용해 쿼리 작성 시 타입 안전성을 보장합니다.
두 도구 모두 훌륭하지만, 제 개발 경험에 비추어 볼 때 Drizzle ORM이 몇 가지 측면에서 더 편리했습니다.
Drizzle ORM의 스키마 정의 방식은 매우 직관적이고 선언적입니다:
import { pgTable, serial, text, integer } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
email: text('email').unique().notNull(),
age: integer('age')
});
Drizzle ORM은 이 스키마 정의로부터 자동으로 CREATE TABLE
SQL을 생성할 수 있어, 스키마와 코드가 항상 동기화되어 있습니다.
반면 Kysely는 타입 정의에 더 중점을 두고 있어 스키마와 타입 정의가 분리되는 경향이 있습니다:
interface Database {
users: {
id: Generated<number>;
name: string;
email: string;
age: number | null;
};
}
이 타입 정의는 TypeScript 코드에서 타입 안전성을 제공하지만, 이 타입 정의만으로는 CREATE TABLE
SQL을 생성할 수 없다는 것이 결정적인 단점입니다. 실제로 테이블을 생성하려면 별도의 SQL 스크립트나 마이그레이션 코드를 작성해야 합니다. 이는 타입과 실제 데이터베이스 스키마 간의 불일치 가능성을 높입니다.
Drizzle의 접근 방식이 데이터베이스 스키마와 TypeScript 타입을 더 긴밀하게 연결해주어 개발 과정에서 혼란을 줄여주었습니다.
Drizzle ORM의 마이그레이션 도구(drizzle-kit
)는 정말 인상적이었습니다. 스키마 변경사항을 자동으로 감지하고 SQL 마이그레이션 파일을 생성해주는 기능이 개발 워크플로우를 크게 개선했습니다:
npx drizzle-kit generate:pg
이 명령어 하나로 스키마 변경사항에 대한 마이그레이션 파일이 생성되며, 이를 검토하고 적용하는 과정이 매우 간단했습니다.
반면 Kysely의 마이그레이션은 본질적으로 수동적입니다. 개발자가 직접 마이그레이션 파일을 작성해야 하며, 스키마 변경사항을 자동으로 감지하거나 SQL을 생성해주는 기능이 없습니다:
// Kysely의 마이그레이션 예시
async function up(db: Kysely<any>): Promise<void> {
await db.schema
.createTable('users')
.addColumn('id', 'serial', (col) => col.primaryKey())
.addColumn('name', 'text', (col) => col.notNull())
.addColumn('email', 'text', (col) => col.unique().notNull())
.addColumn('age', 'integer')
.execute();
}
async function down(db: Kysely<any>): Promise<void> {
await db.schema.dropTable('users').execute();
}
이러한 수동 방식은 복잡한 스키마 변경에서 실수할 가능성이 높아지고, 특히 큰 프로젝트에서는 작업량이 상당히 증가할 수 있었습니다.
하지만 Kysely의 마이그레이션에도 두 가지 중요한 장점이 있습니다:
TypeScript 기반 마이그레이션: Kysely의 마이그레이션 스크립트는 TypeScript로 작성되기 때문에, 마이그레이션 로직에 애플리케이션 로직을 통합할 수 있습니다. 예를 들어, S3와 같은 오브젝트 스토리지의 데이터도 함께 마이그레이트하는 복잡한 시나리오를 구현할 수 있습니다. 반면 Drizzle ORM은 SQL 기반 마이그레이션이므로 이러한 통합이 불가능합니다.
양방향 마이그레이션: Kysely는 up
과 down
함수를 모두 정의하여 업그레이드와 다운그레이드를 모두 지원합니다. 이는 특히 팀 협업 환경에서 중요한데, 다른 개발자의 변경사항과 충돌이 발생할 경우 롤백이 필요할 수 있기 때문입니다. Drizzle ORM은 현재 업그레이드만 지원하며, 다운그레이드 기능이 없어 협업 시 불편할 수 있습니다.
참고로, Python 생태계의 SQLAlchemy 마이그레이션 도구인 Alembic은 훨씬 더 발전된 형태의 마이그레이션을 제공합니다. Alembic은 비선형적인 마이그레이션 경로(브랜치포인트 생성 가능)를 지원하여 복잡한 팀 개발 환경에서도 유연하게 대응할 수 있습니다. 이상적으로는 JavaScript/TypeScript 생태계의 ORM도 이러한 수준의 마이그레이션 도구를 제공하는 것이 바람직합니다.
Drizzle ORM에서 테이블 간 관계 설정이 매우 직관적이었습니다:
import { relations } from 'drizzle-orm';
export const usersRelations = relations(users, ({ one, many }) => ({
profile: one(profiles, {
fields: [users.id],
references: [profiles.userId],
}),
posts: many(posts)
}));
이 방식은 데이터베이스 설계의 본질적인, 관계적인 측면을 명확하게 표현해주었습니다.
두 ORM 모두 쿼리 작성을 위한 API를 제공하지만, Drizzle의 접근 방식이 더 직관적이고 관계형 모델을 활용하기 쉬웠습니다:
// Drizzle ORM - db.query 방식으로 관계 활용
const result = await db.query.posts.findMany({
where: eq(posts.published, true),
with: {
user: true // 게시물 작성자 정보를 함께 조회
}
});
// 결과 접근이 직관적이고 타입 안전함
console.log(result[0].title); // 게시물 제목
console.log(result[0].user.name); // 작성자 이름 - 객체 구조로 명확하게 구분됨
console.log(result[0].user.id); // 작성자 ID - 게시물 ID와 이름이 같아도 문제 없음
// Kysely
const result = await db
.selectFrom('posts')
.where('posts.published', '=', true)
.leftJoin('users', 'posts.userId', 'users.id')
.selectAll();
// 결과 접근 시 칼럼 이름 충돌 문제
console.log(result[0].id) // 오류: posts.id와 users.id 중 어떤 것인지 모호함
console.log(result[0].name) // 오류: 둘 다 name 칼럼이 있다면 모호함
Drizzle의 접근 방식이 테이블과 컬럼을 참조할 때 타입 안전성을 더 강력하게 보장하고, 관계를 활용한 쿼리 작성이 더 직관적이었습니다.
특히 여러 테이블 조인 시 동일한 이름의 칼럼 처리 부분에서 Drizzle ORM이 훨씬 더 편리했습니다. 이는 제 개발 경험에서 가장 중요한 차이점 중 하나였습니다.
// Drizzle ORM - 동일 이름 칼럼 처리
const result = await db.query.posts.findMany({
with: {
user: true // posts.id와 users.id가 모두 있지만 자동으로 구분됨
}
});
// 결과에 자연스럽게 접근 가능
console.log(result[0].id); // 게시물 ID
console.log(result[0].user.id); // 사용자 ID - 명확하게 구분됨
console.log(result[0].user.name); // 사용자 이름
// Kysely - 동일 이름 칼럼 처리를 위해 별칭 필요
const result = await db
.selectFrom('posts')
.leftJoin('users', 'posts.userId', 'users.id')
.select([
'posts.id as postId', // 별칭 필수
'posts.title',
'posts.content',
'users.id as userId', // 별칭 필수
'users.name as userName', // 칼럼 이름이 같을 수 있으므로 별칭 필수
'users.email as userEmail' // 일관성을 위해 모든 사용자 관련 칼럼에 접두어 필요
]);
// 별칭을 통한 접근
console.log(result[0].postId); // 게시물 ID
console.log(result[0].userId); // 사용자 ID
console.log(result[0].userName); // 사용자 이름
Drizzle ORM은 테이블과 칼럼을 객체로 참조하기 때문에, 동일한 이름의 칼럼이 있어도 자연스럽게 계층 구조로 처리되며 타입 추론도 정확하게 작동합니다. 반면 Kysely에서는 문자열 기반 접근 방식 때문에 별칭을 수동으로 지정해야 하는 경우가 많았고, 복잡한 조인에서 이런 작업이 번거로워졌습니다. 특히 여러 테이블에 같은 이름의 칼럼이 많을수록 모든 칼럼에 명시적인 별칭을 지정해야 하는 불편함이 있었습니다.
또한 Drizzle ORM은 결과 타입을 자동으로 정확하게 추론해주어 별도의 타입 지정 없이도 안전하게 결과를 사용할 수 있었습니다.
물론 Kysely도 여러 강점이 있습니다:
또한 앞서 언급했듯이, Kysely의 TypeScript 기반 마이그레이션과 양방향(up/down) 마이그레이션 지원은 특정 상황에서 Drizzle ORM보다 우위에 있는 기능입니다.
JavaScript/TypeScript 생태계의 ORM을 이야기하기 전에, 여러 언어 중에서도 Python의 SQLAlchemy는 특별한 위치를 차지합니다. 개인적으로 여태 사용해본 다양한 언어의 ORM 중에서 SQLAlchemy가 가장 기능이 풍부하고 강력하다고 느꼈습니다. 복잡한 쿼리 구성, 고급 관계 매핑, 트랜잭션 관리, 이벤트 시스템 등 SQLAlchemy의 기능은 정말 방대합니다.
Drizzle ORM은 JavaScript 생태계에서 매우 인상적인 발전을 이루었지만, 아직 SQLAlchemy의 경지에는 이르지 못했다고 생각합니다. 특히 다음과 같은 부분에서 SQLAlchemy의 성숙도와 기능 풍부함이 돋보입니다:
두 ORM 모두 훌륭한 도구이지만, 제 개발 스타일과 프로젝트 요구사항에는 Drizzle ORM이 더 잘 맞았습니다. 특히 스키마 정의의 직관성, 강력한 마이그레이션 도구, 그리고 전반적인 개발자 경험 측면에서 Drizzle ORM이 더 생산적인 개발을 가능하게 해주었습니다.
동일 이름 칼럼 처리와 같은 실질적인 문제에서 Drizzle ORM의 객체 기반 접근 방식이 가져다주는 편리함은 실제 프로젝트에서 큰 차이를 만들었습니다.
ORM 선택은 결국 프로젝트 특성과 개인 선호도에 크게 좌우됩니다. 새로운 프로젝트를 시작한다면 두 도구 모두 간단히 테스트해보고 자신의 워크플로우에 더 적합한 것을 선택하는 것이 좋겠지만, 제 경우에는 Drizzle ORM이 명확한 승자였습니다.
앞으로 Drizzle ORM이 더욱 발전하여 SQLAlchemy 수준의 풍부한 기능과 유연성을 제공하게 되길 바랍니다. JavaScript/TypeScript 생태계에도 그런 수준의 강력한 ORM이 있으면 좋겠습니다. 다행히도 Drizzle ORM은 계속해서 발전하고 있으며, 그 발전 속도를 보면 기대가 큽니다.
여러분의 경험은 어떤가요? 다른 ORM 도구나 언어를 사용해보셨다면 의견을 공유해주세요!
bgl gwyng shared the below article:
洪 民憙 (Hong Minhee) @hongminhee@hackers.pub
LLM 기반의 게시글 번역 기능이 추가되었습니다. 우선, 자신이 쓴 게시글이 LLM을 이용해 번역되는 것을 허용하려면, 게시글 공개 설정에서 “LLM 기반 자동 번역 허용” 옵션을 켜 주셔야 합니다. 기존 게시글은 모두 이 옵션이 꺼져 있습니다만, 새로 쓰는 게시글의 경우 기본적으로 켜져 있습니다.
위와 같이 옵션을 켜 준 게시글은 위쪽에 다음과 같이 “다른 언어로 읽기” 메뉴가 표시되게 됩니다. 이 메뉴에 나오는 언어 목록은 언어 설정에서 정할 수 있습니다.
이 중에서 이미 번역이 완료된 언어는 바로 표시되지만, 아직 번역이 완료되지 않은 언어의 경우, 아래와 같이 기다리라는 메시지가 뜨게 됩니다. 게시글의 분량에 따라 번역 시간은 차이가 나지만, 짧으면 30초에서 길면 5분 정도 걸립니다.
번역이 완료되면, 아래와 같이 메시지가 바뀝니다.
번역 기능은 제가 Hackers' Pub을 맨 처음 구상할 때부터 핵심 기능으로 고려하고 있던 것이었습니다. 소프트웨어 프로그래머로서 일정 수준 이상 성장하기 위해서는 반드시 영어를 배워야만 하는 불합리함이나 그리고 일본어나 중국어 등 영어가 아닌 언어로 쓰인 다양한 자료에 대부분의 외국인은 접근하지 못한다는 아쉬움을 오래 전부터 느꼈기 때문입니다. 다행히 얼마 전부터 LLM의 번역 품질이 아주 좋아졌고, 이를 활용하여 꽤 괜찮은 품질의 번역 기능을 Hackers' Pub 같은 작은 웹사이트에서도 구현할 수 있게 되었네요.
참고로 현재 번역에 쓰이는 모델은 Claude Sonnet 3.7입니다. 저렴하다고는 할 수 없는 모델인데요. 시범적으로 운영해 보고, 비용이 너무 부담된다고 여겨지면 Gemini 2.5 Flash 같은 다른 모델로 전환하는 것도 고려하고 있습니다.
아무튼, 모처럼 추가한 번역 기능이니 많은 분들이 유용함을 누리셨으면 좋겠습니다.
아래는 제가 샘플로 미리 만들어 둔 번역본들입니다: