Geonwoo Lee
← 프로젝트 목록

개인 상황판 · 자동화/운영

디딤

답이 여러 페이지에 흩어지면 지금 뭘 해야 하는지 알 수 없습니다.

취업 준비에 필요한 것을 한 화면에 모은 개인 상황판입니다.
취업 공고 수집, 분석, 학습 및 학습기록, 메일 요약 및 분류, 알림 등의 다양한 개인 기능들을 이 한 페이지에서 관리할 수 있습니다. 메일 쪽을 채우는 도구를 만든 뒤 전면 검수를 한 번 돌려 29가지를 찾아 고쳤습니다.

혼자 쓰는 도구입니다
상주 서버 없이 개인 PC에서 돕니다. 아래 수치는 제 메일함 한 벌(계정 2개·2,382통)에서 나온 것이며 여러 사용자나 운영 규모를 뜻하지 않습니다. 메일 본문과 발신자가 들어 있어 저장소와 실행 화면은 공개하지 않습니다.

01 / 무엇인가

필요한 것 여섯 가지를 여섯 개의 도구로 만들지 않았습니다.

우선순위 · 주간 작업 · 생각 정리 · 프로젝트 현황 · 결정 기록 · 결정의 흐름. 취업 준비에 필요하다고 적어 둔 것들입니다. 각각을 페이지로 만들면 그 사이를 오가게 되고, "지금 뭘 해야 하는가"의 답이 흩어지면 그 질문에 답할 수 없습니다. 그래서 하나의 면으로 만들었습니다.

화면은 열 개이고, 가운데 구분선으로 성격이 갈립니다.

구분선 위는 취업, 아래는 일상 — 섞이면 "지금 할 일"이 흐려집니다
갈래화면데이터를 넣는 쪽
취업상황판 · 로드맵 · 우선순위 · Lab · 면접 · 구직직접 적습니다
일상일정 노트 · 구매 노트직접 적습니다
일상메일 · 고정비별도 도구가 채웁니다

서버를 세우지 않았습니다. 이 화면의 값어치는 대화 상대와 같은 자리에 있다는 것이라, 별도 도메인으로 옮기면 그 연결이 끊깁니다. 그래서 claude.ai 아티팩트 한 장으로 두고, 빌드 도구가 없고 파일이 한 장이라는 제약은 그대로 받아들였습니다.

기여 범위 — 설계·구현·운영 전부 제가 했습니다. 구현 과정에서 AI 도구를 사용했고, 무엇을 만들지와 무엇이 틀렸는지의 판단은 제가 내렸습니다.

02 / 만든 방식

여섯 개를 다 설계하고 시작했으면 첫날에 아무것도 못 띄웠습니다.

첫 화면 하나를 두 시간 안에 띄우고 동결한 뒤, 필요해지는 순서대로 나머지를 붙였습니다. 붙은 순서가 곧 실제로 필요했던 순서입니다.

  1. 하루 동안 화면이 하나씩 늘었습니다.

    상황판 → 결정 분기 → 일정 노트(o/x/△, 다음 날로 넘기기, 달력에 수행도를 색으로) → 구매 노트(우선순위 매트릭스·태그·후보 비교) → 교재. 마지막에 이름을 정했습니다.

  2. 탭 이름을 일곱 번 고쳤습니다.

    "한눈에"는 무엇을 보는지가 없어 상황판으로, "게이트 36칸"은 내부 구조를 이름으로 내보낸 것이라 진도로, "Inbox"는 영어 낱말이 기능을 가려 생각담기로 바꿨습니다. 규칙은 하나입니다 — 누르기 전에 무슨 일이 생길지 이름에 있어야 합니다.

  3. 화면 문장 규칙을 문서로 굳혔습니다.

    "무엇이 막고 있는가?" 같은 제목이 AI 말투로 읽히고 TBD 같은 약어가 그대로 남아 있었습니다. 나중에 메일 화면을 만들면서 같은 규칙이 일곱 줄짜리 문서가 됐습니다 — 한 줄에 한 문장, 실제 이름으로 쓰기, 자르지 않기, 숫자에 무엇을 센 숫자인지 붙이기 등입니다.

이 방식의 대가도 있습니다. 만드는 동안 커밋을 하지 않아 초기 74판의 코드가 남아 있지 않습니다. 결정과 근거만 뒤늦게 설계 문서로 옮겼고, 코드는 되살릴 수 없다는 사실을 그 문서 첫 장에 적었습니다.

03 / 메일 화면과 그 뒤

되돌릴 수 없는 것을 먼저 정했는데, 그것을 지키는 테스트가 없었습니다.

