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
3

거꾸로 상태 모나드로 강화 학습 하기 (1/2) 2편을 마저 써야하는데, 먼저 하스켈 세미나 시간에 전체 내용으로 동료들한테 발표를 했다. 근데 발표하면서 글에 해결해야하는 문제점이라고 써놓은게 되게 얼렁뚱땅이란걸 깨달았다. 실제로 코드를 짠지가 시간이 좀 되어서 정확히 뭐가 문제였는지 좀 까먹어서 실제로 쓰기가 힘들어서 중간에 좀 놨었다ㅋㅋ 암튼 발표를 해보는게 내용 점검에 도움이 많이 된단걸 알았다.

거꾸로 상태 모나드로 강화 학습 하기 (1/2)

기계 학습을 전혀 모르고 살면 안 되겠다 싶어, 얼마전부터 하스켈로 공부하기 시작했다. Hasktorch라고 하스켈용 Torch 바인딩을 사용한다. 이전에 도전했을땐 MNIST까지 하고 다음에 뭘 해야할지 모르겠어서 그만뒀는데, 이번엔 강화 학습으로 이어나가 보기로 했다. 강화 학습은 주어진 환경에서 보상을 최대화하는 에이전트를 학습시키는 것으로, 데이터가 필요없다는게 장점이다. 대신 환경을 만들어야 하는데, 간단한 게임도 환경이 될 수 있다. 게임 만들기는 데이터 모으기와 달리 즐거운 일이니 마다할 필요가 없다. 첫번째로 도전으로 스네이크 게임을 골랐는데, 다들 한번쯤은 해봤을 것이다. 뱀을 조종해 먹이를 최대한 많이 먹으면 되는데, 뱀의 머리가 벽이나 아니면 자기 몸통에 부딪히면 죽는다. 여차여차 학습시켜서 이정도까지 하는데에는 성공했다. 강화 학습 지식이 일천해서 게임을 클리어하는 수준까지는 못 만들겠다. 이 글은 학습을 잘 시키는 방법이 아니라, 강화학습 코드를 어떻게 잘 짜느냐에 대한 것이다.<일단 강화 학습이란걸 형식화 해보자. 앞서 언급한 환경과 에이전트란 단어를 어떻게 정의할수 있을까? 먼저 에이전트의 정의는 이렇다.type Agent = Observation -> Action<관측 Observation 에 따라 행동 Action 을 선택한다. 나는 눈앞에 콜라가 보이면 마신다. 환경은 에이전트를 실행하는 무언가이다. 일상적인 표현으로 쓰자면, 에이전트를 둘러싼 무언가이다.runAgent :: Agent -> [Action]<이 runAgent 함수가 환경의 역할을 수행한다. Agent를 인자로 받아 죽을 때까지 선택한 행동들을 반환한다. 그런데 이건 너무 외연적인 정의고, 환경과 에이전트가 보통 만족할만한 조건을 나열해보자면 이렇다.환경은 상태를 가지고 있고 시간이 지남에 따라 변경된다상태는 에이전트가 무엇을 관측할지를 결정한다에이전트의 행동은 다음 상태에 영향을 끼친다<이 조건들을 바탕으로 환경을 좀더 구체적으로 정의하면 다음과 같다.class Environment e where type State e type Observation e type Action e update :: (State e, Action e) -> State e -- 조건 1, 3 observe :: State e -> Observation e -- 조건 2<스네이크 게임에서 상태는 뱀의 모양과 먹이의 위치, 관측은 상태와 같고(플레이어는 전체 게임 화면을 볼 수 있다), 행동은 좌회전과 우회전이 된다. 그런데 뱀이 아무렇게나 좌회전 우회전 한다고 박수 쳐줄순 없고, 우리는 얘한테 바라는 게 있다. 죽지않고 더 많은 먹이를 먹어야 한다. 이를 위해 뱀이 제때 방향을 바꿔서 먹이를 지나치지 않고 먹으면 잘 했다고 보상을 주자. 그러면 뱀은 보상을 더 많이 받을 방법을 학습한다.type RewardFunction = (Observation, Action) -> Float<보상 함수는 관측와 행동에 따라 보상을 결정한다. 가령 뱀이 먹이 하나를 냠냠하면 보상을 1 주면 된다. 지나쳐버리면 0점이고, 죽었을 때는 -1점을 줄 수도 있다. 당근과 채찍이라 생각하고 정의하면 된다. 또, 보상은 더해서 누적이 되어야 하므로 대충 Float으로 고른다. 학습을 시키려면 보상을 계산해야하고, 그러기 위해 관측과 행동을 짝지어야한다.trainAgent :: Agent -> [(Observation, Action)]<runAgent와 달리 Observation도 포함되어 있다. 이때 [(Observation, Action)]을 에피소드 Episode 라고 한다. 에피소드로부터 보상을 구하자.rewards = fmap (uncurry rewardFn) (trainAgent agent)rewardFn :: RewardFunctionagent :: Agent<...해치웠나? 에피소드가 어떻게 기록될지를 살펴보자.0123456789행동→↓→↓←↑→↓←↓보상🍎🍎🍎💀<위의 rewards의 값이 이런 의미일거라고 보인다. 실제로 Float 값을 표시해보자.0123456789행동→↓→↓←↑→↓←↓보상0010011000<혹시 이상한 걸 찾으셨나요? 이런식으로 보상하는게 틀린 건 아니다. 다만 에이전트가 장기적인 계획을 세우도록 학습시키지 못한다. 먹이를 먹는 순간에만 보상을 받기 때문에, 멀리 떨어진 먹이를 향해 다가가게끔 유도할 수가 없다. 이를 해결하려면 보상을 뒤에서부터 누적시켜야 한다.0123456789행동→↓→↓←↑→↓←↓보상3332221000rewards = scanr (+) 0 (fmap (uncurry rewardFn) (trainAgent agent))<코딩 테스트용 코드를 짜야할것 같은 느낌이 들었는데, 다행히 scanr 함수 덕분에 쉽게 해결했다. 좀더 개선해볼까. 지금의 보상 체계에서 에이전트는 먼 미래를 고려하며 선택하는 것을 배울 수 있다. 그런데, 사실 뱀이 맨 처음에 좌회전을 하던 우회전을 하던, 죽기 전까지 먹이를 총 몇개 먹는지에 엄청난 영향을 끼칠거 같진 않다. 어떤 시점에서의 선택의 영향은 시간이 지날 수록 점점 희미해진다. 이 점을 반영해서 뱀이 잘못된 편견을 갖지 않도록 도와주자. 미래의 보상을 누적하되, 감쇠율 0.9를 적용하는 것이다.0123456789행동→↓→↓←↑→↓←↓보상1.932.152.391.541.711.901.000.000.000.00rewards = scanr (\x y -> x + 0.9 * y) 0 (fmap (uncurry rewardFn) (trainAgent agent))<이제 나머지는 GPU한테 맡기면 된다. 조금만 기다리면 위의 동영상에서처럼 움직이는 뱀을 볼 수 있다.<여기서 GPU를 100장 더 사서 뱀 대신에 좀더 우리 삶에 도움되는 에이전트를 학습시킨다면, 그걸 10년전에 했으면, 난 지금 부자가 되어있을지도 모르겠다. 하지만 기회는 이미 떠났고, 난 지금 돈은 없지만 대신 시간은 많다. 그 시간을, 지금의 그럭저럭 볼만한 코드를 쥐꼬리만큼 개선하는데 낭비해보려 한다. 지금 코드에서 뭐가 마음에 안드냐면,<보상이 사실 서로 다른 두 개를 가리킨다 먹이를 먹자마자 즉각적으로 주는 보상과, 그것을 누적한 보상, 이렇게 두 개가 있다. 실제로 학습에 사용하는 것은 후자이다. 그런데 막상 보상 함수의 정의는 전자에 대한 것이다. 이는 보상 함수를 계산할 때 미래에 어떤 일이 일어나는지 알수가 없어서 그렇다. 정의를 두 개로 나눈 이유가 의미를 명쾌하게 하기 위해서가 아니라, 그냥 한번에 계산을 할수 없기 때문이다.<환경의 정의 위에서 살펴본 runAgent의 정의가 일견 우아해보일 수 있다. 문제는 그 정의는 환경과 에이전트가 모두 순수 함수일 것을 강요한다는 것이다. Environment의 정의도 마찬가지다. 환경과 에이전트는 각자의 부수효과 Side effect 를 가질 수 있어야 한다. 가령 온라인 게임을 환경으로 삼는다면, 환경은 네트워킹을 할 수 있어야 한다. 또, 에이전트는 매번 똑같은 선택이 아닌 확률적 선택을 하고 싶을텐데, 이는 순수 함수로써는 불가능하다.<그러면 부수효과를 허용하면 되는거 아냐?<맞다. 나처럼 시간이 많다면 직접 해보는 것도 나쁘지 않다. 하지만 정의가 점점 지저분해지는 것을 보게될 것이고... 시간을 아껴주기 위해 정답을 알려주겠다. 환경은 에이전트가 실행될 수 있는 모나드여야 한다. 딱 거기까지여야 한다. 환경과 에이전트 사이에 그 이상의 관계는 부적절하다.<글이 생각했던 것보다 길어져버려서, 오늘은 여기까지 해야겠다. 이어지는 글에서 거꾸로 상태 모나드가 이걸 어떻게 해결하는지 소개한다. 사실 아까 환경이니 에이전트니 어쩌고 할때부터, 진작에 강화 학습을 마스터한 학생들이 이미 다 아는 내용에 지겨워 졸기 시작하는게 보였다. 다음 수업은 재밌을테니, 대신 그때까지 모나드를 배워오세요.

