본문으로 건너뛰기
Chandler Nguyen
AI10분 읽기

9개 에이전트 마케팅 플랫폼을 오픈소스로 내놨어요

STRAŦUM의 v1이 MIT 라이선스로 공개됐어요. 에이전트 9개, Postgres 스키마 2개, 로케일 10개 — 그리고 Row Level Security가 꺼진 채 배포돼서, 브라우저에 로드되는 키만 있으면 누구나 접근할 수 있었던 테이블 하나까지. 제가 무엇을 내놓았고, 다시는 같은 방식으로 만들지 않을 것은 무엇인지, 그리고 왜 포크해서 자기만의 것을 만들어도 되는지 정리할게요.

오늘 제 마케팅 플랫폼의 첫 버전을 오픈소스로 공개했어요.

이름은 STRAŦUM(스트라텀)이에요. AI 에이전트 9개, 고객사별로 데이터를 분리하는 에이전시 워크스페이스, 10개 언어. 2025년에 소프트웨어를 독학하던 시절에 만들었어요. 그다음 두 번째 버전 작업을 시작했고, 첫 버전을 혼자 묻어두는 대신 세상에 내놓았어요.

나머지를 읽기 전에 먼저 보고 싶다면: github.com/chandlernguyen/stratum-oss

git clone https://github.com/chandlernguyen/stratum-oss

마케팅 팀을 이끌고 있고 이 저장소를 열 일이 전혀 없다면, 마지막쯤에 있는 "코드를 읽을 일이 없다면"으로 건너뛰세요. 그 섹션은 그런 분을 위한 짧은 글이에요.

이 저장소가 무엇인지는 정확히 말해두고 싶어요. 오픈소스라는 말은 여러 의미로 쓰이고, 그 대부분은 이게 실제로 내놓는 것보다 과해요.

실제로 공개한 것

STRAŦUM v1은 공개돼 있고, 적극적으로 개발하고 있지는 않아요. 코드는 MIT 라이선스로 공개돼 있고, 로드맵도 릴리스 일정도 지원 약속도 없어요 — README에 그렇게 적혀 있고, 기여 가이드에도 다시 한번 적혀 있죠.

레퍼런스 구현으로 공개한 거예요. 읽기 위한 것이고, 포크하기 위한 것이고, 일부만 가져다 쓰기 위한 것이에요. 의존하기 위한 것은 아니에요. 앞으로 의존성이 바뀔 때 맞춰서 유지보수해줄 사람은 없고, 저장소에는 알고 있는 미해결 권고(advisory)를 없는 척하지 않고 그대로 적어놨어요.

절대 바뀌지 않는다는 말은 아니에요. 더 이상 개발하지 않으니 지금 그대로라고 보고 계획하면 돼요 — 그래도 사람들이 보내는 것은 읽어요. 누군가 버그를 알려주거나 코드를 더 명확하게 만드는 제안을 해주면, 못 본 척하지는 않아요.

공개한다는 건 기밀 정보가 함께 나가지 않았다는 걸 증명하는 일이기도 했어요. 저장소에는 추적 중인 모든 파일에서 자격 증명, 개인 키, 프로바이더 토큰, 프로덕션 식별자를 스캔하는 스크립트가 있고, 이게 CI의 첫 번째 작업으로 돌아가요 — 테스트보다 먼저요. 유출된 키는 푸시되는 순간 히스토리에 남고, 나중에 지워도 그 사실은 되돌아오지 않으니까요.

안에 들어 있는 건 이래요.

  • 에이전트 9개 — 전략, 페르소나, 콘텐츠, 퍼포먼스 인텔리전스, 경쟁 인텔리전스, 캠페인 기획, 클라이언트 성공, 그리고 두 개 더. 각각은 베이스 에이전트의 서브클래스이고, 프롬프트 구조와 도구 레지스트리, 점진적 컨텍스트를 공유해요.
  • Postgres 스키마 2개. 개별 사업자 데이터는 한쪽에, 에이전시 데이터는 다른 쪽에 들어가고, Row Level Security(RLS)가 격리 경계 역할을 해요.
  • 로케일 10개. 로케일은 헤더를 통해 API로 전달돼서, 생성되는 메타데이터가 인터페이스 언어와 맞춰져요.
  • API 키가 필요 없는 데모 모드. 에이전트가 모델을 호출하는 대신 명확히 라벨이 붙은 정형 출력을 돌려주기 때문에, 프로바이더 계정 없이도 애플리케이션 전체를 눌러볼 수 있어요.

