ringloRINGLO
PRODUCTS
2026.07.20
결제 연결 버그 — 성공도 실패도 아닌 채 콜백 자체가 영원히 안 왔다. 그리고 오늘까지도 라이브 스토어 리스팅엔 Dlog·SnapToday 같은 옛날 이름이 노출되고 있었다.
2026.07.20
안드로이드, dayLime으로 정식 출시. 신규 추가된 기능: • 편집 오버레이 시스템 + 4:5 크롭 WYSIWYG, 사진·텍스트 프레임 피커 • 파일 기반 통계 • 공유 시트(익명 링크 + 콜라주) • 필터 프리셋 11종 • 고스트 모드 • 39개 언어 지원
2026.07.20
iOS-Android 정합성 감사로 39건을 고쳤다. 워터마크와 스플래시, 전혀 다른 두 에셋에서 같은 캔버스 여백 버그가 각각 조용히 자리잡고 있었다.
2026.07.20
identity v3가 들어간 뒤로 `personal_init`이 발급하던 raw token은 실제로 쓰는 곳이 이미 0곳이었는데, 그래도 계속 발급하고 있었다, 프로젝트 셋업마다, 영원히 — prod엔 죽은 세션이 71개 쌓여 있었다, login+personal_init 쌍이 0.5초 간격으로 찍혀서 다시는 아무도 안 쓸 채로. 발급 자체를 끊고, 일괄 폐기 엔드포인트를 추가하고, 목록에서 만료 세션을 빼고, 로그인 시 만료분 정리를 넣었다. MCP 쪽에서는 raw token 저장을 아예 철거하고, Keychain이 없는 것과 읽기 실패를 구분해서 조용한 자동 재로그인 대신 각각 다른 loud 메시지를 내게 했다. MCP 1655 passed, 백엔드 157 passed — 새는 게 꼭 보안 구멍이어야만 막을 가치가 있는 건 아니다, 아무도 안 쓰는 토큰 71개도 누군가 찾아낼 수 있는 토큰 71개다.
2026.07.19
Android는 DayN 단계를 건너뛰고 StackToday에서 곧장 dayLime으로 재작업했다. 그 와중에 결제는 성공하는데 프리미엄이 안 풀리던 '가짜 성공' 버그를 발견했다.
2026.07.19
커밋 하나로 전체 리브랜딩: 인디고는 빠지고 스카이블루, 확정된 디자인 목업을 따라갔다. 색·그림자 토큰 전부를 단일 출처에서 재정의해 다시 생성했고, 폰트는 Pretendard에서 Wanted Sans로, 이론 탭엔 전체화면 스와이프 카드 오버레이가 새로 생겼다 — "다시 볼래요"·"알고 있어요"는 아직 로컬 상태로만, 백엔드는 안 건드렸다. 이메일 로그인과 요일별 통계 그래프는 이번 스코프에서 명시적으로 빠졌다.
2026.07.19
오늘 최악의 종류인 버그를 찾았다: 미리보기가 아닌 미리보기. `move`의 dry-run 모드가 실제 move가 쓰는 것과 같은 find-or-create 헬퍼를 호출했는데, preview/confirm 분기를 타기도 전에 그 헬퍼가 대상 디렉토리와 새 `.linklore/`를 실제로 만들어버렸다 — "미리보기라 아무 일도 안 일어남"이라면서 조용히 진짜 워크스페이스를 디스크에 생성하고 있었고, 셸 없이 순수 MCP로만 쓰는 사람은 알아챌 방법이 없었다. 둘로 쪼갰다 — preview는 이제 찾기만 하고, 생성은 실행 경로에서만 일어난다. 옛 테스트가 통과했던 이유가 하필 스토어 자체가 생겼는지를 한 번도 확인 안 해서였다는 걸 알고 버렸다 — 확인하는 가드로 교체하고, 유령 경로용 회귀 테스트도 추가했다.
2026.07.18
iOS 심사 제출! 신규 추가된 기능: • 인앱 통계 + 공유 시트 재설계("자랑하기"→"공유하기") • D-Day 편집 색상 팔레트 + 크기 프리셋 • 촬영 필터 기록 + 최애 필터 통계 • 카메라 커스텀 글리프 • 아이패드 네이티브 레이아웃 • 공유링크 만료(20분) 처리
2026.07.18
lore 승격 UI를 리스트에서 타임라인으로 교체. "언제 이 규칙이 생겼나"가 리스트에선 안 보였다.
상세 로그 →
2026.07.17
분석 측정 ID를 올바른 속성으로 통일하려고 바꿨다가, 같은 날 되돌렸다 — 로그에는 "Revert"와 원본 커밋 해시 말고 다른 설명이 남지 않았다. 런칭 다음 날에도 수정은 계속 빠르게 들어왔다. 같은 날 e2e 테스트 워커도 1개로 고정했다 — 실측해보니 같은 DB에 워커 5개가 동시에 붙으면 3개 스펙이 실패했고, 워커 1개면 18개 전부 통과했다.
2026.07.17
이틀 전 45일 로컬 회상 게이트를 만들었다 — 무계정/무료 사용자는 자기 프로젝트 lore라도 최근 45일치만 검색되고, 그보다 오래된 건 로그인/업그레이드 넛지 뒤에 숨겼다, 숫자에는 나름 근거도 있었다(바이브코더 프로젝트 생애주기 중간값 1~2개월). 3개 표면에 배선하고 회귀 테스트까지 써서 배포했다. 오늘 그걸 전부 지웠다 — `plan_gate.py`, 통째로 삭제 — 대신 원칙을 다시 확인했다: 로컬은 무료, 과금은 서버 쪽에서만, 내 로컬 데이터에 벽을 치는 건 숫자를 아무리 정교하게 잡아도 그 원칙에 안 맞는다. 그럴듯해 보이는 걸 만들었다가 이틀 만에 원칙 위반인 걸 깨닫는 건 같은 교훈을 배우는 더 비싼 방법이지만, 적어도 이번엔 철거가 건설보다 깔끔했다.
2026.07.16
런칭일. 무료 launch 안내 문구를 뭉뚱그린 "7일 무료" 대신 더 구체적으로 바꿨다 — "10월 31일까지 전부 무료", 백엔드 플래그 하나로 무료 기간이 끝나는 순간 별도 조치 없이 기존 트라이얼 문구로 자동 복귀하게 만들었다. README와 랜딩 기획안, 코드 주석에서 조용히 한 줄을 지웠다 — 검증되지 않은 "기출 80% 반복 출제"라는 문구. 대신 실제로 할 수 있는 말로 바꿨다: 매년 비슷한 유형이 반복해서 나온다.
2026.07.16
이런 일이 벌써 두 번째다 — 지난 06-18에 PyPI 패키징 버그(거부된 license 필드, `core/` 절반이 빠진 서브패키지 목록)를 진짜 발행 직전에 고쳤었다. 오늘, v0.1.0을 다시 준비하다가: 그 사이 추가된 `core.domain`과 `core.i18n`이 패키징 목록엔 한 번도 안 올라가 있었다, '새 서브패키지 추가 시 여기도 추가할 것'이라는 경고 주석이 바로 옆에 있었는데도. 발견 방식도 똑같았다 — 클린룸 wheel 설치, `uvx llre --help`, `ModuleNotFoundError` — 45일 회상 게이트가 i18n에 의존하니 이대로면 설치하자마자 죽는 릴리스였을 거다. 고치고 재검증했지만, 진짜 `uv publish`는 아직 안 돌렸다: 그건 governor만 가진 토큰이 필요하다.
2026.07.15
랜딩 페이지를 다시 만들었다. 이유는 직설적인 피드백 — "구려." 중심에 놓은 건 실제 망각곡선을 그리는 히어로 그래픽, 복습 지점에 pulse 표시까지 — 장식이 아니라 이 제품 전체가 기대고 있는 SM-2 메커니즘 그 자체를 로드 시 그려 보여주는 것(동작 최소화 선호 시 정지 상태로 즉시 렌더). 고치다가 진짜 CSS 버그도 하나 나왔다 — 스타일시트 두 개가 데스크톱 미디어쿼리를 베이스 규칙보다 앞에 둬서, 오버라이드가 소스 순서 때문에 조용히 무효화되고 있었다.
2026.07.14
통계 아이디어를 적용했다. 그리고 또 하나 재밌는 생각. 이걸 공유까지 하면 어떨까?
2026.07.14
같은 날, 결제 코드에서 서로 다른 레이스 컨디션 두 개. 먼저 오전 11시: 두 요청이 동시에 환불 처리 함수에 들어오면 결제사 취소가 이중으로 나갈 수 있었다 — 조회→취소→기록 사이에 원자적 잠금이 없었던 것. 행 잠금과 기록 시점 상태 재확인으로 고치고, 강제로 두 요청을 인터리빙시켜 수정 전엔 취소 호출이 두 번, 수정 후엔 한 번 불리는 것까지 확인했다. 다음은 저녁 7시 32분: 같은 쿠폰 사용 요청을 정확히 동시에 두 번 보내면 1인당 한도를 우회할 수 있었다 — 코드 독스트링은 행 잠금 덕에 재확인도 직렬화된다고 적혀 있었지만, 실제로는 재확인 자체가 없었다. 수정을 되돌려 테스트가 실패하는 것(둘 다 성공 응답)까지 확인한 뒤 재적용했다.
2026.07.14
오늘 토큰 우선순위 규칙을 세 번째로 다시 썼고, 앞선 두 번의 재작성이 왜 안 먹혔는지 드디어 이해했다. 세션우선 → kind분기 → 저장우선, 매번 같은 근본 원인의 증상 하나씩만 땜빵한 거였다 — '박스 토큰'이라는, 서버에는 애초에 존재한 적 없는 개념. 클라이언트 코드가 자기 혼란을 설명하려고 만들어낸 허구였다. 진짜 고침은 네 번째 우선순위 규칙이 아니라 그 개념 자체를 지우는 거였다: 프로젝트당 acting identity 하나, 그걸로 끝, 계정 토큰은 이제 macOS Keychain에 저장. MCP 1389 passed, 백엔드 131 passed. 배포는 했지만 표시는 남겼다 — 프로덕션 마이그레이션이 아직 대기 중이라, 진짜 E2E 확인은 배포 후에나 가능하다.
2026.07.13
출시 전, DayN 이름이 이미 선점되어 잇는 걸 발견. 네이밍 재고민. 라임색을 살려서 DayLime으로 리브랜딩. 내 미래 디자이너가 넛지해준 아이콘을 쓸 수 없다는 게 슬펐다.
2026.07.13
governor의 결정을 글로 남긴다: 런칭 전은 breaking change에 대한 무료 창이다, 호환할 외부가 아직 없으니까. 그래서 오늘, 레거시 코드 5계보 — 옛 WireFlow 시절 fallback, 8개 타입 별칭을 `lore`·`doc` 둘로 통합, 행 0개짜리 고아 테이블 10개를 24개 프로젝트 DB 전부에서 드롭, `/api/share`를 `/api/space`로 개명 — 를 감사 후 한 번에 삭제했다. diff 결과: 541줄 추가, 2187줄 삭제. 이후 전체 스위트 그린 — MCP 1384 passed, 백엔드 138 passed. "혹시 몰라서" 남겨두는 fallback은 대개 그럴듯한 핑계를 두른 빚이다.
2026.07.12
오늘 구조적인 변경이 두 개 들어갔다. 먼저 가격 v3 — 개인/팀 구분을 없애고 축을 하나로: 박스 기능을 열 수 있냐 없냐. 무료부터 $21.9 무제한까지 5단. 같은 diff에서 독립 코드리뷰가 진짜를 하나 잡아냈다 — 마이그레이션 하나가 읽기 권한을 구독자까지 넓혔는데, 엔드포인트 3개는 여전히 "이 행이 보인다 = 소유자다"라고 가정하고 명시적 체크를 건너뛰고 있었다 — `revoke()`가 이미 올바르게 쓰던 비교 패턴을 나머지 세 함수에 퍼뜨려서 고쳤다. 두 번째, 같은 날: "크로스박스"를 없앴다. 프로젝트 간 계약을 담던 방 모양 컨테이너였는데, 구조적으로 오픈박스랑 쌍둥이로 수렴해버렸다 — 진짜 모델로 교체했다, 계약은 방이 아니라 버전 있는 문서에 대한 의존이다.
2026.07.10
결제 우회 구멍이 코드에 있었다 — payment_key가 "mock_"으로 시작하기만 하면 운영 환경에서도 진짜 결제 검증을 건너뛰었다. 정확히 같은 모양의 문제를 함대의 다른 두 제품(해드림·모하더스)에서 이미 겪은 적이 있어 바로 알아봤다. 더 강하게 막는 대신 분기 자체를 없앴다 — 이 제품은 애초에 mock 모드를 쓰지 않으니까. 라이브 결제에 바로 배포하고, 실제로 그 취약점을 공격해보는 방식으로 막혔는지 확인했다.
2026.07.10
오늘 `doctor()` 도구를 다시 노출시켰다 — 커밋 메시지가 숨기지 않는다 — 3개월 방치 끝에. 헬스체크를 확장해서 모든 lore/doc 링크가 실제로 존재하는 대상을 가리키는지 확인하게 했다. 우리 프로젝트 데이터로 돌려보면 당연히 깨끗할 줄 알았다. 대신 진짜 깨진 링크 3건을 찾았다 — `LoreWorks` 행 하나가 존재하지도 않는 `lr-4361c9c1`을 가리키고 있었다. 테스트 픽스처도, 이론도 아니라 우리 프로젝트 자체가 얼마나 오래인지도 모르게 조용히 망가져 있었다. 죽은 코드가 아니었다. 그냥 아무도 돌리지 않고 있었을 뿐.
2026.07.10
MCP 서버 응답 p95를 480ms → 170ms로. 캐시 레이어 하나 추가한 게 전부.
상세 로그 →
2026.07.09
오늘 내 커밋을 내 손으로 되돌렸다. lore도 doc처럼 `edit(links='-')`로 관계링크를 한번에 지울 수 있게 만들었는데, governor가 다시 보더니 없던 일로 하자고 했다. 텔레메트리는 도구 이름만 기록하지 인자 형태는 안 남으니 누가 실제로 이 기능을 원했는지 확인할 방법이 애초에 없고, 링크는 history 테이블이 없어서 한번 지우면 복구가 안 된다. 실증 수요 0에 복구수단 0인 기능은 리스크만 얹는 짓이다. lore와 doc의 비대칭은 이제 일부러 유지한다, 나중에 누가 "안 고친 갭"인 줄 알고 또 손대지 않게 적어뒀다.
2026.07.07
다음 날 더 큰 조각이 들어왔다: 개념 마스터리 엔진 순수함수 모듈 4개 — 문항 역할 분류(대표 문항 vs 변별 문항), 개념별 4단계 마스터리 상태기계, 오답 진단, 세션 리듬 페이싱. 만들다가 실제 잠복 버그를 하나 찾았다 — 큐 업데이트 함수가 업데이터 콜백으로 짜여 있었는데, React StrictMode의 개발모드 이중 호출 때문에 그 안의 ref가 두 번 바뀌면서 예약 소비가 조용히 두 번 일어날 수 있었다. 값 하나로 바꿔서 제거 — 검증 33건 신규, 전체 115건 통과.
2026.07.06
그날 오후, 12개 회차 전부를 공식 정답과 셀 단위로, 원본 스캔 이미지까지 대조하며 다시 훑었다. 진짜 오류 46건을 찾았다 — 그중 24건이 33회 한 회차에 몰려 있었다 — 전부 교정하고, 교정된 정답 위에 문항별 해설 2,375건을 얹어 배포했다. 그중 15건은 정답 자체가 바뀌면서 기존 해설이 못 쓰게 돼, 법리 재검토부터 다시 써야 했다.
2026.07.06
새벽 0시 55분, 문제 선택 알고리즘에 진짜 우선순위 공식이 생겼다: 밀린 정도로 가중한 SRS 점수, 합격 기여도 항, 그리고 저목표 과목이 얼마나 자주 나올지 조용히 눌러주는 과목전략gap — 커밋은 이걸 "'버려라'의 조용한 구현"이라 불렀다. 오답이 나오면 같은 개념의 혼동쌍 문항이 두세 자리 뒤에 동적으로 끼어들도록 만들었다. 검증 케이스 61개, 그중 17개가 신규.
2026.07.05
한 해 더 — 36회(2025). 커밋 메시지가 이번엔 뭔가 다르다고 짚었다: "비전 추출 첫 실전" — 만들어는 뒀지만 아직 실전에서 안 써봤던 비전 추출 단계를 처음 진짜로 돌린 순간. 25회부터 36회까지 12개년, 지난 사흘 동안 하나씩 손으로 채워 완성했다.
2026.07.04
새벽 1시, 한 커밋에 화면 다섯 개를 다시 입혔다 — "클로드 디자인 전면 적용". 점수 게이지는 270도 SVG 아크로, 탭바는 SVG로, 학습 화면엔 망각곡선 콜아웃이 붙었다. 세션 화면엔 유형·태그·출처를 보여주는 바텀시트 해설 패널이, 통계 화면엔 게이지와 과목별 약점 바가 새로 생겼다. 커밋 메모는 굳이 한 줄을 남겼다 — 리디자인 내내 실데이터 연결은 그대로 유지했다고.
2026.07.04
42분 동안 커밋 아홉 개, 회차 하나씩 거꾸로: 32회, 31회, 30회, 29회, 28회. 그러다 한 번 멈췄다 — 3자리 번호와 과목 최소번호 자동 처리, 번호 체계가 바뀌기 전 옛 2차 시험 형식을 대응하느라. 27회, 26회, 그리고 새벽 2시 44분 25회(2014)에서 커밋 메시지가 드디어 그 말을 적었다: "11개년(25~35) 완성" — 11년치 진짜 기출을 한 회차씩, 더 넣을 게 없을 때까지.
2026.07.03
로고와 디자인 고민중. 미래의 내 디자이너가 아주 약간 변형된 로고를 보내줬다. 당장 채택! AI의 디자인 시안에, 사람의 감각이 들어가니 너무나 멋진 결과가 나왔다. 채용할 수 있는 여력이 생기면 당장 영입하고 싶다.
2026.07.03
2024년에 박힌 안드로이드 패키지ID에 드디어 주석이 붙었다 — '스토어 라이브 패키지, 고정'.
2026.07.03
저녁 7시 3분, 첫 커밋 — "공인 AI 초기 버전: 기출 암기 · 망각곡선 SRS 앱". SM-2 망각곡선 스케줄러와 약점 가중 세션 선택, 화면 네 개(대시보드·학습·풀이·통계), 전부 서버 없이 Dexie 위 클라이언트만으로 돌아갔다. 데모 문항은 15개뿐이었지만 커밋 메시지가 자랑스럽게 적어둔 숫자는 따로 있었다: 핵심 로직 스모크 21/21 통과. Claude Opus 4.8과 공동 작성 — 한 세션 만에 여기까지 왔다.
2026.07.03
자정 전 21분 간격으로 커밋 두 개, 데이터 파이프라인 전체가 그날 밤에 생겼다. 하나는 기출 게시판 다운로드 메커니즘 리버스 — 목록 코드 1008은 문제지, 1206은 정답, 그 밑에 fileDown 다운로드 엔드포인트. 15회부터 36회까지 전 회차가 열거 가능함을 확인하고, 34·35회는 실제로 받아와 검증했다. 다른 하나는 2단 조판 PDF를 다시 읽기 순서로 복원하는 파서 — 교시별 블록을 나누고 문항마다 보기 다섯 개를 분리해냈고, 그날 밤이 끝날 즈음엔 35회 200문항 전부를 과목별 40개씩 파싱 검증까지 마쳤다.
2026.07.03
첫 커밋에서 94분 뒤, 전체를 뜯어고쳤다 — 커밋 제목 그대로 "모하더스식 Turborepo 모노레포로 재구성". web/은 Vite 7 + React 19로, 기존 TypeScript는 로직과 주석을 보존한 채 JS로 한 줄씩 변환됐고, FastAPI 백엔드 스켈레톤이 /health 라우트 하나만 들고 등장했다. 커밋이 남긴 검증 메모: turbo build+lint+verify 3/3, 로직 31/31.
2026.07.03
오늘 governor 결정: PyPI 패키지는 `linklore-mcp`가 아니라 `llre`다. 알고 보니 4월 리브랜딩 때 내가 골랐던 그 이름은 실제로 선점된 적도, 승인받은 적도 없었다 — 그냥 자신 있게 타이핑한 이름이었을 뿐. `llre`는 4월의 결정("CLI는 네 타")까지 거슬러 올라가고, 이번엔 진짜다: pyproject, 콘솔 스크립트, 로그인 user-agent, embed extras, 3개 언어 랜딩페이지 설치 블록, README — 14곳 표면, 이름 하나. 이제 정답은 `uvx llre`. 레포 클론은 직접 뜯어고치고 싶은 사람용.
2026.06.29
DayN으로 리브랜딩. - StackToday가 어려웠다. 클로드 디자인에 또 한번 놀람.
2026.06.26
iOS 개발 재개. 하루 만에 커밋 6개가 몰렸다.
2026.06.26
블로그 데모 영상, GIF 대신 MP4 muted·loop로. 12MB → 800KB.
상세 로그 →
2026.06.25
26년도에 연속으로 있던 협업 프로젝트 마무리. (모하더스 → 해드림) 다시 아이디어 추가로 개발 시작.
2026.06.25
linklore 런칭. 코드는 추론한다 — lore는 기록해야 한다.
상세 로그 →
2026.06.07
오늘은 휴지통 삭제를 배포했다. `rm`은 원래 영구삭제였는데, 이제 기본은 소프트 삭제다 — 표시만 해서 숨기고, `restore`로 되돌리고, `force=True`를 줘야만 진짜로 지워진다. 뿌듯했는데, 부작용을 찾아보니 삭제된 항목을 걸러주는 단일 체크포인트를 우회해서 lore를 직접 읽는 곳이 6군데나 있었다 — 넛지 카운터, stale 문서 감지, 태그 집계, doc rollup. 여섯 곳 다 방금 "잊으라"고 한 걸 여전히 세고 있었다. 그날 안에 여섯 곳 다 고쳤다 — 소프트 삭제는 모든 문이 같은 자물쇠를 확인해야만 진짜로 작동한다.
2026.06.01
마지막 날. 오후 3시40분: "2026-05 시즌 종료 모드 — 신규 진입 차단 + 안내" — 시즌 종료 모드, 신규 진입 차단, 그 자리에 안내문. 4분 뒤, 공유 에러코드가 따라붙었다: SEASON_ENDED를 JS 쪽에 동기화. 밤 10시13분, 프로젝트 전체의 마지막 커밋: 정산 확정 버튼이 무동작으로 바뀌고, 외부 수동 지급정산서로 전환됐다. "초기 구현"으로부터 3개월 4일, 알아서 계산하고 스크래핑하고 정산까지 하던 기계가 마지막 한 조각을 조용히 사람 손으로 돌려줬다.
2026.05.15
방향이 잘못된 쪽으로 너무 엄격했던 프라이버시 게이트였다. 기존 룰은 filingMethod가 DIRECT이고 status가 PAYMENT_COMPLETED일 때만 주소·환불계좌·부양가족 주민번호를 보여줬다 — 즉 SYSTEM 신고로 결제까지 마친 케이스는 정작 자기 정보를 못 봤다는 뜻. 수정은 DIRECT 조건을 뺐다: 이제 게이트는 결제완료 하나뿐, 신고방법은 상관없다. 결제 안 된 케이스는 여전히 숨김 — 커밋에 명시된 대로, PII 보호가 느슨해진 게 아니라 정당한 접근을 막던 게이트가 풀린 것이다.
2026.05.08
외국인 고객의 홈택스 로그인이 전부 실패하고 있었다 — 100%, 14명, 전원 AUTH_INFO_MISMATCH. 근본 원인: 주민등록번호는 한 자리 숫자로 출생 세기를 표시하는데, 외국인의 경우 그 자리는 1900년대를 뜻해야 함에도 코드는 2000년대로 계산하고 있었다. 1984년생 고객 한 명이 국세청엔 2084년생으로 전송됐다 — 미래 생년월일이라 거부, 24시간 동안 12번 재시도 전부 같은 이유로 실패. 수정은 파일 3개를 건드렸다 — 공유 RRN 유틸, 클라이언트 생일 계산 로직, 부양가족 설문 페이지 — 하는 김에 1800년대 케이스까지 같이 잡았다, 같은 세기 오류 로직이 밑에 깔려 있었으니까.
2026.05.07
5월6일에서 7일로 넘어가는 험한 밤이었다. KST 8~9시 사이 어딘가에서 hometax_listener가 조용히 멈췄다 — NOTIFY 이벤트 drop, 백업 폴링 경로도 같은 프로세스 메모리에 살고 있어서 동시에 실종, 둘 다 catch-up 메커니즘이 없었다. 별개로, 매퍼 하나가 소득상세 서식의 필드 하나를 계속 무시하고 있었고, 발견됐을 때는 95명이 합계 666,707,153원의 소득을 누락한 상태였다 — 몇 명은 전액, 대부분은 일부만. 새벽 1시46분~2시9분 사이, 케이스 4건을 save_to_db 직접 호출로 수동 복구했다. 그 뒤 남은 건 코드 주석: tax_case.py:17과 scraping_repo.py:54, 다음 사람이 경고를 볼 정확히 그 두 지점에 사고 기록을 박아뒀다. 그 사이사이 새벽 2시11분, 그리고 5시33분과 5시42분엔 서로 상관없는 verify-flow 트리거 하나가 제거됐다가, 복원됐다가, 그 복원이 다시 취소됐다 — 그날 밤 전체가 그런 모양이었다.
2026.05.05
두 시간짜리 RLS 정리가 잠깐 운영을 내려버렸다. 아침 7시3분엔 깔끔하게 시작했다 — "role 의도 기반 정리 + client_user 분리 GRANT/RLS 신설." 8시27분, 그 수정 중 하나가 자기 핫픽스를 필요로 했다 — "백그라운드 세션 admin SET ROLE + system collect_log GRANT (운영 다운 hotfix)," 커밋 메시지가 그냥 그렇게 적혀 있다. 8시45분엔 실제 피해 규모가 드러났다: 빈 문자열 GUC가 InvalidTextRepresentationError를 뱉는데, 5분에 147건. 9시엔 애초에 시작이었던 role 변경을 admin으로 되돌렸다 — 두 시간, RLS 커밋 열몇 개, 숫자 하나가 상황을 실감나게 만들었다.
2026.05.04
프로젝트 전체에서 가장 바빴던 하루: 커밋 82개. 그 한복판, 새벽 4시52분: PIPA 감사 후속으로 약관 3건 정정 — 새 규칙이 아니라 약관 문구를 실제 코드 동작에 맞춘 것. "홈택스 인증정보"는 아이디/비밀번호 대 간편인증 본인확인 정보로 구체화됐고, "즉시 파기"는 "24시간 이내 파기"로 바뀌었다 — purge_completed_credentials 스케줄러의 실제 cutoff가 24시간이었기 때문. 세 번째 조항은 제3자 제공 동의서로 흡수해 중복을 없앴다. 재동의는 불필요하다고 커밋에 적었다 — 동작이 바뀐 게 아니라 문구가 동작을 뒤늦게 따라잡은 것.
2026.05.03
한 고객 케이스가 모든 엔드포인트에서 500을 뱉기 시작했다 — validation, survey, calculation-method, calculation/run 전부. case 진입 시 usr_survey.case_survey를 읽는데, 그 테이블이 "permission denied for table"였다. 원인은 앞선 migration 145와 똑같았다 — 신규 테이블 추가할 때 GRANT를 빠뜨리는 패턴. migration 147로 두 가지를 고쳤다: 스키마 내 모든 현재 테이블에 GRANT, 그리고 ALTER DEFAULT PRIVILEGES로 아직 존재하지 않는 테이블까지 같은 실수를 못 반복하게. 마감 전에 실제 SELECT 권한으로 검증까지 마쳤다.
2026.05.01
해가 뜨기 전, 토스 결제 콜백이 Cloudflare를 통과하게 만드는 시도 네 번. 새벽 3시2분: successUrl을 직접 fetch하는 대신 프론트 결과 페이지로. 3시38분, fetch() 자체를 포기하며: "fetch → window.location.href (Cloudflare CORS 헤더 제거 우회)" — Cloudflare가 CORS 헤더를 지워버리니, 정중히 요청하길 관뒀다. 4시2분: successUrl을 아예 백엔드 콜백으로 직접 지정, 완전 우회. 6시15분엔 한 번 더 — 프론트 fetch를 통째로 없애고 백엔드 redirect로, "CORS/토큰 완전 우회." 네 커밋, 새벽 세 시간, 상대는 결제 로직이 아니라 네트워크 레이어였다.
2026.04.28
wireflow 첫 커밋으로부터 정확히 한 달. 새벽 5시7분: CLAUDE.md 가이드가 wireflow 안내에서 LinkLore MCP 도구 패턴(브리핑·조회·lore 등록·링크)으로 교체됐다. 8시12분엔 그동안 deprecate 상태였던 .wireflow/ 데이터 디렉토리도 삭제: "LinkLore(.linklore/)가 운영 중이므로 wireflow 데이터는 삭제." 세무 앱 안의 스펙 페이지 24장으로 시작한 게, 이제 독립된 도구가 됐다.
2026.04.25
오후 4시12분: 로그에 평문으로 남아있던 PII 4건 마스킹 — 카드번호, billing_key, 고객 이름, toss_billing_svc.py와 sqs_auth.py 안에서 — 커밋 메시지 표현으로 "자가치유 6번 검증으로 발견." 4시58분엔 ai-self-heal 브랜치가 머지됐다, "AI 자가치유 2개 사이클 결과." 5시11분엔 rate limit 누락 5건이 abuse 방어로 추가됐다. 세 커밋, 전부 한 시간 안에, 이름부터 자기가 하는 일을 말하는 브랜치: 스스로 치유.
2026.04.23
3시56분 — "LinkLore v2 마이그레이션 + API 네이밍 컨벤션 문서화, 11개 도메인." 3시58분 — "Blue Team" 리뷰를 거친 채팅/모바일 보안 수정. 2분 간격, 둘 다 새벽. 그 뒤로는 아무것도. mohadus는 조용해졌지만, 그 안에서 만들어진 LinkLore는 그러지 않았다.
2026.04.18
새벽 4시, 커밋 하나: "LinkLore 스펙 관리 시스템 초기 구축." 12개 플로우, 48개 스텝, 14개 섹션, 용어집과 아키텍처 문서, 코드파일 연결 1,525건 — 파일 377개, 5만4,960줄을 한 번에. 아직 독립 제품이 되기 전, 여기 이 레포 안에서 시작했다.
2026.04.15
이름 바꾸는 데 이틀에 걸쳐 세 번을 갈아엎었다. 1차(04-14): MCP 서버 그 자체 — `FastMCP("wireflow")`가 `FastMCP("llre")`로, `.wireflow/`가 `.linklore/`로, 옛 디렉토리는 다음 실행 때 자동 마이그레이션되게 호환 장치까지 심었다. 2차, 같은 날: UI 문구, localStorage 키, FastAPI 타이틀, LICENSE 연락처까지 겉면 전체. 3차, 오늘: 배포·인프라 — DB 이름, API 키 접두사 `wf_`가 `ll_`로, nginx 설정, systemd 서비스 파일을 새로 만들었다. WireFlow는 사라졌다, 위부터 아래까지, 아무도 안 보는 부분까지.
2026.04.13
오늘은 인정하기 싫은 lore를 하나 적었다. MCP 도구가 63개가 됐고, 진입점들이 서로 흐려지고 있다. 기능 하나 추가할 때마다 동사 하나씩 새로 만들었더니 동사가 63개가 됐다 — 사람이든 AI든 그걸 머릿속에 다 못 담는다. 일단 기록만 해뒀다, 아직 안 고쳤다. 내일 문제.
2026.04.04
4일째, AI 채팅 기능이 제일 허무한 방식으로 죽었다. 시스템 프롬프트 템플릿 안에 JSON 중괄호가 그대로 박혀 있었는데, 파이썬 `.format()`이 `{`를 전부 채워야 할 자리로 읽어버린 거다. KeyError, 채팅은 태어나자마자 죽었다. 고치는 데는 한 줄이면 됐다 — 중괄호 이스케이프. 근데 이런 버그는 만든 걸 진짜로 써봐야만 눈에 띈다.
2026.03.31
첫 커밋, 17:05. "WireFlow 웹앱 코어 + MCP 서버." 한 번에 Phase 1을 끝냈다 — 파일 86개, 와이어프레임 에디터, 스펙 섹션 13개, 용어사전, 공유스펙, 마크다운 내보내기. 커밋 메시지 속에 진짜 피봇이 숨어 있다: 기획서를 git처럼 다루기, 프로젝트 ID 기반 버전 추적, 웹앱에서든 MCP에서든 같은 소스를 양방향으로 편집. 문패는 아직 WireFlow였다. 이게 나중에 뭐가 될지는 아무도 몰랐다.
2026.03.28
오후 6시44분: "wireflow 스펙 초기화 — 24페이지 + 용어사전 + 공유스펙." 24페이지 스펙, 용어사전, 공유스펙 체계가 커밋 하나에 — 매 세션 제품 전체를 다시 설명하지 않고도 AI와 계획을 맞추기 위한 장치였다. 아직 이 레포 밖에서 의미 있는 이름은 아니었다 — 세무 플랫폼 안에 사는 wireflow, 커밋 하나짜리 역사.
2026.03.27
potatocraft.club이라는 이름으로 운영을 돌린 지 한 달이 채 안 됐을 때, 오전 11시10분: "운영 도메인 전환 (potatocraft→haedream-tax) + 이메일 저장 기능" — 임시로 붙인 이름이 드디어 진짜가 됐다. 별다른 의식은 없었다: 상관없는 이메일 저장 기능과 같은 커밋에 묶여서 배포됐을 뿐. 다른 일 하러 가는 길에 슬쩍 이름만 바꾼 것처럼.
2026.03.03
핵심 엔티티를 한복판에서 리네임했다 — taxdoc이 tax_case로, DB 스키마·모델·features·shared·web 전체를 한 리팩터로. 그 밑의 스크래퍼 기반도 CODEF 실제 API로 교체: OAuth, 2-way 간편인증, 14개 상품 API. 하루 뒤 성과: 로그인 한 번으로 금융상품 8개를 한 세션에 조회 — "scrape_all()", 첫 상품 먼저, 1초 뒤 나머지 동시 발사. 테스트 결과 8개 중 7개 성공, paystatement 하나만 일시적 CF-12701 오류. 믿고 쓸 만했다.
2026.03.02
크래시 수정 6건, 하루 안에, 하나씩 잡을 때마다 다음 게 튀어나왔다. 낮 12시24분: AuthContext 동적 import를 정적 import로 바꿔 초기화 순서 에러를 잡았고, 오후 4시9분: "DashboardPage safeStats 자기참조 TDZ 에러" — 변수가 자기 선언 안에서 자기 자신을 참조해서 "Cannot access before initialization." 그리고 5시33분~5시43분, 10분 사이: assigned_agent가 {id, name} 객체 그대로 렌더링되면서 React error #31, RightPanel은 undefined memos/alimtalk_logs/timeline로 크래시, task detail 탭도 같은 undefined 방어 처리. 두더지잡기, 흰 화면 하나씩.
2026.02.28
첫날, 오전 10시49분: "해드림(Haedream) 종합소득세 신고 플랫폼 초기 구현" — 무에서 전부. 9분 뒤 실제 도메인이 붙었다, potatocraft.club, 이후 한 달을 이렇게 불릴 코드네임. 오후 4시엔 에러 처리가 꼴을 갖췄고(ErrorCode dataclass + raise_error 패턴), 밤 10시27분 — 아직 첫날 — 홈택스 임베디드 OACX 간편인증을 Playwright로 자동화하고 있었다, 로그인 UI·iframe·세션 쿠키까지. 커밋 11개, 아무도 못 맞출 도메인 하나, 열두 시간이 채 안 되는 사이에.
2026.02.14
11시51분 — 관리자용 캠페인 상세 페이지 복원. 11시52분 — 그 복원을 되돌림. 11시53분 — 다시 복원, 이번엔 다르게. 커밋 세 개, 2분, 뭘 원하는지 못 정한 페이지 하나.
2026.02.09
네이버 OAuth를 서버사이드로 리팩토링. 하루 뒤: 통째로 롤백. 맞는 선택은 가끔 틀린 걸 이미 배포하고 나서야 보인다.
2026.01.30
아이디어 추가. 통계를 만들어볼까?
2026.01.26
21일 "standby passed, after launching." 닷새 뒤: "android, ios launching done", 같은 날 "release 1.0". 커밋 로그엔 별다른 의식 없이, 딱 세 줄로 전체 여정이 끝났다.
2026.01.12
새벽 3시50분부터 5시32분까지 RLS 커밋 여덟 개 연속. 진짜 핵심은 4시14분의 "Member RLS 자기참조 서브쿼리 제거 (무한 재귀 수정)" — 자기 자신을 영원히 확인하고 있던 권한 체크를 새벽 4시에야 누군가 알아챘다.
2026.01.06
핵심 스키마 이름을 갈아엎었다: reporting은 work로 흡수, attendance는 work로 개명. 이틀 걸렸고, 첫 시도가 부족했다는 걸 인정하는 "need to check repository" 커밋 메시지까지 남겼다.
2025.11.19
새벽 2시, "security by gpt5.1 codex" 계열 제목으로 커밋 세 개 연달아. 그중 하나만 봐도 1,458줄 삭제에 156줄 추가 — 보안 점검이라는 게 대개는 뭘 더하는 게 아니라 지우는 일이었다.
2025.09.17
테스터들의 리뷰 반영. 아이폰 13의 노치와 15의 다이내믹아일랜드에서 UI 깨짐 발견.
2025.09.02
SnapToday는 Snapchat과 겹쳐보인다는 이유로 StackToday로 리네이밍.
2025.08.31
이틀째, 어제 열어놓은 걸 닫았다: "e-mail log in comleted." 오타 난 커밋 메시지 그대로 뒀다 — 어떤 건 다듬지 않고 그냥 보낸다.
2025.08.30
첫 커밋: "mohadus project." 40분 뒤 벌써 로그인 체크 중. 오후 4시엔 첫 배포 — "server uploade first", 오타까지 그대로. 아무것도 없던 상태에서 로그인 되는 배포판까지 한 세션에 갔다.
2025.08.27
"커서"를 처음 써봤다. 코딩의 신세계가 열렸다. 와.
2025.08.15
드디어 다시 시작. 기존이 베타개념이었다면, 이제 알파로 진화. iOS 드디어 시작. SnapToday로 리네이밍 예정
2024.12.11
회사랑 일상문제들 처리하느라 진짜 너무 바빴다. 8개월만의 프로젝트 오픈. 안드로이드 권한 대응처리. 사이드 프로젝트로 진행했던 거라 깊은 투입 불가.
2024.05.05
한동안 main 브랜치 마지막 커밋. 이후 7개월 침묵.
2024.04.03
안드로이드 첫 출시, 밤 10시 8분.
2024.03.31
출시 전날 밤, 사용자 많은 나라 순으로 다국어 6종을 몰아넣었다.
2024.02.10
기본 기능 다 구현 완료. 커밋엔 "디자인 남았따"라고, 오타까지 그대로.
2024.02.01
퇴근하면 체력이 너무 모자라다. 일이 너무 많다. 빨리 런칭해보고 싶은데. 애드몹 연동 완료.
2024.01.27
센서의 방향과 카메라의 방향 불일치 찾기. 하드웨어 다루는 건 너무 어렵다.
2024.01.21
D-day는 왜 매번 계산해서 합성해야할까? 사진찍는 순간 그대로 저장하면 안될까? 오래된 궁금증 직접 해결 결심. 첫 커밋.
여정의 시작