바이브코딩 실전 · 후속 개선 8편
원본을 바꾸는 버튼에는 권한과 실패 기준이 먼저 필요하다.
조회 화면에 ‘읽음’ 버튼을 붙이는 일은 작아 보인다. 그러나 노션의 체크를 바꾸는 순간, 앱은 원본에 쓰는 도구가 된다. 누가 누를 수 있는지, 어떤 칸을 바꾸는지, 결과를 모를 때 다시 보내도 되는지까지 정해야 한다. 이번 편은 작은 버튼에 허용할 권한을 좁히는 방법을 다룬다.
오늘 다시 볼 메모가 0개면 오류일까?
오늘 목록이 비어 있다고 계산부터 고칠 필요는 없다. 다시 볼 날짜가 오늘이거나 과거이고, ‘다시 봄’ 체크가 꺼진 메모만 오늘 목록에 들어간다. 모든 일정이 미래라면 0개가 정상이다. Aside는 이번 점검에서 이 계산을 오류로 취급하지 않고, 미래 일정이 있다는 사실을 화면에 명확히 드러내는 쪽을 택한다. ‘월/일에 다시 보기’와 ‘오늘 다시 볼 메모’를 나누고, 완료와 날짜 미지정도 구별한다. 숫자가 작아 보인다는 이유로 미래 메모까지 오늘 할 일에 합치면 오류를 고치는 것이 아니라 약속한 날짜의 뜻을 바꾸게 된다.
앞선 앱에서 메모를 열어 본 표시는 현재 브라우저에 남는다. 이것은 노션의 ‘다시 봄’과 다르다. 가상 텃밭 기획을 잠깐 열어 봐도 다시 검토할 일을 끝냈다는 뜻은 아니다. 다른 기기에서도 유지할 완료 표시는 소유자가 별도로 ‘읽음’을 눌러 정한다.
알림을 보여 주는 일도 실제로 읽는 일과 다르다. 메모봇이 건넨 요청서에는 알림을 보여 주면 ‘다시 봄’을 체크한다는 규칙이 적혀 있다. 이번 웹앱의 명시적 읽음과 의미가 다를 수 있지만, 그 봇 규칙은 바꾸지 않는다. 화면 개선을 핑계로 다른 도구의 동작까지 조용히 변경해서는 안 된다.

버튼마다 바꾸는 칸을 정한다
쓰기를 허용하는 대상은 ‘다시 볼 날’, ‘다시 봄’, ‘용도’ 세 칸뿐이다. 본문과 제목까지 고칠 수 있는 범용 편집 기능을 만들지 않는다. 소유자로 로그인한 사람이 명시적으로 버튼을 누를 때만 이 제한된 요청을 보낸다.
- 읽음: ‘다시 봄’ 체크를 참으로 바꾼다. 날짜나 용도는 그대로 둔다.
- 3·7·14일 미루기: 서울 기준 오늘에 선택한 일수를 더한 날짜를 넣고, ‘다시 봄’을 거짓으로 바꾼다.
- 보관: 확인창을 거쳐 기존 용도를 보존하면서 ‘보관’을 더하고, 날짜는 비움(null), ‘다시 봄’은 참으로 둔다. 메모 삭제가 아니다.
기존 용도에 ‘책소재’가 있다면 보관 뒤에도 그 성격은 남아야 한다. ‘보관’ 하나로 모두 덮어쓰면 버튼 하나가 분류 정보를 지우게 된다. 요청문에는 바꿀 값뿐 아니라 손대지 않을 값도 써 두는 편이 안전하다.