hackers.pub · Hackers' Pub

Link author: bgl gwyng@bgl@hackers.pub

8
1

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

간단한 rpmbuild의 사용과 private rpm package 배포

Perlmint @perlmint@hackers.pub

마지못해 패키지를 만들어야 할 것 같은 사람을 위한 설명입니다. 제대로된 패키지를 만들고 싶은 경우에는 부족한 점이 많습니다.

대부분의 경우에는 프로그램을 직접 소스에서 빌드하는 일도 적고, 그걸 시스템 전역에 설치하는 일도 흔치는 않을 것입니다. 좋은 패키지매니저와 관리가 잘되는 패키지 저장소들을 두고 아주 가끔은 직접 빌드를 할 일이 생기고, 흔치 않게 시스템 전역에 설치할 일이 생길 수 있습니다. 어지간한 프로그램들은 요즈음의 장비에서는 별 불만 없이 빌드 할 만한 시간이 소요되나, 컴파일러처럼 한번 빌드했으면 다시는 하고 싶지 않은 프로그램을 다시 설치해야하는 경우도 있을 수 있습니다. 하필 이런 프로그램들은 결과물도 덩치가 매우 큽니다. 이럴 때는 최대한 간단하고 필요한 항목만 패키지에 넣어서 만들어두고 다시 활용하면 좋을 것이기에 이런 경우를 위한 rpmbuild에 대한 나름 최소한의 사용 방법을 정리해봅니다.

