여태까지 地下鐵에서 다음 驛이 어딘지 알 수 없을 때마다 머릿속에서 온갖 陰謀論을 떠올렸었는데… 이제라도 다음 驛이 常時 表示된다니 多幸이네. (내가 주로 떠올렸던 陰謀論은 廣告를 더 많이 보게 하려고 다음 驛을 가끔만 表示한다는 것이었다.)

bgl gwyng
@bgl@hackers.pub · 83 following · 98 followers
슈티를 함께 만들 팀을 만들고 있습니다. 관심 있으신 분, 또는 잘 모르겠지만 이야기를 나눠보고 싶은 분도 bgl@gwyng.com으로 편하게 연락주세요.
GitHub
- @bglgwyng
shootee
- www.shootee.io
나는 버전 올리기 강박증같은게 있는데, RN 초기에 불안정한 라이브러리들 많이 쓰다가 생긴거 같다. 일단 버전 올린다음에 빌드 터지는지 기존 기능 잘돌아가는지 확인하는데, 이거하느라 쓰는 시간도 꽤 된다. 실제로 시간을 아끼고 있는지(모르던 버그를 모르고 해결해서) 아닌지 모르겠다.
GitHub 저장소 코드를 분석해 AI로 문서화하는 도구. 다이어그램을 적극적으로 활용해 아키텍처를 쉽게 이해할 수 있고, 문서의 깊이와 정확도도 높다. 여러모로 <오픈 소스 소프트웨어 아키텍처>를 읽으며 아쉬웠던 부분들을 커버해주는 프로젝트. https://deepwiki.com/
개발자의 저주: 고치는 능력을 가진 자의 무한한 책임감
------------------------------
- 사소한 자동화를 반복하다 보면 어느 순간 모든 도구와 시스템이 *고쳐야 할 대상* 으로 보이게 되는 *인지의 임계점* 에 도달하게 됨
- 기술력이 쌓일수록 문제를 단순히 인식하는 것을 넘어 *책임처럼 느끼게 되는 감정의 무게* 를 가지게 됨
- *고치고자 하는 욕구* 는 단순한 생산성 향상을 넘어서 감정…
------------------------------
https://news.hada.io/topic?id=20735&utm_source=googlechat&utm_medium=bot&utm_campaign=1834
@bglbgl gwyng 도움이 되는지는 모르겠지만, 저는 써놓을 때도 있고 안 써놓을 때도 있었네요. 🤔
@hongminhee洪 民憙 (Hong Minhee) 오홍 참고해보겠습니다!
.cursorrules나 .windsurfrules 등의 파일에 프로젝트에 대한 설명을 써놓는것도 도움이 되나요? 공심 홈페이지의 가이드라인을 보면 코딩스타일 등의 지침만 써놓아서요. 어차피 알아서 일종의 인덱싱을 할테니 필요없을까요?
@bglbgl gwyng Live Query가 뭔가요?
@hongminhee洪 民憙 (Hong Minhee) https://orm.drizzle.team/docs/latest-releases/drizzle-orm-v0311 요렇게 쿼리 결과가 reactive해서 refetching 대신 구독을 할수있는 쿼리를 Live Query라고 하더라고요.
잉 drizzle에 Live Query 지원이 되네요? [join된 테이블의 reactivity에 문제가 있는데] 이건 고치면되는 버그같고요? 지금 만들고 있는거 왜 하고있지? 제가 원하는 추가 기능을 넣으려면 새로 짤 필요가 있을순 있지만 말이죠.
안녕하세요, 숫자상입니다.
먼 미래에는 어떻게 될 지 잘 모르겠지만, 일단 코딩 에이전트한테 LSP를 툴로 쥐어 줘야 하는 게 아닌가 하는 생각이 요즘 많이 든다.
AI에 대한 SW 엔지니어들의 자신감은 "어쨌거나 업계 내에서 만드는거라서-" 인거 같다. 손바닥 위에 있다는 감각(얼추 맞긴 하다).
타 직업군은 AI나 LLM 솔루션 자체를 다루는데도 한계가 있거니와(아무래도 fork떠서 고친다거나 할순 없으니까) 결과물도 자기 의사와 관계 없이 학습당하고 있기 때문에…
아예 거스를 수 없는 것이기 때문에, 타 분야에서는 오히려 공격적으로 자기 분야에 특화된 모델을 만들고, 기존 저작물들을 학습으로 부터 보호해서 우선권을 선점 하는게 그나마 좀 더 낫지 않을까?
근데 후자는… 테크기업이 양아치라서 잘 안될거같다.
@bglbgl gwyng 맞아요. 아마도 실세계에 이런 테스트 코드가 많기 때문에 더 그러는 게 아닐까 싶습니다… ㅋㅋㅋ
@hongminhee洪 民憙 (Hong Minhee) 결국 다 휴먼의 원죄군요...
실제로 방금 어떤 사례를 발견했냐면, 계산이 살짝 까다로운 값에 대한 테스트를 만들라고 시켰더니 코드를 한 백줄 뱉어내는데
expect(x).toBe(42)
이렇게 값에 대한 테스트를 안하고
expect(typeof x).toBe("number")
이러고 넘어가려고 했다. 손바닥 이리내.
Hackers' Pub은 기본 Markdown 문법 외에 다양한 확장 문법을 지원합니다. TeX을 통한 수식, 각주, 경고 박스(admonitions), 표, Graphviz를 통한 도표, 코드 블록에서 특정 줄만 강조하기 등…
마땅한 기술 블로깅 플랫폼을 못 찾았다면, Hackers' Pub도 고려해 보세요!
bgl gwyng shared the below article:
논리와 메모리 - 논리와 저수준(Low-level) 자료 표현(Data representation) (2 편 중 2 편)

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:
- The three-tier permission model (allow/require approval/deny) feels more flexible than binary allow/deny
- Separating approval objects from interactions appears more secure against forgery
- The explicit handling of edge cases (mentioned users, post authors) provides clearer semantics
- The extensible framework allows for handling diverse interaction types, not just replies
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
join을 지원하는 reactive한 SQLite client 개발 거의 다 되어간다. 혹시 중간에 관두는걸 막기위해 남긴다.
@ailrunAilrun (UTC-5/-4) LLM 요약 대신 글 앞 부분을 보여주는 옵션을 설정에 만들어 보도록 하겠습니다. 😅
@ailrunAilrun (UTC-5/-4) 옵션을 추가했습니다! 설정 → 환경 설정 → AI가 생성한 요약 선호 옵션을 해제하시면 됩니다.
<section>
버리고 <article>
써야 하는 이유 #a11y
〈section〉
태그 안의 글에 헤딩(제목)을 포함하면 화면상에서는 그 헤딩들이 논리적인 순차 구조를 가지고 있는 것처럼 보인다. 하지만 이는 순전히 시각적인 것일 뿐 보조 기술과 연동된 구조 정보가 아니다.〈section〉
태그의 용도는 무엇이고, 헤딩을 어떻게 코딩해야 보조 기술 사용자에게 정말 중요한 구조 정보를 전달할 수 있을까?
AI가 짠 코드의 테스트코드를 AI한테 짜게하고 있으니 Who watches the watchman? 이 떠오르는 것이다.
@hongminhee洪 民憙 (Hong Minhee) 오 다 방법이 있긴하네요.
.vscode/settings.json으로 확장 켜고끌수 없나 찾아봤는데 해당 이슈가 8년째 오픈이란걸 알게되었다.
세상엔 재미있는 사람들이 많아 제트엔진 내부의 공기 흐름을 직접 볼 수도 있다. ....... 아니 세상에 너무 재밌잖아!
똑같은 인터페이스에 대한 여러 구현체에 대해 같은 테스트를 적용하기위한 좋은 방법이 뭘까요? vitest의 경우에 test.each(implementations)
이런식으로 할수 있다는데, 이러면 구현체가 늘어났을때 테스트 파일을 수정해야하는점이 마음에 안든단 말이죠. 지금 구현체를 인자로 받아 테스트를 정의하는 함수를 만들고 각 구현체 마다 .test.ts
파일을 만들어서 호출하는 방식을 고려하고 있습니다. 더 좋은 방법이 있을까요?
SolidJS는 React처럼 Reactivity 코어가 분리되어 있지않은거 같다? solid-three, solid-native 등의 프로젝트들이 있는데 2년넘게 관리되고 있지않다.
@bglbgl gwyng 커스텀 렌더러 (Solid에선 Universal Rendering이라고 부름) 지원 자체는 잘 되어 있는데 그냥 커뮤니티 망치가 부족해서 유지보수가 안 되는 것에 가깝고 😅 이런 물건은
왜인진 도저히 모르겠지만 나름 관리가 잘 되고 있습니다
프로젝트 이름 예쁘게 짓는 방법 구합니다
프로젝트 이름 예쁘게 짓는 방법 구합니다
캘린더 이벤트로 변환이 가능한 데이터들 (예약 서비스의 예약 내역, 캘린더 양식이 아니어서 변환이 필요한 데이터, 매우 낮은 에러 레이트 리밋(?) 같은 이유로 인하여 일반적인 캘린더 동기화에 넣기 불안한 출처)를 모아다가 주로 사용하는 캘린더 서비스로 보내주는 서비스를 만들려고 합니다.
SolidJS는 React처럼 Reactivity 코어가 분리되어 있지않은거 같다? solid-three, solid-native 등의 프로젝트들이 있는데 2년넘게 관리되고 있지않다.
현재 Hackers' Pub은 Fresh 2.0 알파 버전을 사용하고 있는데, Fresh 자체의 한계점도 많이 느꼈고 무엇보다 최근 몇 달 사이에 정식 릴리스를 향한 진전이 보이지 않기에 GraphQL 준비가 끝나면 프런트엔드를 SolidStart로 점진적으로 옮겨가고자 한다.
아재들을 노리는 곳인가하고 들어가 봤습니다. 함수랑산악회. 여기에, 소속된 분이 계실 수도 있겠습니다. 곳곳에 소규모 조직들이 있네요.
bgl gwyng shared the below article:
애플리케이션 개발 측면에서 본 Drizzle ORM 대 Kysely 비교