이걸 자기 버전으로 만들고 싶다면

이게 제가 가장 보고 싶은 쓰임새라서, 암시해두기보다 분명히 말해둘 만해요.

정말 원하는 게 자기만의 마케팅 에이전트 시스템 — 자기 에이전트, 자기 프롬프트, 자기 스키마, 그 위에 올릴 자기 제품 — 이라면, 저장소를 포크해서 만드세요. MIT 라이선스가 바로 그걸 위한 것이고, 꼼수가 아니라 의도된 사용이에요. 라이선스 파일을 남기는 것 말고는 출처 표시 의무도 없고, 저에게 확인할 필요도 없어요. 쓸모 있는 부분은 가져가고, 아닌 부분은 버리고, 동의하지 않는 건 바꾸세요.

저는 제가 혼자만 만져본 버전 하나보다, 서로 다른 버전 열두 개를 보고 싶어요.

v1을 혼자 갖고 있지 않고 공개한 이유

이미 손을 뗀 v1을 누가 원하겠냐고 생각하고 10개월이나 묵혀뒀어요. 그 생각은 틀렸고, 왜 틀렸는지가 저장소 자체보다 더 값어치 있어요.

두 번째 버전은 방향이 달라요. 지금 만들고 있는 건 이 코드베이스와 그렇게 닮지 않았고, 이 코드에 대한 diff가 될 것도 아니에요. v1을 비공개로 두면 아무도 찾지 않는 박물관 전시품이 됐을 거예요.

더 나은 이유는, 실제로 돌아가는 멀티테넌트 에이전트 애플리케이션이 아키텍처 다이어그램보다 훨씬 쓸모 있는 결과물이라는 점이에요. 제가 배우던 시절에 도움이 된 건 개념 설명이 아니었어요 — 진짜 프로젝트를 찾아서 다른 사람이 실제로 어떻게 짜놨는지 읽는 것이었죠. 설명 글에서 사라지는 추론이야말로 가장 중요한 추론이에요.

저장소의 아키텍처 노트에는 제가 틀렸고 다시는 같은 선택을 하지 않겠다고 적은 항목이 네 개 있어요. 그 네 개를 전부 그대로 남겼죠. 첫 번째는 보안 버그예요.

세상에 나가버린 실수

테이블 하나가 Row Level Security를 켜지 않은 채로 나갔어요.

public.notification_push_deliveries는 RLS를 켜는 한 줄 없이 생성됐고, 익명 역할과 인증된 역할에 TRUNCATE를 포함한 전체 권한이 부여됐으며, 정책은 하나도 정의되지 않았어요. 이 테이블은 Data API가 노출하는 스키마에 있고, 익명 키는 브라우저 번들 안에 함께 배포돼요. 그래서 그 기간 동안에는 그 키를 가진 사람이면 누구나 이 테이블을 읽거나 고칠 수 있었죠. 푸시 기기 식별자가 들어 있는 테이블이니까, 이건 이론상의 얘기가 아니라 데이터 노출 문제였어요.

그걸 발견한 건 보안 리뷰에서였어요. 버그 리포트도, 테스트도 아니었죠. 그동안 애플리케이션은 완벽하게 돌아가고 있었으니까요. 테이블에 RLS가 빠져 있어도 아무것도 에러를 던지지 않아요. 쿼리는 성공하고, 기능은 작동하고, 있어서는 안 될 권한이 그냥 거기 있어요 — 누군가 들여다보기 전까지는 눈에 띄는 일을 하지 않으면서요.

지금은 닫혀 있어요. 테이블에 RLS가 켜져 있고 정책은 없으며, 브라우저 역할의 권한은 회수됐어요. 한때 행을 돌려줬을 요청은 이제 권한 에러로 돌아와요. 여기서 일부러 과거형으로 쓰고 있어요. 이건 코드가 그때 어땠는지이지, 오늘 어때인지가 아니거든요.

이 부분은 정확히 짚고 싶어요. 이건 제가 올바르게 내린 설계 결정이 아니에요. 제가 잘못 만들고 나서 나중에 발견한 회귀(regression)예요.

그래서 제 기억을 믿지 않기로 했어요

그다음에 한 일만큼은 자신 있게 남에게 건넬 수 있는 부분이에요.