rpmbuild

rpmbuild는 rpm-build 패키지로 설치가 가능하며, 나름 단순하게 rpm으로 패키징을 할 수 있는 유틸리티입니다. spec파일에 패키지 정보, 빌드 명령, 설치 명령, 패키지가 포함해야 할 파일 목록을 작성해서 rpmbuild에 입력으로 넣어주면 빌드부터 시작해서 rpm패키지를 만들어줍니다. native 프로그램의 경우 디버그 심볼을 알아서 분리해서 별도의 패키지로 만들어주고, 필요한 의존성도 추정해서 명시해줍니다. 또한, 필요한 경우 하나의 spec 명세로 연관된 서브 패키지도(ex. 실행파일 패키지인 curl과 라이브러리 패키지 libcurl, 라이브러리를 사용하기 위한 개발 패키지 libcurl-devel) 같이 만들 수 있습니다.

작업 환경

rpmbuild는 기본으로 ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS,BUILDROOT}의 경로에서 동작하며 각 경로의 용도는 다음과 같습니다.

  • SOURCES에는 압축된 소스코드가 위치합니다.
  • SPECS에는 패키지 정의인 spec파일을 둡니다.
  • BUILD밑에서 빌드 작업이 진행됩니다.
  • RPMS에 바이너리 rpm결과물이 생성됩니다.
  • SRPMS에는 소스 rpm결과물이 생성됩니다.
  • BUILDROOT는 패키징 하기 위해 빌드 결과물을 모으는 경로입니다.

spec파일

spec파일은 패키지를 어떻게 빌드하고 어떤 항목들이 패키지에 포함될지, 패키지의 이름, 설명 및 의존성 등의 메타데이터, 패키지 설치, 삭제시의 스크립트를 정의할 수 있습니다. 보통 시작 부분에는 메타데이터 정의로 시작하며, 다음과 같은 기본적인 형태를 취합니다. 나름 단순하게 만든 python을 위한 spec을 예시로 들어보겠습니다.

Summary: Python %{version}
Name: python-alternative
Version: %{version}
Release: 1%{?dist}
Obsoletes: %{name} <= %{version}
Provides: %{name} = %{version}
URL: https://www.python.org
Requires: libffi openssl
AutoReq: no
License: PSFL

Source: https://www.python.org/ftp/python/%{version}/Python-%{version}.tgz

BuildRequires: libffi-devel openssl-devel
BuiltRoot: %{_tmppath}/%{name}-%{version}-%{release}-root

%define major_version %(echo "%{version}" | sed -E 's/^([0-9]+)\\..+/\1/' | tr -d)
%define minor_version %(echo "%{version}" | sed -E 's/^[0-9]+\\.([0-9]+)\\..+/\1/' | tr -d)

%description
Python

%package devel
Summary: python development files
Requires: %{name} = %{version}-%{release}

%description devel
Python development package

%prep
%setup -q -n Python-%{version}

%build
./configure --prefix=%{_prefix}

%install
%{__make} altinstall DESTDIR=%{buildroot}
%{__ln_s} -f %{_bindir}/python%{major_version}.%{minor_version} %{buildroot}/%{_bindir}/python%{major_version}

%clean
%{__rm} -rf %{buildroot}

%files
%{_bindir}/python*
%exclude %{_bindir}/idle*
%{_bindir}/pip*
%{_bindir}/pydoc*
%exclude %{_bindir}/2to3*
%{_libdir}/libpython*
%{_prefix}/lib/libpython*
%{_prefix}/lib/python*
%{_mandir}/man1/python*

%files devel
%{_includedir}/python*
%{_prefix}/lib/pkgconfig/python*

%로 매크로를 사용할 수 있으며, %package, %description, %files 같은 매크로는 인자를 주어서 서브 패키지를 정의하는데도 쓸 수 있습니다. 앞선 예제처럼 devel 이라고작성하면 메인 패키지이름 뒤에 붙여서 python-alternative-devel가 되며, curl - libcurl과 같은 경우에는 메인의 이름은 curl이고, 딸린 패키지를 정의할 때는 %package -n libcurl과 같이 -n옵션을 추가해서 지정할 수 있습니다. 몇몇 매크로는 단계를 정의하는 것과 같은 동작을 하며 다음과 같습니다.

%package

유사성을 보면 spec파일의 맨 첫부분은 메인 패키지의 %package에 해당하는 것이 아닌가 싶습니다. <Key>: <Value>의 형태로 메타정보를 작성합니다. 대부분은 Key를 보면 무슨 값인지 추측 할 만합니다. 나중에 설명할 %files에서 나열한 파일을 rpmbuild가 분석하여 자동으로 패키지가 필요로 하는 의존성을 추정해서 추가 해 줍니다. python 스크립트, perl 스크립트, native 실행파일 등을 분석해서 알아서 추가해주는 것 같은데, 경우에 따라서는 틀린 의존성을 추가해주기도 합니다. 이 때는 AutoReq: no를 설정하여 자동 의존성 추가를 막을 수 있습니다. 이 python-alternative 패키지는 /usr/local/bin/python%{version}을 설치하는데 아마도 같이 포함되는 python 스크립트에 의해서 /bin/python을 의존성으로 추정하여 요구합니다. 패키지 스스로가 제공하는 의존성은 미리 설치 되어있기를 요구하지 않게 동작하는 것 같으니 보통은 문제가 없습니다만, 이 경우에는 스스로 제공을 하지 않기 때문에 python을 설치하기 위해서 python이 필요한 경우가 발생하므로 AutoReq를 껐습니다.