화면에서 숨기면 권한도 막힐까?
소유자가 아닌 사람에게 버튼을 숨기는 것은 안내일 뿐, 서버의 문을 잠그는 방법은 아니다. 서버는 요청마다 서명된 소유자 세션과 정확한 Origin, 즉 요청이 출발한 사이트를 확인한다. 메모가 해당 보관함 소속인지, 세 칸의 자료형이 맞는지, 허용하지 않은 항목을 보내지는 않는지도 검사한다. 요청 크기와 빈도에도 제한을 둔다. Aside가 구현하는 경계는 ‘이 화면에서만 누르게 하기’가 아니라 ‘서버가 허용한 세 칸에만 쓰기’다. 화면을 우회한 요청도 같은 문턱을 지나야 하므로 버튼의 노출 여부만으로 안전을 판단하지 않는다.
다른 도구가 먼저 값을 바꾸는 상황도 살핀다. 앱은 화면을 읽을 때의 수정 시각과 세 칸의 값 묶음, 곧 스냅숏을 함께 보낸다. 서버가 다시 읽은 값과 다르면 저장을 멈추고 새 값을 확인하게 한다. 수정 시각 하나에만 기대지 않고 변경 대상인 세 값도 대조한다. 수정 시각은 같지만 대상 값이 바뀐 경우도 가상 자료로 시험한다.
다만 이번 구현은 완전한 잠금이 아니다. 값을 확인하는 요청과 저장하는 요청이 서로 떨어져 있다. 문패를 확인한 뒤 문을 여는 짧은 사이에 다른 사람이 값을 바꿀 여지는 남는다. 같은 메모의 동시 편집을 피하고, 충돌하면 새 값을 읽은 뒤 다시 판단해야 한다.
실패 안내도 저장 여부를 나눈다
쓰기에 실패한 경우와 저장은 끝났지만 뒤따른 조회만 실패한 경우는 다르다. 뒤의 경우를 ‘저장 실패’라고 표시하면 사람은 같은 버튼을 다시 누르기 쉽다. 서버가 저장 성공을 확인하면 그 사실을 유지하고, 최신 목록을 확인하지 못했다는 경고만 따로 보여 준다.
반대로 응답이 끊겨 실제 저장 여부를 모르면 ‘결과 불확실’이다. 이때 쓰기 요청을 자동 재전송하지 않는다. 거절된 요청, 충돌, 저장 뒤 조회 실패, 결과 불확실을 같은 빨간 안내 하나로 뭉개지 않아야 다음 행동을 정할 수 있다.
이미 성공한 상태를 늦게 도착한 옛 목록으로 되돌려서도 안 된다. 앱은 성공한 값을 유지하고, 불일치가 5초를 넘으면 해당 메모를 직접 조회한다. 확인에 실패하면 마지막으로 확인한 값과 오래된 자료라는 표시를 남긴다. 로그아웃이나 세션 만료 뒤에 온 응답으로 메모를 다시 펼치지도 않는다. 다만 로그아웃이 이미 출발한 원격 쓰기까지 취소한다는 보장은 없다.
가상 시험과 실제 쓰기를 구별한다
운영 서버에는 코드가 배포되고, 익명의 새 쓰기 요청이 차단되는 것을 확인한다. 실제 원본의 식별값과 수정 시각, 세 칸 값도 그대로임을 대조한다. 버튼 동작 시험은 실제 서버의 인증과 요청 출처 검사에 가상 SDK를 연결해 진행한다. 저장소와 통신하는 부분을 가짜 응답으로 바꾸어 읽음·미루기·보관과 지연·거절 처리를 살피는 방식이다. 이 시험을 위해 실제 노트를 수정하지 않는다. 따라서 이 결과는 버튼과 방어 동작의 확인이지, 실제 노션 쓰기 성공의 증거가 아니다. 운영 배포와 실제 동기화 완료를 같은 말로 보고하지 않는다.
노션 연결에 콘텐츠 업데이트 권한이 있는지, 실제 쓰기가 되는지는 아직 미검증이다. 첫 실제 처리는 소유자가 직접 확인할 단계로 남는다. 권한 부족을 오류로 안내하는 코드가 있다는 사실과 실제 연결이 그 권한을 가진다는 사실도 구분해야 한다.
다음은 독자가 바꿔 쓸 실습용 요청문이며 실제 사용자 발언이 아니다.
조회 앱에 소유자 전용 읽음·미루기·보관 버튼을 추가해 줘.
원본의 날짜·다시 봄·용도 세 칸만 변경하고 본문은 건드리지 마.
브라우저 열람과 원본 완료 표시를 구분해 줘.
충돌하면 멈추고, 저장 여부가 불확실하면 자동 재전송하지 마.
가상 자료로 먼저 시험하고 실제 쓰기는 확인 전까지 하지 마.
저장 성공과 후속 조회 실패를 나누어 보고해 줘.
검수 기준은 다음과 같다.
- 작동: 가상 자료에서 세 버튼이 약속한 칸만 바꾸고 기존 용도를 보존하는가.
- 실패: 익명 요청·충돌·불확실 응답을 구별하며, 늦은 목록이 성공을 되돌리지 않는가.
- 저장 위치: 브라우저 열람은 이 브라우저에, 명시적 완료는 노션에 남는다고 안내하는가. 실제 쓰기 미검증 표시도 있는가.
읽음 버튼의 완성도는 누르기 편한 모양만으로 정해지지 않는다. 무엇을 바꿔도 되는지와 어디까지 확인했는지를 함께 보이게 하는 것이, 조회 화면을 쓰기 도구로 넓힐 때의 기준이다.
기록 기준: 2026년 10월 20일의 후속 개선 작업. 예시 화면과 설명도식에는 가상 자료를 사용했다.
이 글은 실제 제작 기록을 바탕으로 AI의 도움을 받아 구성하고 검수했다.