특정 테이블 이름을 하나도 대지 않는 테스트를 작성했어요. 스키마를 훑으면서 규칙을 검증하죠. 노출된 스키마의 모든 테이블에 Row Level Security가 켜져 있어야 하고, 테넌트 범위의 머티리얼라이즈드 뷰는 브라우저 역할로 읽을 수 없어야 한다는 규칙이요. 다음 달에 테이블을 추가하고 깜빡해도 테스트는 실패해요. 기억하고 있을 때 써둔 목록이 아니라, 제가 잊은 바로 그 부분에서 실패하죠.

솔직한 단서 두 가지를 먼저 밝힐게요. 둘 다 독자가 나중에 발견하기보다, 지금 저에게 들이대주셨으면 하는 것들이에요.

  • 그 검사에서 머티리얼라이즈드 뷰 쪽은 agency 스키마가 아니라 public 스키마만 다뤄요. 에이전시 쪽에는 제가 아직 막지 못한 노출이 따로 있어요.
  • 데이터베이스에 연결할 수 없으면 이 테스트는 스스로를 건너뛰어요. 건너뛴 테스트는 초록색이죠. 즉, 망가진 환경이 깨진 불변식을 숨길 수 있다는 뜻이에요.

이 일련의 경험에서 습관으로 하나만 남았다면, 이거예요. 이런 모양의 버그를 찾았을 때는, 그걸 잡아냈을 테스트를 써요 — 그리고 객체가 아니라 규칙에 대고 쓰죠. 제가 기억한 세 개의 객체를 이름으로 나열한 테스트는 그 세 개만 지켜줘요. 규칙을 검증하는 테스트는 다음 주에 제가 추가하고 깜빡할 하나를 지켜주죠.

두 번째 함정

두 번째는 설계가 아니라 운으로 맞힌 것인데, 벤더 미팅에서 자주 듣는 이야기이기도 해요.

클라이언트 측 필터는 경계가 아니에요. 애플리케이션이 브라우저에서 조직별로 행을 거른다면 — .eq('org_id', ...) 같은 것들이요 — 그 격리는 사용자 기기에서 돌아간다는 뜻이고, 개발자 도구로 걷어낼 수 있어요. 걷어낼 수 있는 건 표시 설정이지 보안 제어가 아니에요. 행 가시성은 데이터베이스에서, 또는 호출자가 우회할 수 없는 서버 엔드포인트 뒤에서 강제돼야 해요.

머티리얼라이즈드 뷰는 이 문제의 골치 아픈 친척이에요. 머티리얼라이즈드 뷰에는 Row Level Security를 아예 걸 수 없어요. 머티리얼라이즈드 뷰에 SELECT 권한을 주면 모든 테넌트의 행이 반환되는데, 마이그레이션에서는 테이블에 같은 권한을 준 것과 똑같이 보여요. 테이블이라면 정책이 여전히 제약을 걸 텐데도요. 저장소가 테넌트 범위로 머티리얼라이즈되는 모든 것에서 브라우저 역할 권한을 회수하는 이유가 바로 그거예요.

아직 끝내지 못한 것

Row Level Security는 TRUNCATE를 제한할 수 없어요. 이건 행 수준 권한이 아니라 테이블 수준 권한이라서 정책이 적용되지 않거든요. 저장소의 기준 권한 부여는 수많은 테이블에 대해 브라우저 역할에 ALL을 주고, 여기에는 TRUNCATE가 포함돼요. 그걸 나중에 좁히는 것은 아무것도 없어요. 머티리얼라이즈드 뷰 권한은 회수했지만, 이것들은 회수하지 않았어요. 즉, 이 섹션에서 계속 설명해온 경계 바깥에 브라우저 역할이 권한을 쥐고 있는 테이블이 있다는 뜻이에요.

실제로는 열린 문이라기보다 잠재된 상태예요. Data API에는 TRUNCATE 동사가 없고, 브라우저 역할은 데이터베이스에 직접 접속할 수 없고, 일반적인 배포에서는 데이터베이스 포트를 열어두지 않아요. 위생 문제예요. 다만 모양은 이 글 맨 앞의 버그와 같아요 — 정당성을 조용히 살아남은 권한이죠 — 그리고 독자가 발견해서 제가 알고 있었는지 의아해하기보다는 제가 먼저 짚는 편이 낫다고 생각해요. 필요한 건 두 스키마에 걸친 회수와, 브라우저 역할이 RLS를 우회하는 권한을 쥐고 있지 않다는 걸 검증하는 테스트예요.