洪 民憙 (Hong Minhee) @hongminhee@hackers.pub
TypeScript로 백엔드 서버를 개발하면서 적절한 ORM 선택은 항상 중요한 결정 중 하나입니다. 최근 제 프로젝트에서 Drizzle ORM과 Kysely를 모두 사용해 볼 기회가 있었는데, 개인적으로는 Drizzle ORM이 더 편리하고 생산성이 높았던 경험을 공유하고자 합니다.
두 ORM에 대한 간략한 소개
Drizzle ORM은 TypeScript용 ORM으로, 타입 안전성과 직관적인 API를 강점으로 내세우고 있습니다. 스키마 정의부터 마이그레이션, 쿼리 빌더까지 풀스택 개발 경험을 제공합니다.
Kysely는 “타입 안전한 SQL 쿼리 빌더”로 자신을 소개하며, 타입스크립트의 타입 시스템을 활용해 쿼리 작성 시 타입 안전성을 보장합니다.
두 도구 모두 훌륭하지만, 제 개발 경험에 비추어 볼 때 Drizzle ORM이 몇 가지 측면에서 더 편리했습니다.
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도 여러 강점이 있습니다:
- 더 가벼운 구조: 필요한 기능만 포함할 수 있는 모듈화된 구조
- SQL에 더 가까운 접근: SQL 구문에 매우 충실한 API 설계
- 유연성: 복잡한 쿼리에서 때로 더 유연한 작성이 가능
또한 앞서 언급했듯이, Kysely의 TypeScript 기반 마이그레이션과 양방향(up/down) 마이그레이션 지원은 특정 상황에서 Drizzle ORM보다 우위에 있는 기능입니다.
SQLAlchemy와의 비교 및 앞으로의 기대
JavaScript/TypeScript 생태계의 ORM을 이야기하기 전에, 여러 언어 중에서도 Python의 SQLAlchemy는 특별한 위치를 차지합니다. 개인적으로 여태 사용해본 다양한 언어의 ORM 중에서 SQLAlchemy가 가장 기능이 풍부하고 강력하다고 느꼈습니다. 복잡한 쿼리 구성, 고급 관계 매핑, 트랜잭션 관리, 이벤트 시스템 등 SQLAlchemy의 기능은 정말 방대합니다.
Drizzle ORM은 JavaScript 생태계에서 매우 인상적인 발전을 이루었지만, 아직 SQLAlchemy의 경지에는 이르지 못했다고 생각합니다. 특히 다음과 같은 부분에서 SQLAlchemy의 성숙도와 기능 풍부함이 돋보입니다:
- 복잡한 서브쿼리와 윈도우 함수 지원
- 다양한 이벤트 리스너와 훅
- 다양한 상속 전략
- 복잡한 트랜잭션 관리와 세션 관리
- 대규모 프로젝트에서 검증된 안정성
- Alembic을 통한 비선형적 마이그레이션 지원
- 놀라울 정도로 방대하고 상세한 문서화
결론
두 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:
Hackers' Pub 업데이트: LLM 기반의 게시글 번역 기능

