여섯 편 동안 무엇을 어떻게 만들었는지 적었다. 마지막 편은 틀렸던 것들이다. 다섯 개를 골랐는데, 고르고 보니 공통점이 있었다. 에러를 띄우고 죽는 고장은 오히려 금방 고쳤다. 오래 걸린 쪽은 전부 아무 말 없이 틀려 있던 것들이다.
1. 화면이 그냥 옛날 것으로 남아 있었다
어드민 대시보드를 새로 만들어 붙였다. 새로고침을 했는데 예전 화면이 그대로 나왔다.
코드를 다시 봤다. 경로도 맞고 파일도 있었다. 몇 번을 지웠다 다시 써도 똑같았다. 한참 뒤에 서버 쪽 로그를 열어 보고 알았다.
getFromImportMap: PayloadComponent not found in importMap
쓰는 CMS는 커스텀 화면의 경로를 별도 목록에 적어 둬야 알아본다. 그 목록을 만드는 명령을 한 번 돌려야 하는데, 안 돌렸으니 새 화면을 못 찾은 것이다.
문제는 못 찾았을 때의 동작이었다. 화면을 못 띄우면 그냥 기본 화면으로 조용히 되돌아간다. 오류는 서버 로그에만 찍힌다. 브라우저에는 아무 표시도 없다.
보고 있는 화면이 "새 코드가 안 먹은 것"인지 "원래 이렇게 생긴 것"인지 구분할 방법이 없었다.
2. 주소에 한글이 들어갔다
글 제목을 넣으면 주소를 자동으로 만들게 해뒀다. 영어 제목으로 테스트할 때는 멀쩡했다. 한글 제목을 넣어 보니 이렇게 나왔다.
/posts/postgres-17이-sqlite를-능가한-지점
기술적으로는 문제가 없다. 브라우저도 처리하고 저장도 된다. 그런데 이 주소를 복사해서 어딘가에 붙이면 알아볼 수 없는 긴 문자열이 된다.
제목에서 영문과 숫자만 뽑아 잇는 방식으로 바꿨다.
| 결과 | |
|---|---|
| 처음 | postgres-17이-sqlite를-능가한-지점 |
| 지금 | postgres-17-sqlite |
3. 집에서는 되고 폰에서는 안 됐다
3.1 20초짜리 요청이 끊겼다
밖에서 폰으로 들어가 본문 일부를 AI에게 맡겼다. **"Failed to fetch"**가 났다. 집에서 노트북으로 하면 멀쩡했다.
AI 한 번이 20초 안팎 걸린다. 그동안 연결을 열어 둔 채 기다리는 구조였다. 그런데 폰은 화면이 꺼지거나 다른 앱으로 넘어가면 진행 중이던 요청을 죽인다. 서버에서는 일이 멀쩡히 돌고 있는데 화면만 포기한 것이다.
구조를 바꿨다. 요청하면 번호표만 즉시 돌려주고, 결과는 짧은 조회로 가져간다. 오래 기다리는 연결이 없어졌다.
sequenceDiagram
participant 폰
participant 어드민
폰->>어드민: 이 문단 고쳐줘
어드민-->>폰: 번호표 (즉시)
loop 끝날 때까지
폰->>어드민: 다 됐나요?
어드민-->>폰: 아직 / 결과
end
3.2 고쳤는데 또 났다
며칠 뒤 같은 오류가 다시 났다. 증상이 똑같아서 처음엔 안 고쳐진 줄 알았다.
절반만 고쳐져 있었다. 긴 요청은 없앴는데, 짧은 조회가 한 번 실패하면 전체를 포기하도록 짜여 있었다. 앱을 전환하면 그 순간 진행 중이던 조회 하나가 끊긴다. 그거 하나로 끝나 버린 것이다.
결함이 하나 더 있었다. 결과를 한 번 읽으면 서버에서 지우게 해놨다. 응답이 오는 길에 끊기면 결과가 영영 사라져, 다시 물어본 화면은 "그런 작업 없다"를 받는다.
지금은 조회 실패를 연속 15번까지 견디고, 결과는 읽어도 지우지 않는다.
4. 같은 폰인데 OS마다 달랐다
편집기 화면 위아래에 도구 모음을 고정해 뒀다. 키보드가 올라오면 그 바들이 가려졌다.
안드로이드는 쉽게 풀렸다. 뷰포트 설정 한 줄을 넣으면 키보드가 올라올 때 화면 자체를 줄여 준다. 그래서 고정해 둔 바가 줄어든 화면 안쪽에 그대로 남는다.
iOS 사파리는 그 설정을 보지 않는다. 사파리는 레이아웃 크기를 그대로 둔 채 화면만 위로 밀어 올린다. 웹페이지 입장에서는 아무것도 안 바뀐 것처럼 보이는데, 실제로는 아래쪽이 키보드에 덮여 있다.
그래서 밀려 올라간 만큼을 직접 재서 고정 위치에 더해 준다. 사파리가 아닌 곳에서는 그 값이 0이라 아무 영향이 없다.
| 키보드가 올라오면 | 대응 | |
|---|---|---|
| 안드로이드 크롬 | 화면 크기가 줄어듦 | 뷰포트 설정 한 줄 |
| iOS 사파리 | 크기는 그대로, 화면만 밀림 | 밀린 양을 재서 보정 |
같은 문제가 플랫폼마다 다른 모양으로 나타난다는 걸 여기서 배웠다.
5. 내가 만든 장치에 내가 걸렸다
4편에서 자리 표시 장치를 만들었다. AI가 할 수 없는 일을 지어내지 않고 적어 두게 하고, 하나라도 남아 있으면 발행을 막는 것이다.
그 장치를 설명하는 글을 쓰다가 막혔다. 글 안에 예시를 적어야 했기 때문이다.
[[작업: 무엇이 필요한지 한 줄]]
이걸 본문에 쓰는 순간, 발행 차단이 채우지 않은 자리로 센다. 채울 것이 없는데 영원히 발행되지 않는 글이 됐다.
고치는 건 한 줄이었다 — 코드로 적은 부분은 세지 않는다. 코드 안의 글자는 설명이지 지시가 아니다.
재미있는 건 이 결함이 그 장치를 설명하는 글을 쓰기 전까지는 드러날 수 없었다는 점이다. 기능만 테스트했다면 끝까지 몰랐을 것이다.
6. 공통점
다섯 개를 늘어놓고 보니 하나가 겹쳤다.
| 어떻게 틀렸나 | |
|---|---|
| 1 | 오류는 서버 로그에만, 화면은 예전 것 |
| 2 | 저장도 되고 열리기도 함 |
| 3 | 서버는 멀쩡하고 화면만 포기 |
| 4 | 웹페이지 입장에서는 아무것도 안 바뀜 |
| 5 | 막는 게 정상 동작이라 고장으로 안 보임 |
다섯 개 다 멈추지 않았다. 그래서 오래 걸렸다.
그 뒤로는 실패를 상태로 남기는 쪽으로 만들었다. AI 초안이 실패하면 글이 "초안 요청됨"에 멈춰 있고, 실행 기록에 이유가 남는다. 조용히 지나가지 않는다.
4편에서 적은 작업 폴더 문제도 같은 종류였다. 추천 주제가 엉뚱하게 나왔지, 오류가 난 게 아니었다. 결과가 그럴듯해서 더 늦게 알아챘다.
여기까지가 이 블로그를 만든 이야기다. 일곱 편을 쓰는 동안에도 어드민은 계속 고쳐졌다 — 5번 항목이 그 증거다. 글을 쓰는 일과 도구를 만드는 일이 같이 굴러갔다.