%prep

준비단계로 소스코드의 압축을 해제하고 필요한경우 패치를 적용합니다. %setup 매크로를 이 안에서 보통 사용하며, %setupSource에 명시된 파일명의 압축 파일을 SOURCES 밑에서 찾아서 압축을 풉니다. 그리고 동일한 이름의 디렉토리로 이동을 합니다. 앞선 예제에서는 SOURCES/Python-%{version}.tgz의 압축을 풀고 Python-%{version}으로 이동을 합니다. 패치가 필요한 경우 보통 이 뒤에 패치를 적용하는 명령들을 추가 합니다.

%build

설정, 컴파일 등을 수행하는 단계입니다. 이곳에서 자주 하는 매크로로 %configure, %make_build 등이 있습니다. %configure는 configure를 prefix 및 기타 몇가지 일반적으로 쓰이는 옵션을 추가하여 실행해주며, %make_buildmake와 비슷하게 모든 타겟을 빌드 합니다. 예제에서는 둘다 안쓰고 있고, 심지어 실제 빌드는 안하는데 어쨌든 이후의 %install까지 지나고나서 빌드 결과물만 맞는 위치에 만들어지면 대충 패키지를 만드는데는 별 문제는 없는 것 같습니다.

%install

여기서 빌드 결과물을 설치하는 명령을 작성합니다. 일반적으로 %make_install을 사용하여 make install DESTDIR=%{buildroot}와 비슷한 명령을 수행하여 %{buildroot}밑에 빌드 결과물이 prefix를 유지하여 설치되게 합니다. 예제의 %{__ln_s} -f %{_bindir}/python%{major_version}.%{minor_version} %{buildroot}/%{_bindir}/python%{major_version}을 보면 추정 할 수 있듯이, 패키지에 포함시킬 파일들을 %{buildroot}밑에 생성을 하면 되며, 추가적인 심볼릭 링크는 패키지를 빌드하는 시점에는 존재하지 않지만, 패키지를 설치하게되면 존재하게 될 %{_bindir}/python%{major_version}.%{minor_version}를 향하는 것을 %{buildroot} 밑인 %{buildroot}/%{_bindir}/python%{major_version}에 만듭니다.

%files

패키지에 포함될 파일 목록을 작성합니다. glob 양식으로 파일 목록을 작성할 수 있습니다. %{buildroot} 밑에 생성 되었지만 어느 %files에도 포함되지 않은 파일이 있는 경우에는 빌드를 실패합니다. 그러므로 %exclude를 사용해서 명시적으로 제외해줘야 합니다.

기타 매크로

rpmbuild에서는 기본으로 다양한 매크로를 제공하고 있습니다. --define "_libdir %{_prefix}/lib64"와 같은 옵션을 실행시에 주어서 실행시점에 매크로를 덮어 쓸 수도 있고, 앞선 spec파일 내의 %define major_version 와 같이 다른 매크로와 셸 명령을 활용하여 매크로를 정의 할 수도 있습니다. 원하는 동작을 안하는 것 같은 경우에는 --show-rc옵션을 사용하여 매크로가 어떻게 정의되어있는지 확인해 볼 수 있습니다.

빌드

rpmbuild의 매뉴얼을 보면 자세하게 나와있지만 가장 단순하게는 rpmbuild -bb <specfile>로 바이너리 패키지를 빌드할 수 있습다. 이 때, 압축된 소스코드는 미리 SOURCES밑에 두어야 합니다.

private rpm package 배포

직접 비공개 패키지 저장소 프로그램을 실행하여 제공하는 방법도 있겠지만, 최대한 간단하게 할 수 있는 방법으로, rpm관련 패키지 설치 명령이 입력으로 http등의 URL도 받는 것을 활용하여 적당한 장비에서 http로 서빙을 해주면 됩니다.

Read more →
4
1
1
1
3
2

왜 맥북으로 개발을 하면 상시로 저장공간이 모자란 걸까요? 500GB 쓰는데 그렇습니다. OmniDisk를 가끔 돌려보는데 한 300GB정도가 어딘가 숨어있어요...

5

よっしゃ、Deno compileで、tar.gzをbase64にエンコードしてシングルバイナリの中にいれて、バイナリ1個だけもっていったら、ええようにできた。 いま、このタイミングだとLLMの恩恵を受けやすいTypeScriptは、プログラマの道具箱に入れておくのは良い。

1
2
1
3
0
0
2

다른 얘기지만 “에모지 리액션을 하나밖에 달지 못한다”는 Misskey의 제약이라고 알고 있습니다. Hackers' Pub도 그렇고 Pleroma/Akkoma도 그렇고 한 사람이 같은 게시물에 여러 에모지를 달 수 있게 되어 있어요.



RE: https://yuri.garden/notes/a6x41eyvis

2
2

n.news.naver.com/mnews/article
[단독] “해커에 뚫린 이유 있었네”… SK텔레콤, 정보보호 투자비 감액

통신업계 관계자는 “SK텔레콤은 지금까지 해킹 공격 피해를 입은 적이 없다는 안이함이 정보보호 투자 축소로 이어졌다”면서 “유영상 사장 체제에서 인공지능(AI) 투자에 집중한 나머지 정보보호 투자에는 소홀해 뼈아픈 실책이 됐다”고 말했다.

이거 서버관리실 담당자를 싹 해고하고 나서 온갖 사건사고 터지고 사장이 울며불며 돌아와달라 했던 사건이랑 비슷한거같은데, 피해가 없다면 관리자님들이 일 잘하는거임... :ablobcat_frustration:

2
0
0
4

🤔

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.

https://github.com/misskey-dev/xq

3
0
0

JS에서는 라이브러리의 함수를 쓸때 this binding이 되어있는지 아닌지를 몰라서 a = b.c라고 마음대로 못 쓰고 a = (x) => b.c(x)가 되는지 먼저 꼭 확인해야한다. 안습;;

1
2
6

해커스펍에서 댓글을 달 때, 굳이 @로 아이디 언급을 하지 않아도, 원 글과 타래는 연관 지어지는 거지요? 타래에 참여하고 있는 분들이 여럿이라면, 다 언급을 해야 하는 거고, 한 분이라면 굳이 언급하지 않아도 되는 거고요?

1

3년차 웹 프런트엔드 개발자입니다. 잠시 10주 여름 방학 동안 계약직으로 일할 수 있는 직장을 찾고 있습니다. (6월 마지막 주부터 8월 마지막 주) http://frontend.moe/portfolio/

올해 2학기까지 수료하면 졸업 예정이라, 학부 졸업 이후 정규직 전환 조건으로도 희망하고 있습니다.

4
1
9
0

바이브 코딩에 줄곧 Claude Sonnet 3.7만 쓰다가, 오늘 Gemini 2.5 Pro를 써 봤는데, 코딩을 더 잘 하는지는 잘 모르겠지만 응답 속도 하나만은 훨씬 빨라서 좋다. 바이브 코딩을 하다가 결국 답답함을 못 참고 내가 직접 코딩하게 되는 까닭 중 하나가 기다림의 지루함이었는데, 그 부분이 많이 완화된달까?

3

https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.6#superclass-expansion-is-more-conservative

내가 9.4 -> 9.6 마이그레이션에서 겪고 있는 문제가 이거랑 관련이 있는거 같은데(확실치 않음)... 9.4에서는 c :: Type -> Constraint 일때 forall c. c Int 뭐 이런 조건이 있으면, 모든 c에 대해 c Int가 존재하는게 말이 안되는데도 실제로 c Int 꼴로 쓰이는 c만 고려해서 타입체크를 통과시켜줬던거 같다(이것도 확실하지 않음). 근데 9.6에선 당연히 거부당한다.

위의 내 이해가 맞다면 9.4의 constraint solving 완전 무근본이었단건데, 이건 또 믿기 어렵다(하스켈의 설계 결정에 대한 신뢰 유지한다고 하면). 어디서 내가 잘못 파악한거지.

3
1

WinRing0: 왜 Windows가 각종 PC 모니터링 앱을 악성코드로 인식하기 시작했는가
------------------------------
* 2025년 3월 11일부터 전세계 수많은 PC 유저들이 Windows Defender(Windows에 내장된 안티바이러스 앱)로부터 악성 코드 경고를 받기 시작함.
* 악성 코드의 진원지는 대부분 PC 제어용 소프트웨어로, Razer Synapse, SteelSeries Engine, MSI Afterburner 등이 포함되어 있음.
* 이들 소프트웨어들의 공통점이 모…
------------------------------
https://news.hada.io/topic?id=20453&utm_source=googlechat&utm_medium=bot&utm_campaign=1834

0
0

Hackers' Pub에도 팀 계정 같은 걸 만들어야 하나 싶은 생각이 가끔 드는데… 이를테면 현재로서는 Hackers' Pub 공식 계정을 깔끔하게 만들 방법이 떠오르지 않는다. 안 쓰는 메일 주소로 새 계정을 파는 식으로 해야 하는데, 별로 그런 식으로 풀고 싶지가 않다.

7

I've been reflecting lately on projects like @fedifyFedify: an ActivityPub server framework, @holloHollo :hollo:, and @botkitBotKit by Fedify :botkit:. Sometimes I wonder if I'm solving problems that very few people actually need solved. How many developers truly want to build their own server from scratch?

It feels a bit like inventing shoes that let people walk on their hands all day. Would there be a viable market? How many would actually buy them?

That's the sense I get with these projects. They do have users who find them tremendously valuable, but the total user base is inherently limited. The tools serve an important function for a small audience of specialized developers.

There are moments when my motivation wavers. When the user community consists of just a handful of enthusiastic supporters, it's sometimes difficult to maintain momentum and justify the ongoing investment of time and energy.

And yet, there's something meaningful about creating specialized tools that solve complex problems well, even if they're only used by a few. Perhaps that's enough.

0

현재의 이른바 “에이전틱” 코딩 어시스턴트들은 종래의 정적 분석 기술을 활용하지 못하는데, 아마도 머지 않은 미래에 둘이 결합될 날이 올 것 같긴 하다. 다시 말해, 애초에 LLM이 컴파일조차 안 되는 코드를 뱉지는 못하게 할 수 있을 거라고 생각한다. 그 때가 되면 정말 평균적인 사람 프로그래머가 이룰 수 있는 품질의 코드를 내놓을 수 있지 않을까? 컴파일도 되고, 겉보기에는 잘 돌아가지만, 몇몇 코너 케이스에서는 여전히 깨지는… 그럼 그때는 또 LLM이 QA도 하고 코드 리뷰도 해서 고치는 미래가…!?

2
2
0
0
6

BotKit 0.2.0 릴리스