洪 民憙 (Hong Minhee) @hongminhee@hackers.pub
LLM 기반의 게시글 번역 기능이 추가되었습니다. 우선, 자신이 쓴 게시글이 LLM을 이용해 번역되는 것을 허용하려면, 게시글 공개 설정에서 “LLM 기반 자동 번역 허용” 옵션을 켜 주셔야 합니다. 기존 게시글은 모두 이 옵션이 꺼져 있습니다만, 새로 쓰는 게시글의 경우 기본적으로 켜져 있습니다.


위와 같이 옵션을 켜 준 게시글은 위쪽에 다음과 같이 “다른 언어로 읽기” 메뉴가 표시되게 됩니다. 이 메뉴에 나오는 언어 목록은 언어 설정에서 정할 수 있습니다.


이 중에서 이미 번역이 완료된 언어는 바로 표시되지만, 아직 번역이 완료되지 않은 언어의 경우, 아래와 같이 기다리라는 메시지가 뜨게 됩니다. 게시글의 분량에 따라 번역 시간은 차이가 나지만, 짧으면 30초에서 길면 5분 정도 걸립니다.


번역이 완료되면, 아래와 같이 메시지가 바뀝니다.


번역 기능은 제가 Hackers' Pub을 맨 처음 구상할 때부터 핵심 기능으로 고려하고 있던 것이었습니다. 소프트웨어 프로그래머로서 일정 수준 이상 성장하기 위해서는 반드시 영어를 배워야만 하는 불합리함이나 그리고 일본어나 중국어 등 영어가 아닌 언어로 쓰인 다양한 자료에 대부분의 외국인은 접근하지 못한다는 아쉬움을 오래 전부터 느꼈기 때문입니다. 다행히 얼마 전부터 LLM의 번역 품질이 아주 좋아졌고, 이를 활용하여 꽤 괜찮은 품질의 번역 기능을 Hackers' Pub 같은 작은 웹사이트에서도 구현할 수 있게 되었네요.
참고로 현재 번역에 쓰이는 모델은 Claude Sonnet 3.7입니다. 저렴하다고는 할 수 없는 모델인데요. 시범적으로 운영해 보고, 비용이 너무 부담된다고 여겨지면 Gemini 2.5 Flash 같은 다른 모델로 전환하는 것도 고려하고 있습니다.
아무튼, 모처럼 추가한 번역 기능이니 많은 분들이 유용함을 누리셨으면 좋겠습니다.
아래는 제가 샘플로 미리 만들어 둔 번역본들입니다:
- Ditch the DIY Drama: Why Use Fedify Instead of Building ActivityPub from Scratch? (영어) → 〈DIY 드라마는 그만: 왜 ActivityPub을 처음부터 구축하는 대신 Fedify를 사용해야 할까요?〉 (한국어)
- 〈애플리케이션 개발 측면에서 본 Drizzle ORM 대 Kysely 비교〉 (한국어) → 「アプリケーション開発の観点から見たDrizzle ORMとKyselyの比較」 (일본어)
- 〈deno-task-hooks: Git 훅을 Deno 태스크로 쉽게 관리하기〉 (한국어) → deno-task-hooks: Easily Manage Git Hooks as Deno Tasks (영어)
- Browser-Native Translation and Language Detection APIs Coming Soon (영어) → 〈브라우저 네이티브 번역 및 언어 감지 API 곧 출시 예정〉 (한국어)
@hongminhee洪 民憙 (Hong Minhee)
@bglbgl gwyng 처음 도커로 서비스를 구동할 때는 latest 태그를 붙여 사용했는데 버전 간 호환성 문제를 겪은 다음부터는 항상 정확한 버전을 가리키도록 태그를 만들어 사용하게 되었습니다. 근데 ... 확실히 매번 손으로 파일을 수정하고 손으로 docker compose pull && docker compose down && docker compose up 이라고 치는 건 ..... 개선 여지가 있다고 생각만 하고 있는데 ...... 뭘 해야 하는지는 잘 모르갰더라구요. 그.. 왓치타워 같은 솔루션이 있는 걸 알고는 있는데 제가 모를 때 그냥 버전이 띡 바뀌는 건 또 썩 맘에 안 들기도 하고요 ;;;;;;
@meWoojin Kim
@hongminhee洪 民憙 (Hong Minhee) 제가 Nix가 minimal한 해결책이라고 했던건, Nix를 딱 그 이미지 태그가 박힌 docker-compose.yml을 출력(빌드?)하는데 까지 쓸수있다는 의미에서였습니다. 그러니까 배포하려는 서비스의 소스코드를 입력으로 주면 그걸로 빌드한 docker 이미지의 태그가 박힌 compose.yml을 구하는 함수를 정의할수 있어요.
@hongminhee洪 民憙 (Hong Minhee) 아앗 ...... 그러면 안되나요? ..... (말씀하신 것과 똑같이 운영하는 사람 1)
@meWoojin Kim
@hongminhee洪 民憙 (Hong Minhee) 여기서 불만족스러우신 부분이 이미지 태그를 손으로 수정하는 부분일텐데, 사실 딱 그문제를 최소한의 개념으로 해결하는게 Nix이긴 합니다. 토끼굴에 빠질수있어 적극적으로 영업은 못하겠습니다만ㅋㅋ
LLM 시대 이후로 생산성과 관련해서 스트레스를 더 많이 받는거 같다. 당신이 오늘 허투루 보낸 하루는 누군가가 올바른 프롬프팅으로 +10K LOC를 할수있는 하루였다, 같은 생각을 퇴근하면서 한다.
큰 틀에서는 동의합니다. 파인만 아저씨 책을 보셨다니..며칠전 전공자들의 고집을 짚었던 걸로 보아, 전공은 아니신가 했는데, 셀프 디스를 하셨던 건가!)
(다른 비함수형 언어와 달리) 워낙 IO란 걸, 잘 구분해야 하는 게, 쉽지 않은 미션인데, 시작을 너무 전통 hello world 에 얽매이는 건 아닐까 싶어서요. 굳이 쉽지 않은 걸 보여주고, 모르고 넘어가자라고 하느니, 차라리 더하기 하며, 로그 남기는 걸, 직접 순수 함수로 만들어 보는 게, 낫지 않을까 혼자 상상해 봤습니다.
@bglbgl gwyng
@lionhairdino 아뇨ㅋㅋ물알못인데 그냥 친구가 책 빌려줘서 읽어봤습니다. IO를 쓰게한다고 해서 IO를 꼭 당장 설명해야하는건 아니니까요. 나중으로 미루면 되잖아요. 저는 당장
putStrLn
이나 getLine
를 못쓰게 해버리면 무슨 하자가 있는 언어라고 오해할까 걱정이 되네요ㅋㅋ
너무 친절하게 쓰여 있어서, 오히려 생각, 상상할 여지를 주지 않아서 그랬을까요? @bglbgl gwyng
@lionhairdino 네네. 캄캄한 방안의 구조를 파악하려면 모서리에 계속 부딪혀야하지요.
main = do
n <- getLine
putStrLn $ "hello " <> n
설명해야 될 게 한가득인데, 나중에, 나중에 하며 넘어가야 한다. 꼭 Lazy 평가처럼 말이다. 전통적인 "hello world"에서 출발하지 않아도 되는 것 아닐까? 첫 언어가 아닌 분들한테는, Writer
혹은 State
만들기부터 시작하면 어떨까? 단, "모나드"라고 말하지 않고.
@lionhairdino 사실 전 어떤 좋은 설명을 제공해야한다는 생각 자체에 좀 회의적입니다. 그냥 하다보면 알게되도록 보조해주는게 최선이라고 생각합니다. 약간 별개의 얘긴데, 옛날에 파인만 빨간책 읽다가 참 좋은 책이란 생각이 들었지만 설명이 너무 똑똑해서 덮었습니다.
국내만 해도 수백만 MAU를 달성하는 서비스가 여럿이고, 엄청나게 많은 인원이 엄청나게 많은 가설을 세우면서 실험을 하고 있는데, 그 많은 실험이 기록으로 정리되지 않고 프로덕트의 피처로 환원되는게 좀 아쉽다. 실험이 누적되면 꽤 의미있는 인사이트를 얻을 수 있을 것 같은데.
개인적으로 영단어 “side effect”의 가장 적절한 번역은 “부작용”이라고 생각하고, 실제로 프로그래밍 이외의 분야에서는 여전히 이 번역어를 가장 많이 쓰는 것 같은데… 사람들이 “부작용”을 副作用이 아니라 否(?)作用이라고 착각하는 것을 염려해서인지 프로그래밍 분야에서는 “부수 효과” 같은 번역어를 더 많이 쓰는 듯하다. “부작용”의 “부”(副)는 “사장”–“부사장”할 때의 “부”인데 말이다.
부끄럽지만 typst로 깎은 이력서와 포트폴리오를 공개합니다: https://github.com/gidongkwon/resume
게임 클라이언트에서 웹 프론트엔드로 커리어 전환을 하는 단계에 있습니다.
혹 피드백주실 것이 있다면 언제든지 좋아요...!
직링크는 아래:
이력서 - https://gidongkwon.github.io/resume/resume-gidongkwon.pdf
포트폴리오 - https://gidongkwon.github.io/resume/portfolio-gidongkwon.pdf
요즘 잡일은 AI 시키고, 그사이 어려운 일을 AI랑 힘을 합쳐 해결해야하는 시대인데, 내가 하루종일 어려운일을 할 체력이 없어서 머리비우고 할수있는 잡일도 일정량 직접 한다. 파일 상하차라던가.
10만 토큰 안쪽으로 작은 요약을 만드는건 가능한데, IDE에 내장된 AI로 어디까지 되는지는 모르겠네요. Aider에서 Claude API를 그대로 썼을때 기준으로는 5만 토큰 제한때문에 Repomix 파일을 그대로 맥락에 포함하지는 않았어요.
그냥 Repomix는 웹에다가 던지고, 지시사항을 XML로 받아서 Aider가 순차적으로 실행하는 식으로 돌려왔어서요. Repomix 파일 던져놓고 어떻게 작업을 진행할지 알려달라고 하면 어느 파일의 어떤 부분을 수정하면되는지 잘 뽑아주긴 합니다.
@kodingwarriorJaeyeol Lee (a.k.a. kodingwarrior)
옵션을 바꿔가며 좀 돌려봤는데 제가 툴을 오해했네요. 의미를 파악해서 알아서 인덱스를 만들어주는게 아니군요.
Relay로 offline db sync를 하고 있었을땐, Relay가 Node의 Id나 Edge의 Cursor가 Opaque란 가정을 하고있는게 걸림돌이라고 느껴졌다. SQLite에 저장하려면 어차피 id로 부터 composite key를 구해야하고, 거기엔 또 order도 존재하는데 Relay는 이런데 전혀 무관심하다. 하지만 일반적인 웹사이트 렌더링에는 저런 가정이 전혀 무리가 없다.
@bglbgl gwyng 아뇨. 리포믹스는 ChatGPT, 클로드챗, 제미니챗한테 던지죠. 구조상 파일 자체가 토큰 수가 많아서요
@kodingwarriorJaeyeol Lee (a.k.a. kodingwarrior)
옵션을 조합해서 작은 요약을 만드는게 불가능한가요?
플러터앱을 repomix로 압축해놓고, GPT한테 던져서 소스코드 모양새 슥 보고 앱스토어에 소개할 내용 적어달라고 하니까 지가 알아서 던져주네.... 세상 너무 좋아짐....
@kodingwarriorJaeyeol Lee (a.k.a. kodingwarrior)
지금 .windsurfrules 쓰는거에서 쩔쩔매고있는데 혹시 repomix로 뽑아서 넣기도 하나요?
Signal같은건데 incremental update도 되고 GC도 가능한 무언가를 만들려고 했더니 이런 정의가 나왔다. 혹시 비슷한거 알고 계신분 있나요?
type Dynamic<Value, Delta> = {
read(): Value;
disconnect(): void;
updated: Observable<Delta>;
fork(): Dynamic<Value, Delta>;
};
그동안 Relay를 offline db sync 용도로 쓰고있었는데(첨부터 그러려고 했던건 아니고, API 두벌 만드는걸 피하다보니 그 역할도 떠맡음), 그래서 Relay가 킹론상 좋다는건 아는데 실질적으로 장점을 못누리고 살았었다. 근데 지금 추가하는 기능에서는 Relay를 본래 용도에 맞게 쓰고있는데, 설계 고민도 줄여주면서 코드가 쭉쭉 나온다.
@bglbgl gwyng 아, 전자를 가리키는 거였습니다. 타입을 못 맞춰서 몇 회를 이터레이트하네요… ㅋㅋㅋ
@hongminhee洪 民憙 (Hong Minhee) 아하 제 경험과 비슷하네요. 하스켈에서도 그렇고 타입을 한방에 맞추는건 참 잘하는데, 한방에 맞추는걸 실패했을때 둠루핑으로 쉽게 빠지는거 같아요. 이 현상이 구현이 틀렸을 때보다 타입이 틀렸을 때 더 심한 느낌입니다.