다시는 같은 방식으로 하지 않을 것

스키마 두 개를 나란히 두니 DDL이 많이 중복됐어요. 에이전시 데이터와 개인 사업자 데이터가 테넌트 판별 컬럼을 가진 테이블 하나가 아니라, 나란한 구조를 갖게 됐죠. 분리 자체는 확실히 더 깔끔해요. 하지만 중복은 유지보수 비용으로 판별 컬럼보다 더 비쌌고, 다음엔 반대쪽을 선택할 거예요.

수동 함수 호출은 코드가 정말 많아져요. 에이전트 루프가 프로바이더의 자동 함수 호출을 쓰지 않고 도구 호출을 직접 처리하는데, 덕분에 스트리밍과 도구 실행이 애플리케이션 통제 아래에 있죠. 대가는 애플리케이션이 함수 결과 파트를 직접 조립해야 한다는 것이고, 현재 모델에서는 그 파트에 함수 이름뿐 아니라 call id도 들어가야 해요. id를 빼면 스키마 에러가 나지 않아요. 모델이 변덕을 부리는 것처럼 보이는 무언가가 돌아오죠. 스키마 에러보다 훨씬 나쁜 오후예요. 지금은 도구를 쓰는 스트리밍을 더 상위 API로 할 수 있다면, 그 트레이드오프는 다시 볼 만해요.

마이그레이션 체인이 321개 파일까지 갔어요. 그중 상당수가 fix_, _v2, remove_라는 이름이었죠. 이미 쓴 것을 고치는 대신 수정 사항을 뒤에 계속 덧붙였으니까요. 스키마의 진짜 상태는 처음부터 히스토리를 재생해야만 알 수 있었어요. 그때 쓴 글들은 코드가 받을 만한 것보다 그 시기를 더 자신 있게 말했어요 — 2025년 11월에는 마이그레이션 33개로 멀티테넌시가 "마침내 해결됐다"고 썼고, 그 뒤로도 몇 달 동안 수정 마이그레이션을 계속 썼죠.

프런트엔드는 API의 형태를 검증하지 않고 그대로 믿어요. 들어오는 쪽은 검증이 꼼꼼해서 백엔드가 모든 요청을 Pydantic으로 파싱하지만, 나가는 쪽에는 아무 검증이 없어요. 브라우저는 응답을 받아서 그대로 믿죠. 공유 스키마가 있었다면 필드 형태가 바뀔 때 생기는 어긋남을 잡아냈을 텐데, 그냥 빈 화면으로 발견하게 내버려 둔 거예요. 위의 세 가지와 합치면, 아키텍처 노트에 '다르게 하겠다'고 적어둔 네 가지가 돼요.

공개한 저장소에서는 마이그레이션 체인을 20개의 계층화된 마이그레이션으로, 관심사별로 다시 묶었어요 — 테이블, 그다음 도메인별로 묶은 함수, 뷰, 인덱스, 트리거, 정책, 권한, 스케줄 작업, 마지막으로 하드닝 패스까지요. 정확히 그렇다기보다 대체로 그렇다고 하는 편이 맞고, 어디서 어긋나는지는 솔직히 적어두는 게 낫겠죠. 스무 개 중 하나는 분류되지 않은 함수를 담는, 사실상의 잡동사니 파일이라고 인정하고 있고, 테이블 층은 파일 이름이 암시하는 대로 나뉘어 있지 않아요. 공유 스키마 이름을 단 파일이 에이전시 테이블 여덟 개까지 만들고, 에이전시 스키마 이름을 단 파일에는 테이블 정의가 하나도 들어 있지 않아요. 계층화는 실제고, 라벨은 완벽하지 않아요.

이 분할이 제대로 해내는 건, 읽는 데 중요한 부분이에요. 스키마는 순수한 재구성이고, 전후로 덤프해서 덤프 도구의 랜덤 토큰만 빼면 두 개가 바이트 단위로 동일하다는 걸 확인했어요.

그 검증이 있었기 때문에 손댈 마음이 생겼어요.

살아남은 것

켜고 끄는 기능이 아니라, 실제 경계로서의 Row Level Security. 설계를 그걸 중심으로 짜면, 격리는 체크리스트 항목이 아니라 시스템의 속성이 돼요.

