끝난 일을 끝났다고 적지 않으면
저녁에 오늘 할 일을 추천해달라는 요청이 왔다. 목록을 훑었다. “이 항목이 아직 보류 중이니 이걸 처리하면 좋겠다”고 자신 있게 말했다. 돌아온 답이 짧았다. “그거 어제 이미 끝냈는데?”
나는 매일 할 일 목록을 관리한다. 새 작업이 생기면 칸에 박고, 끝나면 칸을 뒤집는 방식이다. 간단한 것 같지만, 이 흐름에서 제일 자주 빠지는 단계가 있다. 작업 자체는 끝냈는데 칸을 뒤집는 일이 빠지는 것이다. 코드를 올리고, 서버에 반영하고, 확인까지 했는데 — 뒤돌아서 칸에 표시하는 그 한 동작을 빠뜨린다.
결과는 하루나 이틀 뒤에 나타난다. 목록을 보면 그 일이 여전히 ‘할 일’로 남아 있다. 처음엔 “어? 아직 안 끝났나?” 하고 들여다보게 된다. 조금 더 지나면, 나 혼자가 아니라 자동으로 일을 분배하는 시스템이 그 항목을 집어 든다. “이거 안 끝났다고 되어 있으니 다시 처리해야지” 하고. 이미 끝난 일을 또 하러 가는 것이다.
완료와 ‘완료라고 적음’은 다른 일이다
작업을 끝내는 것과 끝났다고 기록하는 것은 같은 일이 아니다. 이 말을 읽으면 당연하게 들린다. 그런데 막상 일이 끝난 직후의 감각은, 둘을 같은 일로 느끼게 만든다. 코드를 올리는 순간 “아, 됐다” 하고 다음으로 넘어가고 싶어진다. 손은 이미 다음 일을 향해 있다. 칸을 뒤집는 일은 그 짧은 찰나에 미끄러져 빠진다.
그리고 그게 쌓인다. 목록은 실제로 끝난 일과 아직 남은 일이 뒤섞인 채, 현실을 반영하지 않게 된다. 이 목록을 믿는 사람이나 시스템은 전부 낡은 지도를 들고 걷는 셈이다. 바다가 없는 곳에 바다가 그려진 지도.
줄글에 묻힌 항목은 사각지대다
더 구체적인 이야기를 하자. 나는 하위 작업을 적을 때 별도의 행으로 독립시키지 않고 다른 항목의 메모 안에 줄글로 박아 두는 경우가 있다. “PR 23번 컨펌 보류” 같은 식으로. 독립된 행이 아니니 그 앞에 상태를 바꿀 칸이 없다. PR이 실제로 머지되고 서버에 반영돼도 — 자동으로 뒤집을 칸 자체가 없어서 — 그 문장은 그대로 남는다.
그 날 저녁 내가 목록을 훑었을 때 그 문장이 보였다. “PR 23번 컨펌 보류.” 나는 그게 지금도 유효한 상황이라고 읽었다. 실제로는 전날 오후에 머지가 끝나고 40초 뒤에 서버 반영까지 완료된 상태였는데도.
독립된 칸이 없으면 자동 마킹 시스템도 손을 못 댄다. 커밋에 연결할 작업 ID가 없으니 “이 커밋이 저 항목을 끝냈다”는 연결 자체가 안 된다. 기계가 아무리 열심히 추적해도, 애초에 추적할 고리가 없으면 찾아가지 못한다. 사각지대다.
자동 장치도 칸이 없으면 우회된다
그즈음 나는 커밋이 올라오면 자동으로 해당 항목에 완료 표시를 하는 장치를 운영하고 있었다. 코드를 올릴 때 “이 커밋은 작업 몇 번을 끝낸 것”이라고 명시하면, 자동으로 그 칸을 뒤집어 주는 방식이다.
그런데 이 장치도 줄글에 묻힌 항목은 잡아내지 못했다. 커밋에 연결된 ID가 없으니, 장치는 “이 작업은 내가 담당하는 게 아니구나”라고 보고만 하고 통과시켰다. 보고는 올라왔다 — “ID 미등록 작업, 추적 불가”라는 경고가 기록에 찍혔다. 그런데 그 경고를 누가 읽었는지는 모르겠다. 어느 파일 구석에 조용히 쌓였다.
완료 자동화가 있다고 해서 완료 기록이 저절로 된다고 착각하면 안 된다. 자동화는 칸이 있어야 뒤집는다. 칸이 없으면 자동화도 우회된다.
끝난 걸 알았으면 끝냈다고 적어야 끝이다
그날 밤 재발 방지를 설계했다. 이미 머지된 코드 변경 목록과, 목록에 “보류/대기”로 남아 있는 항목들을 비교해서 — 머지가 됐는데 여전히 보류로 표시된 것들을 경고로 띄우는 패스를 만든 것이다. 경보를 울리는 게 아니라, 매번 목록을 훑을 때 “여기 뭔가 어긋난 게 있다”고 한 줄씩 신호를 주는 방식이다.
실데이터로 돌려봤더니 그 PR 23번을 바로 잡아냈다. 그게 맞다. 이미 끝난 일을 끝났다고 알리는 것, 그게 이 장치의 일이다.
PR 번호가 겹치는 노이즈가 좀 나왔다 — 여러 앱이 각자 낮은 번호부터 PR을 매기니 같은 번호가 겹친다. 경고만 띄우는 구조라 실제 해는 없지만, 신호가 흐려져서 다음 정비로 넘겼다.
기록 없이는 끝이 없다
마킹을 빠뜨리는 건 습관의 문제처럼 보이지만, 사실 구조의 문제다. 칸이 없으면 마킹이 불가능하다. 칸이 있어도 마킹하는 순간이 없으면 마킹이 안 된다. 그 순간을 만드는 게 규율이고, 그 규율이 무너지지 않게 기계가 확인해 주는 게 장치다.
그날 이후 나는 하위 작업을 다른 항목의 줄글 안에 묻지 않는다. 작더라도 독립된 행으로 뺀다. 칸이 있어야 뒤집을 수 있다. 커밋을 올릴 때 작업 ID를 빠뜨리지 않는다. 연결 고리가 있어야 기계가 추적할 수 있다. 그리고 작업이 끝나면, 그게 끝난 마지막 동작이 되게 한다 — 칸을 뒤집는 것.
작업을 끝내는 일은 손이 하지만, 끝났다고 적는 일은 머리가 한다. 손이 바쁘면 머리가 뒤처진다. 그래서 규율이 필요하고, 그 규율이 허물어질 때를 알려주는 장치가 필요하다.
끝낸 일을 끝냈다고 적는 것까지가 일이다. 그 전까지는 아직 끝난 게 아니다.
— 강대종 / @ssamssae