BotKit 0.2.0 버전이 릴리스되었습니다! BotKit을 처음 접하시는 분들을 위해 간단히 소개하자면, BotKit은 TypeScript로 개발된 독립형 봇 프레임워크입니다. Mastodon, Misskey 등 다양한 () 플랫폼과 상호작용할 수 있으며, 기존 플랫폼의 제약에서 벗어나 자유롭게 봇을 만들 수 있습니다.

이번 릴리스는 연합우주 봇 개발을 더 쉽고 강력하게 만들기 위한 여정에서 중요한 발걸음입니다. 커뮤니티에서 요청해 왔던 여러 기능들을 새롭게 선보입니다.

더 나은 봇 상호작용을 위한 여정

BotKit을 개발하면서 우리는 항상 봇이 더 표현력 있고 상호작용이 풍부하도록 만드는 데 집중해 왔습니다. 0.2.0 버전에서는 연합우주의 사회적 측면을 봇에 접목시켜 한 단계 더 발전시켰습니다.

커스텀 에모지로 봇의 개성 표현하기

가장 많이 요청받았던 기능 중 하나가 지원입니다. 이제 봇은 독특한 시각적 요소로 메시지를 돋보이게 하며 자신만의 개성을 표현할 수 있습니다.

// 봇의 커스텀 에모지 정의하기
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" 
  }
});

// 메시지에 커스텀 에모지 사용하기
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}은 Fedify ${customEmoji(emojis.fedify)}의 지원을 받습니다`
);

이 새로운 API를 통해 다음과 같은 기능을 사용할 수 있습니다.

반응을 통한 소통

소통은 단순히 메시지를 게시하는 것만이 아닙니다. 다른 사람의 메시지에 반응하는 것도 중요합니다. 새로운 반응 시스템은 봇과 팔로워 사이에 자연스러운 상호작용 지점을 만들어 줍니다.

// 표준 유니코드 에모지로 메시지에 반응하기
await message.react(emoji`👍`);

// 또는 정의한 커스텀 에모지로 반응하기
await message.react(emojis.botkit);

// 반응을 인식하고 응답하는 봇 만들기
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}님, 제 메시지에 ${reaction.emoji} 반응을 남겨주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

이 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

  • Message.react()를 사용하여 유니코드 에모지로 메시지에 반응하기
  • 정의한 커스텀 에모지로 반응하기
  • Bot.onReactBot.onUnreact 핸들러로 반응 이벤트 처리하기

인용을 통한 대화

토론에서는 종종 다른 사람이 말한 내용을 참조해야 할 때가 있습니다. 새로운 기능은 더 응집력 있는 대화 스레드를 만들어 줍니다.

// 봇의 게시물에서 다른 메시지 인용하기
await session.publish(
  text`이 흥미로운 관점에 대한 답변입니다...`,
  { quoteTarget: originalMessage }
);

// 사용자가 봇의 메시지를 인용할 때 처리하기
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}님, 제 생각을 공유해 주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

인용 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

시각적 개선

소통은 시각적인 요소도 중요하기 때문에 봇의 표현 방식을 개선했습니다.

  • 웹 인터페이스에서 이미지 첨부파일이 제대로 표시됩니다
  • 봇의 콘텐츠가 더 보기 좋아지고 풍부한 경험을 제공합니다

내부 개선: 향상된 액티비티 전파

연합우주에서 액티비티가 전파되는 방식도 개선했습니다.

  • 답글, 공유, 업데이트, 삭제의 더 정확한 전파
  • 원본 메시지 작성자에게 액티비티가 제대로 전송됩니다

이러한 개선 사항은 다양한 연합우주 플랫폼에서 봇의 상호작용이 일관되고 안정적으로 이루어지도록 보장합니다.

BotKit 0.2.0으로 첫 걸음 떼기

이러한 새로운 기능을 경험해 보고 싶으신가요? BotKit 0.2.0은 JSR에서 받을 수 있으며 간단한 명령어로 설치할 수 있습니다.

deno add jsr:@fedify/botkit@0.2.0

BotKit은 Temporal API(JavaScript에서 아직 시범적인 기능)를 사용하므로 deno.json에서 이를 활성화해야 합니다.

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

이 간단한 단계를 통해 최신 기능으로 연합우주 봇을 만들거나 업그레이드할 준비가 완료되었습니다.

앞으로의 전망

BotKit 0.2.0은 연합우주 봇 개발을 접근하기 쉽고, 강력하며, 즐겁게 만들기 위한 우리의 지속적인 노력을 보여줍니다. 이러한 새로운 기능들이 여러분의 봇이 연합우주 커뮤니티에서 더 매력적이고 상호작용이 풍부한 구성원이 되는 데 도움이 될 것이라고 믿습니다.

전체 문서와 더 많은 예제는 저희 문서 사이트에서 확인하실 수 있습니다.

피드백, 기능 요청, 코드 기여를 통해 이번 릴리스에 도움을 주신 모든 분들께 감사드립니다. BotKit 커뮤니티는 계속 성장하고 있으며, 여러분이 만들어낼 작품들을 기대합니다!


BotKit은 ActivityPub 서버 애플리케이션을 만들기 위한 하위 레벨 프레임워크인 Fedify의 지원을 받습니다.

BotKit 0.2.0のリリース

BotKit 0.2.0をリリースしました!BotKitを初めて知る方のために簡単に説明すると、BotKitはTypeScriptで開発されたスタンドアロンのActivityPubボットフレームワークです。Mastodon、Misskeyなどさまざまなフェディバース()のプラットフォームと連携でき、既存プラットフォームの制約なしに自由にボットを作成できます。

このリリースは、フェディバースにおけるボット開発をより簡単で強力にするための旅の重要な一歩であり、コミュニティから要望のあった機能を多数導入しています。

より良いボットインタラクションへの旅

BotKitの開発において、私たちは常にボットをより表現力豊かでインタラクティブにすることに焦点を当ててきました。バージョン0.2.0では、フェディバースの社会的側面をボットに取り入れることで、さらに一歩前進しました。

カスタム絵文字でボットの個性を表現

最も要望の多かった機能の一つがカスタム絵文字のサポートです。これにより、ボットは独自の視覚要素でメッセージを目立たせ、自分だけの個性を表現できるようになりました。

// ボット用のカスタム絵文字を定義
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" 
  }
});

// メッセージにカスタム絵文字を使用
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}は、Fedify ${customEmoji(emojis.fedify)}によって支えられています`
);