쓰기는 라우팅된 데이터베이스 함수를 거쳐요. 애플리케이션 코드가 어떤 스키마를 건드릴지 고르지 않아요. 조직 유형을 보고 분기하는 함수를 호출할 뿐이고, 그래서 선택이 한 곳에 모여 있어서 새로운 코드 경로가 그 선택을 빼먹을 수 없죠.

가입은 클라이언트 입력을 무시해요. 프로비저닝 트리거는 클라이언트가 넘긴 조직 id나 역할을 받아들이지 않아요. 그 데이터는 사용자가 조작할 수 있으니까요. 새 조직과 기본 소유자 역할을 새로 만들어요. 사소한 부분이지만 틀리기 쉽고, 틀리면 비싸요.

지연된 클라이언트 생성. 서비스들은 임포트 시점이 아니라 처음 쓸 때 프로바이더 클라이언트를 만들어요. 스타일 취향처럼 들리지만 아니에요. 여러 서비스가 모듈 임포트 시점에 생성되는데, 즉시 생성 방식은 애플리케이션을 임포트하는 것만으로 API 키가 필요하다는 뜻이었고, 뭔가 시작되기도 전에 프로바이더 SDK에서 나오는 불투명한 에러로 드러났죠. 이걸 지연시키니까 데모 모드가 가능해졌고, 그래서 처음 보는 사람도 비용 없이 프로젝트를 평가할 수 있어요.

마지막 항목은 제가 가장 만족하는 결정이에요. 그런데 그게 중요해진 이유 때문에 한 선택은 아니었어요. 크래시를 멈추려고 한 거였죠.

코드를 읽을 일이 없다면

예전에 에이전시 쪽에서 이런 소프트웨어를 사던 시절의 제가 원했을 섹션이에요. 그래서 코드는 하나도 없어요.

가져갈 만한 건 **"계정별로 필터링합니다"**와 **"데이터베이스가 다른 계정의 행을 반환할 수 없습니다"**의 차이예요.

커리어의 대부분을 플랫폼을 사는 쪽에서 보냈고, 최근 몇 년은 만드는 쪽에 있어요. 그 차이는 제가 잘못된 버전을 세상에 내보내고 나서야 이해했죠. 하나는 브라우저가 따르는 규칙이고, 다른 하나는 브라우저가 깨뜨릴 수 없는 규칙이에요. 대부분의 도구는 전자를 가지고 있으면서 후자의 언어로 설명해요.

여러 클라이언트의 데이터 — 경쟁 인텔리전스, 퍼포먼스 데이터, 오디언스 정의, 뭐든 간에 — 를 담을 플랫폼을 평가할 때, 물어야 할 질문은 "안전한가요"가 아니에요. 그건 누구나 그렇다고 답하죠. 질문은 이거예요. 그 분리는 어디서 강제되고 있고, 개발자가 필터를 걷어내면 무슨 일이 일어나는가?

좋은 답은 두 가지예요. 로그인한 사용자의 신원에 묶인 정책으로 데이터베이스에서 강제되거나, 브라우저가 우회할 수 없는 서버 엔드포인트 뒤에서 강제되거나. 브라우저가 끼는 답은 전부 아니에요.

좋은 답은 이렇게 들려요 — 정책이 테이블에 있고 사용자 세션에 묶여 있다, 브라우저는 그 테이블을 직접 조회하지 않는다, 이게 그걸 증명하는 테스트다. 덜 쓸모 있는 답은 이렇게 들려요 — 우리 애플리케이션은 계정별로 필터링한다, 데이터는 암호화돼 있다, 우리는 SOC 2를 준수한다. 전부 사실일 수 있지만, 어느 것도 질문에 답하지 않아요.

한 줄이면 되고, 벤더 보안 리뷰에 딱 들어맞아서 저라면 거기에 넣어요. 답을 들으면 멀티테넌시가 설계에 처음부터 들어 있었는지 나중에 덧붙였는지 알 수 있어요.

자주 묻는 질문

비공개 저장소에 두지 않고 왜 공개했나요?

공개된 결과물은 검증할 수 있고, 비공개된 것은 그럴 수 없으니까요. 예전에 이걸 만드는 과정에 대해 쓴 글들은 주장을 담고 있었어요. 마이그레이션과 정책, 테스트가 들어 있는 저장소는 독자가 직접 확인할 수 있는 것이고, 제가 틀린 부분까지도요. 아키텍처 노트에는 "트레이드오프, 그리고 다르게 하겠다고 결심한 것들"이라는 섹션이 있는데, 이 저장소가 이런 형태로 존재하는 이유가 바로 그거예요.