화면 열 개 가운데 메일과 고정비만 사람이 적지 않습니다. 별도 도구가 지메일·네이버 메일을 가져와 분류하고, 그 결과를 이 보드에 읽기 전용으로 올립니다. 보드에서 메일함으로 돌아가는 길은 없습니다 — 사람이 링크를 눌러 메일 서비스를 직접 엽니다.

메일이 2,382통이고 그중 78%가 분류 결과 "읽지 않아도 되는 것"이었습니다. 문제는 양이 아니라 그 안에 섞인 지금 해야 하는 몇 건을 찾는 데 드는 시간이었습니다.

  1. 수집IMAP · 읽기 전용
  2. 정제본문 추출 · 개인정보 마스킹
  3. 분류등급 · 할 일 · 결제 추출
  4. 알림중요한 것만 · 채널 분리
  5. 상황판읽기 전용 화면

이 흐름에서 되돌릴 수 없는 것은 하나입니다. 본문을 평범하게 가져오면 서버가 읽음 표시를 붙이고, 그것을 되돌릴 방법이 없습니다. 읽음 상태가 오염되면 무엇이 새로 왔는지를 판단할 근거를 잃습니다. 그래서 폴더를 읽기 전용으로 열고, 읽음 표시가 붙지 않는 방식으로만 본문을 가져오도록 정했습니다.

코드는 그대로 지켜지고 있었습니다. 문제는 그것을 지키는 테스트가 없었다는 것입니다. 검수에서 확인해 보니 읽기 전용 설정을 지우거나 본문 가져오는 방식을 바꿔도 테스트 281개가 전부 통과했습니다.

테스트를 붙인 뒤, 그 테스트가 실제로 깨지는지 코드를 일부러 훼손해 확인했습니다.

붙인 테스트가 실제로 잡는지 확인한 결과
무엇을 망가뜨렸나붙이기 전붙인 뒤
읽기 전용 설정을 끔281개 전부 통과실패 2건
읽음 표시가 붙는 방식으로 본문 수집281개 전부 통과실패 2건
읽은 메일에 플래그를 붙이는 줄 추가281개 전부 통과실패 4건

오간 명령을 기록하는 방식과 소스를 직접 읽는 방식 두 가지로 검사합니다. 앞의 것만으로는 테스트가 지나가지 않는 새 코드 경로를 놓칩니다.

04 / 화면 이식

중괄호 개수가 맞는다고 구조가 맞는 것은 아니었습니다.

메일 화면은 따로 만든 뒤 이 보드에 옮겨 넣었습니다. 보드는 이미 완성돼 있고 파일이 한 장이라, 옮길 때 클래스 이름이 겹치고 페이지 껍데기가 두 겹이 됩니다. 클래스가 198개라 손으로 고치면 목업을 한 줄 고칠 때마다 그 작업을 다시 해야 합니다. 그래서 변환기를 만들어 통과시켰습니다.

그 변환기가 CSS에서 껍데기를 걷어낼 때 정규식 하나로 선택자{선언}을 긁었습니다. 그러면 조건부 스타일 블록이 통째로 풀립니다.

좁은 화면 전용 규칙이 최상위로 튀어나온 경로
원본정규식이 읽은 것결과
좁은 화면에서만 1열조건이 선택자의 일부로 읽힘모든 폭에서 1열

세 화면이 한꺼번에 무너졌고, 규칙 28개가 중복으로 들어갔습니다. 그때 저는 "중괄호 1332개 / 1332개 균형"만 보고 통과라고 판단했습니다. 개수는 맞았고 구조는 뒤집혀 있었습니다.

  1. 중괄호를 세어 자르고 블록 안쪽으로 재귀하게 바꿨습니다.

    정규식 한 번으로 끝나던 자리를 파서로 바꿨습니다. 조건부 블록은 블록째 보존하고 안쪽만 훑습니다.

  2. 변환기가 스스로 결과를 검사하고, 걸리면 멈추게 했습니다.

    접두사가 안 붙은 클래스, 조건이 선택자로 샌 것, 선언 없는 토큰, 남아 있는 페이지 껍데기 네 가지를 봅니다. 하나라도 걸리면 종료 코드를 0이 아닌 값으로 냅니다 — 반쯤 망가진 결과물을 만들지 않기 위해서입니다.

  3. 검사 규칙은 전부 한 번씩 당한 것들입니다.

    주석이 선택자에 달라붙어 여백 21군데가 0이 된 일, 이미 테두리를 가진 클래스를 컨테이너로 다시 써서 상자가 겹쳐 보인 일이 각각 규칙 한 줄이 됐습니다.