この新しいAPIでは、次のことが可能になりました。

リアクションによるコミュニケーション

コミュニケーションは単にメッセージを投稿するだけではありません。他の人のメッセージに反応することも重要です。新しいリアクションシステムは、ボットとフォロワーの間に自然な交流ポイントを作り出します。

// 標準のUnicode絵文字でメッセージにリアクション
await message.react(emoji`👍`);

// または定義したカスタム絵文字でリアクション
await message.react(emojis.botkit);

// リアクションを認識して応答するボットを作成
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}さん、私のメッセージに${reaction.emoji}でリアクションしてくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

この機能により、ボットは次のことができるようになりました。

  • Message.react()を使用してUnicode絵文字でメッセージにリアクション
  • 定義したカスタム絵文字でリアクション
  • Bot.onReactBot.onUnreactハンドラーでリアクションイベントを処理

引用による会話

議論では、他の人が言ったことを参照する必要がしばしばあります。新しい引用機能により、より結束力のある会話スレッドを作成できます。

// ボットの投稿で他のメッセージを引用
await session.publish(
  text`この興味深い視点について答えます...`,
  { quoteTarget: originalMessage }
);

// ユーザーがボットのメッセージを引用した場合の処理
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}さん、私の考えを共有してくれてありがとうございます!`,
    { visibility: "direct" }
  );
};

引用機能により、ボットは次のことができるようになりました。

  • quoteTargetオプションでメッセージを引用
  • Message.quoteTargetを通じて引用されたメッセージにアクセス
  • 新しいBot.onQuoteイベントハンドラーで引用イベントを処理

視覚的な改善

コミュニケーションには視覚的要素も重要なため、ボットの表現方法を改善しました。

  • ウェブインターフェースで画像添付ファイルが正しく表示されるようになりました
  • ボットのコンテンツがより見やすくなり、豊かな体験を提供します

内部改善:活動の伝播の強化

フェディバースでの活動が伝播する方法も改善されました。

  • 返信、共有、更新、削除のより正確な伝播
  • 元のメッセージ作成者に活動が適切に送信されます

これらの改善により、様々なフェディバースプラットフォームでのボットの相互作用が一貫性と信頼性を持つようになります。

BotKit 0.2.0で最初の一歩を踏み出す

これらの新機能を体験してみたいですか?BotKit 0.2.0はJSRで利用可能で、簡単なコマンドでインストールできます。

deno add jsr:@fedify/botkit@0.2.0

BotKitはTemporal API(JavaScriptではまだ試験的な機能)を使用するため、deno.jsonでこれを有効にする必要があります。

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

これらの簡単なステップで、最新機能を使ってフェディバースボットを作成またはアップグレードする準備が整いました。

今後の展望

0.2.0は、フェディバースボット開発をアクセスしやすく、強力かつ楽しいものにするための私たちの継続的な取り組みを示しています。これらの新機能が、皆さんのボットをフェディバースコミュニティでより魅力的でインタラクティブなメンバーにするのに役立つと信じています。

完全なドキュメントと詳細な例については、私たちのドキュメントサイトをご覧ください。

フィードバック、機能リクエスト、コード貢献を通じてこのリリースに貢献してくださったすべての方々に感謝します。BotKitコミュニティは成長を続けており、皆さんが作成するものを楽しみにしています!


BotKitは、ActivityPubサーバーアプリケーションを作成するための低レベルフレームワークFedifyによって支えられています。

3

BotKit 0.2.0 Released

We're pleased to announce the release of BotKit 0.2.0! For those new to our project, is a framework for creating standalone bots that can interact with Mastodon, Misskey, and other 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 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:

Engaging Through Reactions

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" }
  );
};

This feature allows your bot to:

Conversations Through Quotes

Discussions often involve referencing what others have said. Our new 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 quote support, your bot can:

Visual Enhancements

Because communication is visual too, we've improved how your bot presents itself:

  • Image attachments now properly display in the web interface
  • Your bot's content looks better and provides a richer experience

Behind the Scenes: Enhanced Activity Propagation

We've also improved how activities propagate through the fediverse:

  • More precise propagation of replies, shares, updates, and deletes
  • Activities are now properly sent to the original message authors

These improvements ensure your bot's interactions are consistent and reliable across different fediverse platforms.

Taking Your First Steps with BotKit 0.2.0

Ready to experience these new features? BotKit 0.2.0 is available on JSR and can be installed with a simple command:

deno add jsr:@fedify/botkit@0.2.0

Since BotKit uses the Temporal API (which is still evolving in JavaScript), remember to enable it in your deno.json:

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

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 0.2.0 버전이 릴리스되었습니다! BotKit을 처음 접하시는 분들을 위해 간단히 소개하자면, BotKit은 TypeScript로 개발된 독립형 봇 프레임워크입니다. Mastodon, Misskey 등 다양한 () 플랫폼과 상호작용할 수 있으며, 기존 플랫폼의 제약에서 벗어나 자유롭게 봇을 만들 수 있습니다.

이번 릴리스는 연합우주 봇 개발을 더 쉽고 강력하게 만들기 위한 여정에서 중요한 발걸음입니다. 커뮤니티에서 요청해 왔던 여러 기능들을 새롭게 선보입니다.

더 나은 봇 상호작용을 위한 여정

BotKit을 개발하면서 우리는 항상 봇이 더 표현력 있고 상호작용이 풍부하도록 만드는 데 집중해 왔습니다. 0.2.0 버전에서는 연합우주의 사회적 측면을 봇에 접목시켜 한 단계 더 발전시켰습니다.

커스텀 에모지로 봇의 개성 표현하기

가장 많이 요청받았던 기능 중 하나가 지원입니다. 이제 봇은 독특한 시각적 요소로 메시지를 돋보이게 하며 자신만의 개성을 표현할 수 있습니다.

// 봇의 커스텀 에모지 정의하기
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" 
  }
});

// 메시지에 커스텀 에모지 사용하기
await session.publish(
  text`BotKit ${customEmoji(emojis.botkit)}은 Fedify ${customEmoji(emojis.fedify)}의 지원을 받습니다`
);

이 새로운 API를 통해 다음과 같은 기능을 사용할 수 있습니다.

반응을 통한 소통

소통은 단순히 메시지를 게시하는 것만이 아닙니다. 다른 사람의 메시지에 반응하는 것도 중요합니다. 새로운 반응 시스템은 봇과 팔로워 사이에 자연스러운 상호작용 지점을 만들어 줍니다.

// 표준 유니코드 에모지로 메시지에 반응하기
await message.react(emoji`👍`);

// 또는 정의한 커스텀 에모지로 반응하기
await message.react(emojis.botkit);

// 반응을 인식하고 응답하는 봇 만들기
bot.onReact = async (session, reaction) => {
  await session.publish(
    text`${reaction.actor}님, 제 메시지에 ${reaction.emoji} 반응을 남겨주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