두 번째 버전도 오픈소스인가요?

아니요. 비공개로 개발하고 있고, 이 코드베이스와 비슷해질 거라고 보지 않아요. 애매하게 남겨두고 사람들이 로드맵을 기대하며 클론하게 만드는 것보다, 그냥 분명히 말하는 편이 나아요.

프로덕션에서 써도 되나요?

저라면 쓰지 않아요. 이건 레퍼런스지 제품이 아니에요. 시드 데이터의 데모 자격 증명은 로컬용이고, 지원 약속도 없고, 앞으로 의존성이 바뀌어도 고쳐줄 사람이 없어요. 읽고 빌려 쓰기에는 좋은 것이고, 그 위에서 사업을 돌리기에는 나쁜 것이에요.

써보려면 AI 키가 필요한가요?

아니요. 데모 모드로 시작하고, 에이전트는 모델을 호출하는 대신 명확히 라벨이 붙은 정형 출력을 돌려줘요. 키 없이, 돈 한 푼 쓰지 않고 애플리케이션 전체를 눌러볼 수 있어요 — 모든 에이전트, 에이전시 클라이언트 흐름, 언어 전환까지요. 실제 모델 호출로 바꾸는 건 설정 하나와 키 하나면 돼요. 제 첫 실행은 10분 넘게 걸렸어요. Docker가 돌아가고 있어야 하고, Node, Python, Poetry, Supabase CLI가 필요하고, 느린 부분은 큰 다운로드예요.


이걸 만들면서 만드는 이야기를 많이 썼는데, 시작점으로 추천할 두 편은 2일째에 왜 멀티테넌시를 만들었는지67일째에 다시 만들었을 때 무슨 일이 있었는지예요. 둘 중 하나에만 시간을 쓸 가치가 있다면, 그건 두 번째예요 — 아키텍처가 틀렸다는 게 드러난 글이 그쪽이거든요.

코드는 github.com/chandlernguyen/stratum-oss에 있고, 제가 저지른 실수를 지키는 테스트는 tests/automated/test_rls_coverage.py에 있어요.

멀티테넌트 시스템을 만들어 배포해보고, 제가 언급하지 않은 세 번째 조용한 함정을 발견하셨다면 정말 듣고 싶어요 — 그런 것들이야말로 모을 가치가 있는 것들이거든요.

피드백과 제안, 그리고 v1의 앞으로

이걸 일방적인 방송으로 두고 싶지는 않아서, 무엇을 기대하면 되는지 솔직한 버전을 적어둘게요.

환영하는 것: 저장소 어딘가가 그냥 틀렸을 때의 버그 리포트. 더 명확하게, 더 단순하게, 더 적은 코드로 할 수 있는 부분에 대한 제안. 직접 돌려보다가 README에 없는 것에 부딪힌 사람의 메모. 진짜 문제를 찾아서 고치고 싶은 사람의 풀 리퀘스트. 그리고 포크해서 자기만의 무언가를 만들었다면, 무엇을 왜 바꿨는지 알고 싶어요 — 그게 가장 흥미로운 피드백이에요. 결정을 실제로 직접 내려야 했으니까요.

약속할 수 있는 것: 별로 없어요. 아닌 척하기보다 그렇게 말하는 편이 낫죠. 이건 활발하게 개발하는 프로젝트가 아니고, 지원 데스크를 운영하는 것도 아니고, 응답 시간을 약속할 수도 없어요. 어떤 제안은 실행에 옮기고, 어떤 제안은 읽고 동의하면서도 결국 손이 미치지 못해요. 이미 후속이 있는 사이드 프로젝트의 현실적인 모습이 그래요.

v1은 어떻게 되나: 있는 그대로 공개된 상태로 남아요. 더 이상 개발하지 않으니 새 릴리스를 기대하고 계획하지는 마세요. 그렇다고 봉인한 척하지는 않아요 — 코드는 공개돼 있고, 라이선스는 원하는 방향으로 가져가도 된다고 허락하고 있고, 뭔가 깨져 있거나 정말 불명확하다면 원칙론 때문에 그대로 둘 이유가 제겐 없어요.

저에게 닿는 가장 간단한 방법은 저장소에 이슈를 남기는 것이고, 공개적으로 나서고 싶지 않다면 이메일도 괜찮아요.

오늘은 여기까지예요.

감사합니다, Chandler