결과물은 원본과 도구만으로 바이트 단위까지 다시 만들어집니다. 사람이 손댄 자리가 남아 있으면 그 성질이 성립하지 않습니다.

05 / 전면 검수

테스트 281개가 전부 통과하는 상태에서 29가지가 살아 있었습니다.

만든 것이 실제로 맞게 동작하는지 한 번 전부 확인했습니다. 결함은 테스트가 아니라 실제 데이터를 들여다봐서 나왔습니다. 아래는 그 가운데 성격이 다른 넷입니다.

실제 데이터에서 드러난 것 · 전체 29가지 중 4가지
무엇이 틀렸나왜 안 보였나고친 뒤
같은 결제를 두 번 셈상점과 결제대행사가 상호를 다르게 씀이번 달 총액에서 허수 18% 제거
달러 결제를 원화로 더함통화 칸은 있는데 합계가 보지 않음환산 못 한 15건을 빼고 밝힘
3년 전 일이 "지금 할 것"에할 일 판정에 기간 상한이 없음할 일 21건 → 11건
시도 횟수가 성공해도 안 줄어듦실패 경로만 테스트가 있었음한도 직전이던 24통 복구

맨 아래 것이 이 검수의 성격을 잘 보여줍니다. 분류에 성공해도 시도 횟수가 0으로 돌아가지 않아, 한 번도 실패한 적 없는 메일 24통이 격리 한도를 하나 남겨 두고 있었습니다. 실패 경로를 보는 테스트는 세 개 있었고 성공 경로를 보는 테스트는 없었습니다.

29가지는 전수가 아닙니다
한 번의 검수에서 찾은 것이고, 더 있을 수 있습니다. 찾은 방식은 코드 읽기·실제 데이터 조회·재현 실험이며, 각 결함은 고친 뒤 그것을 잡는 테스트를 같이 붙였습니다(281개 → 327개).

06 / 고장 감지

메일이 0통이면 정상과 고장이 똑같이 조용합니다.

알림이 메일에서 파생되므로, 도구가 죽어도 사용자에게는 "조용한 날"과 구분되지 않습니다. 그래서 메일 내용과 무관한 네 번째 신호를 따로 두었습니다.

  1. 세 층으로 나눴습니다.

    계정 단위(인증 실패·수집 정지), 파이프라인 단위(격리 누적·큐 정체), 전체 정지. 앞의 둘은 본체가 알리고, 전체 정지는 본체와 별개로 도는 감시가 알립니다 — 프로그램이 죽으면 프로그램은 알릴 수 없습니다.

  2. PC가 통째로 안 뜨는 경우는 바깥에 맡겼습니다.

    그때는 감시도 같이 죽습니다. 외부 감시 서비스에 주기적으로 신호를 보내고, 끊기면 그쪽에서 알리도록 했습니다.

  3. 검수에서 이 설계의 구멍도 나왔습니다.

    접속에 성공하면 새 메일이 0통이어도 "수집 성공"으로 기록해, 읽는 위치가 망가져도 조용했습니다. 알림 경로가 죽었을 때 그 사실을 같은 경로로 알리려는 고리도 있었습니다. 둘 다 이 모듈이 애초에 풀겠다고 선언한 문제와 같은 종류였습니다.

알림 채널은 지금 봐야 하는 것 · 하루 요약 · 도구 자체의 고장 셋으로 나눠 두었습니다. 섞이면 고장 알림이 메일 알림에 묻힙니다.

07 / 남은 한계

확인하지 않은 범위를 남겨 둡니다.

화면에서 사람이 적은 것(일정 노트·구매 노트·발신자 판단)은 아직 브라우저 안에만 남습니다. 서버에 남기는 경로를 만들어 두었으나 화면이 아직 그것을 읽지 않습니다. 다른 기기에서 열면 비어 있습니다.

분류 품질은 별도로 측정하지 않았습니다. 화면에 뜨는 등급과 요약은 모델 판정이며, 정답 집합과 비교한 정확도 수치는 없습니다. 검수에서 확인한 것은 "집계와 표시가 데이터와 일치하는가"이지 "판정이 옳은가"가 아닙니다.

검증 범위와 미검증 항목 — 읽기 전용 보장, 집계 정합성, 이식 파이프라인의 재현성, 고장 감지 경로를 확인했습니다. 분류 정확도·다중 사용자·대규모 메일 처리·상용 운영 경험으로 확대하지 않습니다. 메일 본문과 발신자가 들어 있어 저장소와 실행 화면은 공개하지 않습니다.