이 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

  • Message.react()를 사용하여 유니코드 에모지로 메시지에 반응하기
  • 정의한 커스텀 에모지로 반응하기
  • Bot.onReactBot.onUnreact 핸들러로 반응 이벤트 처리하기

인용을 통한 대화

토론에서는 종종 다른 사람이 말한 내용을 참조해야 할 때가 있습니다. 새로운 기능은 더 응집력 있는 대화 스레드를 만들어 줍니다.

// 봇의 게시물에서 다른 메시지 인용하기
await session.publish(
  text`이 흥미로운 관점에 대한 답변입니다...`,
  { quoteTarget: originalMessage }
);

// 사용자가 봇의 메시지를 인용할 때 처리하기
bot.onQuote = async (session, quoteMessage) => {
  await session.publish(
    text`${quoteMessage.actor}님, 제 생각을 공유해 주셔서 감사합니다!`,
    { visibility: "direct" }
  );
};

인용 기능을 통해 봇은 다음과 같은 작업을 수행할 수 있습니다.

시각적 개선

소통은 시각적인 요소도 중요하기 때문에 봇의 표현 방식을 개선했습니다.

  • 웹 인터페이스에서 이미지 첨부파일이 제대로 표시됩니다
  • 봇의 콘텐츠가 더 보기 좋아지고 풍부한 경험을 제공합니다

내부 개선: 향상된 액티비티 전파

연합우주에서 액티비티가 전파되는 방식도 개선했습니다.

  • 답글, 공유, 업데이트, 삭제의 더 정확한 전파
  • 원본 메시지 작성자에게 액티비티가 제대로 전송됩니다

이러한 개선 사항은 다양한 연합우주 플랫폼에서 봇의 상호작용이 일관되고 안정적으로 이루어지도록 보장합니다.

BotKit 0.2.0으로 첫 걸음 떼기

이러한 새로운 기능을 경험해 보고 싶으신가요? BotKit 0.2.0은 JSR에서 받을 수 있으며 간단한 명령어로 설치할 수 있습니다.

deno add jsr:@fedify/botkit@0.2.0

BotKit은 Temporal API(JavaScript에서 아직 시범적인 기능)를 사용하므로 deno.json에서 이를 활성화해야 합니다.

{
  "imports": {
    "@fedify/botkit": "jsr:@fedify/botkit@0.2.0"
  },
  "unstable": ["temporal"]
}

이 간단한 단계를 통해 최신 기능으로 연합우주 봇을 만들거나 업그레이드할 준비가 완료되었습니다.

앞으로의 전망

BotKit 0.2.0은 연합우주 봇 개발을 접근하기 쉽고, 강력하며, 즐겁게 만들기 위한 우리의 지속적인 노력을 보여줍니다. 이러한 새로운 기능들이 여러분의 봇이 연합우주 커뮤니티에서 더 매력적이고 상호작용이 풍부한 구성원이 되는 데 도움이 될 것이라고 믿습니다.

전체 문서와 더 많은 예제는 저희 문서 사이트에서 확인하실 수 있습니다.

피드백, 기능 요청, 코드 기여를 통해 이번 릴리스에 도움을 주신 모든 분들께 감사드립니다. BotKit 커뮤니티는 계속 성장하고 있으며, 여러분이 만들어낼 작품들을 기대합니다!


BotKit은 ActivityPub 서버 애플리케이션을 만들기 위한 하위 레벨 프레임워크인 Fedify의 지원을 받습니다.

0