통신사 해킹 사태 등의 보안 사고에 대해 IT쪽으로 조금이라도 지식이 있는 사람과 아닌 사람(e.g. 우리 엄마 아빠)의 통신사의 잘못에 대한 분노의 크기가 다른거 같다. 가령 나는 해커가 RSA2048를 해독하는 알고리즘이라도 발명해서 해킹했다면 크게 화가 안날것이다. 굿잡, 어쩔수없지 정도? 근데 이번 사고의 디테일은 몰라도 그런거랑은 전~혀 관련 없다는건 당연하다.
근데 우리 엄마도 이게 통신사의 인재라는건 아는데, 동시에 해커들도 뭔가 방어하기 어려운 첨단 기술 그런걸 썼다고 막연히 생각하는거 같다. 그래서 나처럼 통신사들이 한방에 골로 가도 할말 없을 만큼의 잘못을 저질렀다고까지 생각하고 분노하진 않는듯...
The Official Python Documentary has published their teaser trailer at PyCon US 2025, and I'm so honored to be part of the story of Python along with other prominent Python figures.
Check the trailer, and watch the official launch of the documentary at EuroPython later this year.
If a module defines a custom exception type and throws that exception within the module, it absolutely must export that exception type as well. I'd think this is basic, but it seems a surprising number of packages declare exception types without exporting them.
Linux 6.15 is right around the corner, which means it's time for another progress report! We have been pretty busy behind the scenes and we have some exciting developments to share with you all!
As always, we want to thank everyone who support us as none of this would be possible without your generous support.
I've been thinking about client-server interactions in the #fediverse. #ActivityPub#C2S isn't widely used, and most clients rely on Mastodon-compatible APIs instead.
What if we created a new standardized API based on GraphQL + Relay for client-server communication, while keeping ActivityPub for server-to-server federation?
The Mastodon-compatible API lacks formal schema definitions for code generation and type checking, which hurts developer productivity. And ActivityPub C2S is honestly too cumbersome to use directly from client apps.
#GraphQL would give us type safety, efficient data fetching (only get what you need), and the ability to evolve the API without breaking clients. #Relay's features for pagination, caching, and optimistic updates seem perfect for social apps.
Would this be valuable to our community? What challenges do you see? How might we handle backward compatibility? And should this be formalized as an FEP?
참고로 스프린트 모임이란 함께 모여서 오픈 소스 코딩을 하는 자리인데, 한국 연합우주 개발자 모임의 스프린트에서는 새로운 연합우주 서비스나 앱을 개발하거나, 번역이나 문서에 기여하는 등 연합우주와 관련된 다양한 오픈 소스 활동을 모여서 함께 합니다. 지난 스프린트 모임의 기록을 스프린트 블로그(@sprints.fedidev.kr한국 페디버스 개발자 모임)에서 살펴보실 수 있습니다.
저는 그날 Fedify, Hollo, Hackers' Pub에 기여하시고자 하는 분들을 옆에서 도와드릴 예정입니다. Fedify, Hollo, Hackers' Pub에 기여해보고 싶었던 분들이 계시다면 모임에 참가하여 저와 함께 스프린트를 해보는 것도 좋을 것 같습니다.
현재 Hackers' Pub은 Fresh 2.0 알파 버전을 사용하고 있는데, Fresh 자체의 한계점도 많이 느꼈고 무엇보다 최근 몇 달 사이에 정식 릴리스를 향한 진전이 보이지 않기에 GraphQL 준비가 끝나면 프런트엔드를 SolidStart로 점진적으로 옮겨가고자 한다.
그동안 Relay를 offline db sync 용도로 쓰고있었는데(첨부터 그러려고 했던건 아니고, API 두벌 만드는걸 피하다보니 그 역할도 떠맡음), 그래서 Relay가 킹론상 좋다는건 아는데 실질적으로 장점을 못누리고 살았었다. 근데 지금 추가하는 기능에서는 Relay를 본래 용도에 맞게 쓰고있는데, 설계 고민도 줄여주면서 코드가 쭉쭉 나온다.
여태까지 내가 팔로한 사람이 내가 팔로하지 않은 사람에게 단 댓글까지 타임라인에 떠서 불편하셨죠? @xiniha 님의 패치를 통해 이제 내가 팔로한 사람의 글이라도 내가 팔로하지 않은 사람에게 단 댓글인 경우에는 타임라인에 표시되지 않도록 수정되었습니다. 아, 그래도 여전히 내가 팔로한 사람의 프로필에 들어가면 그 사람의 모든 댓글을 다 볼 수 있긴 합니다.
CMYK 프로파일 등 복잡한 ICC 프로파일을 지원하기 위해 기존에 사용하던 Little CMS 2 (lcms2) 에 더해, Rust로 작성된 색 관리 시스템인 moxcms 지원을 추가한 것이 주요 변경사항입니다. CLI 툴의 기본 CMS는 아직 lcms2이지만 --cms moxcms 옵션으로 moxcms를 사용할 수 있습니다.
CMYK 프로파일 등 복잡한 ICC 프로파일을 지원하기 위해 기존에 사용하던 Little CMS 2 (lcms2) 에 더해, Rust로 작성된 색 관리 시스템인 moxcms 지원을 추가한 것이 주요 변경사항입니다. CLI 툴의 기본 CMS는 아직 lcms2이지만 --cms moxcms 옵션으로 moxcms를 사용할 수 있습니다.
Protocols such as ActivityPub are widely used and useful, but unfortunately are not the best option when efficiency is important. Messages are in plain JSON format, which is wasteful, and extensions by various implementations complicate the implementation.
XQ's focus on replacing JSON with Protocol Buffers seems misguided. While serialization efficiency matters, ActivityPub's fundamental bottlenecks are in its multi-hop network architecture and request patterns. Optimizing message format without addressing these core architectural inefficiencies is like polishing doorknobs on a house with structural issues. True performance gains would require rethinking the communication model itself.
We're pleased to announce the release of BotKit 0.2.0! For those new to our project, #BotKit is a #TypeScript framework for creating standalone #ActivityPub bots that can interact with Mastodon, Misskey, and other #fediverse platforms without the constraints of these existing platforms.
This release marks an important step in our journey to make fediverse bot development more accessible and powerful, introducing several features that our community has been requesting.
The Journey to Better Bot Interactions
In building BotKit, we've always focused on making bots more expressive and interactive. With version 0.2.0, we're taking this to the next level by bringing the social aspects of the fediverse to your bots.
Expressing Your Bot's Personality with Custom Emojis
One of the most requested features has been #custom_emoji support. Now your bots can truly express their personality with unique visuals that make their messages stand out.
// Define custom emojis for your bot
const emojis = bot.addCustomEmojis({
botkit: {
file: `${import.meta.dirname}/images/botkit.png`,
type: "image/png"
},
fedify: {
url: "https://fedify.dev/logo.png",
type: "image/png"
}
});
// Use these custom emojis in your messages
await session.publish(
text`BotKit ${customEmoji(emojis.botkit)} is powered by Fedify ${customEmoji(emojis.fedify)}`
);
With this new API, you can:
Add custom emojis to your bot with Bot.addCustomEmojis()
Include these emojis in messages with the customEmoji() function
Communication isn't just about posting messages—it's also about responding to others. The new reaction system creates natural interaction points between your bot and its followers:
// React to a message with a standard Unicode emoji
await message.react(emoji`👍`);
// Or use one of your custom emojis as a reaction
await message.react(emojis.botkit);
// Create a responsive bot that acknowledges reactions
bot.onReact = async (session, reaction) => {
await session.publish(
text`Thanks for reacting with ${reaction.emoji} to my message, ${reaction.actor}!`,
{ visibility: "direct" }
);
};
Discussions often involve referencing what others have said. Our new #quote support enables more cohesive conversation threads:
// Quote another message in your bot's post
await session.publish(
text`Responding to this interesting point...`,
{ quoteTarget: originalMessage }
);
// Handle when users quote your bot's messages
bot.onQuote = async (session, quoteMessage) => {
await session.publish(
text`Thanks for sharing my thoughts, ${quoteMessage.actor}!`,
{ visibility: "direct" }
);
};
With these simple steps, you're ready to create or upgrade your fediverse bot with our latest features.
Looking Forward
BotKit 0.2.0 represents our ongoing commitment to making fediverse bot development accessible, powerful, and enjoyable. We believe these new features will help your bots become more engaging and interactive members of the fediverse community.
For complete docs and more examples, visit our docs site.
Thank you to everyone who contributed to this release through feedback, feature requests, and code contributions. The BotKit community continues to grow, and we're excited to see what you'll create!
BotKit is powered by Fedify, a lower-level framework for creating ActivityPub server applications.
BotKit 0.2.0 버전이 릴리스되었습니다! BotKit을 처음 접하시는 분들을 위해 간단히 소개하자면, BotKit은 TypeScript로 개발된 독립형 #ActivityPub 봇 프레임워크입니다. Mastodon, Misskey 등 다양한 #연합우주(#fediverse) 플랫폼과 상호작용할 수 있으며, 기존 플랫폼의 제약에서 벗어나 자유롭게 봇을 만들 수 있습니다.
이번 릴리스는 연합우주 봇 개발을 더 쉽고 강력하게 만들기 위한 여정에서 중요한 발걸음입니다. 커뮤니티에서 요청해 왔던 여러 기능들을 새롭게 선보입니다.
더 나은 봇 상호작용을 위한 여정
BotKit을 개발하면서 우리는 항상 봇이 더 표현력 있고 상호작용이 풍부하도록 만드는 데 집중해 왔습니다. 0.2.0 버전에서는 연합우주의 사회적 측면을 봇에 접목시켜 한 단계 더 발전시켰습니다.
커스텀 에모지로 봇의 개성 표현하기
가장 많이 요청받았던 기능 중 하나가 #커스텀_에모지 지원입니다. 이제 봇은 독특한 시각적 요소로 메시지를 돋보이게 하며 자신만의 개성을 표현할 수 있습니다.
친구가 외국 반도체회사에 다니는데 이름만 들으면 다 아는 세계에서 손꼽히는 회사다. 1년 전쯤에, 친구가 자기 팀에서 예전부터 쓰고있는 시뮬레이션 코드가 너무 복잡해서 리팩토링 하고 싶다고 나를 찾아왔다. 한 2, 3000줄 되는 Numpy 코드였다.
나는 시뮬레이션의 의미 자체는 전혀 이해를 못하니(이래서 보안문제도 익스큐즈 할수 있었을 것이다), 그냥 코드의 모양만 보고 이상한 부분을 조금씩 고쳐나갔다. 그... 전형적인 물리학자들의 실험실 코드였다(코드를 못짜는건 이해를 하는데, 거기에 대해 한치의 부끄러움도 느끼지 않는다는 점이 뒷목을 잡게 만든다). Numpy 함수도 제대로 활용을 못해놨길래, 나도 Numpy 잘 못쓰지만 대충 이런 함수가 아마 있겠지... 하고 검색해서 찾아내서 교체하고 이런걸 반복했다.
이것저것 고친 다음에 잘돌아가나 한번 실행을 해봤는데, 이럴수가. 시뮬레이션이 1000배 빨라졌다. 아니 뭐, 한 2배 3배 빨라졌으면 내 솜씨라고 자부할텐데, 1000배 빨라진거는 그냥 원래 코드가 똥통이었다고 해석할수 밖에 없다. 구라안치고 정말 1000배다. 1000배의 성능향상의 보답으로 나는 교촌치킨웨지콤보세트를 현장에서 받아먹었다.
그 이후에 어떤 일이 있었냐. 기존 시뮬레이션 코드로는 하루에 시뮬레이션을 2, 3번정도밖에 돌리지 못했는데, 1000배 빨라지고 나니까 결과가 수십초만에 나오니 하루에 수백번 돌릴수 있게 된것이다(내가 고친 코드가 전부는 아니어서 1000배 향상은 아닌데, 가장 큰 병목이긴 해서 결국 100배 이상이라는 듯). 그때부터 100배 많아진 데이터를 처리하기 위한 인프라가 필요해졌다. 그래서 거기 개발팀이 데이터베이스와 데이터 파이프라인 구축을 시작하게 되었다고 한다. 그 팀에서는 일종의 특이점이 시작된것이다;;
First, there's no standardization. ActivityPub specifications don't define how custom emoji should work, leading to inconsistent implementations across different servers like Mastodon and Misskey.
Rendering is particularly problematic. Emojis must display properly across different contexts (in text, as reactions, in emoji pickers) while maintaining quality at various sizes. Animated emojis add another layer of complexity.
Perhaps most concerning is the poor #accessibility. Most implementations simply use the emoji code (like :party_blob:) as the alt text, which provides no meaningful information to screen reader users (in particular, non-English speakers) about what the emoji actually depicts or means.
What really dampens my motivation to implement this feature is knowing I'm investing significant effort into something that ultimately creates accessibility barriers. It's disheartening to work hard on a feature that excludes part of the community.
For my library and CLI projects, I've been writing documentation before writing any code. It helps me imagine the final interface early on, which usually leads to better design. Sure, sometimes I miss implementation details and have to revise later, but hey—it's just docs. Docs are easy to change.
This tiny habit has surprisingly big payoffs. When I focus on how things will be used rather than how they'll be built, I end up with interfaces that actually make sense.
Anyone else do this? Curious about your experience with documentation-first approaches.
그래서 PostgreSQL 드라이버를 아예 node-postgres로 바꿀까 싶기도 한데, 이미 @fedify/postgres 패키지가 Postgres.js에 의존을 하고 있기 때문에 한 애플리케이션에서 두 종류의 드라이버를 쓰는 꼴이 된다. 음, 아무래도 상관 없으려나?
그 동안에는 Mastodon 등 다른 연합우주 인스턴스에서 앙케트를 만들면 Hackers' Pub에서는 앙케트의 선택지가 보이지도 않고 참여할 수도 없었는데요, 이제 Hackers' Pub에서도 앙케트(poll)에 참여할 수 있게 되었습니다. 다만, 아직 Hackers' Pub에서 새 앙케트를 만드는 기능은 구현되지 않았습니다. 새 앙케트를 만드는 기능은 필요하다는 의견이 많으면 구현하도록 하겠습니다. 언제나 같은 패턴이지만, UI 만드는 게 힘들어서요. 😅
저도 두 가지 쟁점 모두 동의하는 편입니다. 그리고, 별개의 이야기입니다만, $ 를 가르칠 때에는 그냥 문법이라고 가르치는 게 학습자의 이해와 응용이 압도적으로 빠르고 좋았습니다.
"이건 여기서부터 뒤로는 다 괄호로 감싸겠다는 뜻이라고 생각하세요."
이러면 한 방에 설명이 끝나고, 필요성이나 편리성에 대해서도 알아서들 납득하는 것이죠. 연산자 우선순위나 좌결합 우결합 등은 그게 되고 나서 얘기하고요. 그러면 "아, 이게 그래서 이렇게 되는 거였군요?" 하면서, 훨씬 쉽게 이해합니다. 이걸 거꾸로 좌결합 우결합 어쩌고부터 가르치려고 하면 다들 꾸벅꾸벅 졸아요... ㅋㅋ ㅠㅠ
드디어 @xtjuxtapose 님이 기다리시던 차단 기능이 구현되었습니다. 차단할 사용자의 프로필 페이지에 가서 팔로·언팔로 버튼 오른쪽에 보이는 말줄임표 아이콘에 마우스 커서를 갖다 대면 (모바일에서는 터치하면) 상세 메뉴가 나오는데, 그 안에 팔로워 삭제 버튼과 차단 버튼이 생겼습니다.
ActivityPub 프로토콜 수준에서는 차단은 Block 액티비티를 차단한 액터에게 보내며, 차단을 해제할 경우 Undo(Block) 액티비티를 보냅니다. 그러나, 그 액티비티를 받은 인스턴스의 구현이 차단한 사용자의 콘텐츠를 볼 수 없도록 막지 않을 수도 있습니다…만, 실질적으로는 모든 구현이 막고 있습니다. 아, 당연하지만 차단은 자동적으로 상호 언팔로를 수행합니다. 차단을 해제하더라도 풀렸던 팔로 관계는 자동적으로 회복되지 않습니다.