기술

세션 만료가 화면에 이틀 떠 있었는데 아무도 몰랐습니다

2026.11.018분 읽기

사내 문서 지식그래프 검색 도구 하나가 고객사의 프로젝트 협업 도구에서 글과 첨부 파일을 가져옵니다. 그 협업 도구의 공개 API 로는 필요한 데이터를 가져올 수 없습니다. 사람이 로그인한 세션으로만 데이터에 접근할 수 있습니다. 그래서 세션이 끊기면 수집이 오류 없이 멈춥니다.

9월 21일에 로그인해 만든 세션이 9월 28일에 만료됐습니다. 첨부 수집이 이틀 동안 멈춰 있었고, 아무도 몰랐습니다. 이상한 점은 따로 있었습니다. 그 도구의 홈 화면에는 이틀 내내 '세션 만료'라는 문구가 떠 있었습니다. 사람이 그 화면을 열어 보지 않았을 뿐입니다.

인증이 만료돼 연동이 알림 없이 멈춘 일은 전에도 있었습니다. 그때는 갱신을 맡은 쪽이 없는 것이 문제였고, 이번 글은 알림을 어떻게 설계했는지에 무게를 둡니다.


화면에 떠 있는 상태는 알림이 아닙니다

처음에는 화면에 만료 표시가 있으니 감시는 된다고 생각했습니다. 이번 일로 그 생각이 틀렸다는 것이 드러났습니다. 화면의 상태는 사람이 보러 와야 보입니다. 알림은 사람에게 찾아갑니다. 둘은 정보의 내용이 같아도 전달되는 방향이 반대입니다.

배치·수집·외부 연동처럼 멈춰도 사용자 화면이 바로 깨지지 않는 작업은 특히 그렇습니다. 상태 화면만 있으면 누군가 우연히 들어가 보기 전까지 멈춘 사실이 드러나지 않습니다. 이번에는 그 우연이 이틀 동안 오지 않았습니다.

화면에 표시된 세션 만료 상태는 사람이 보러 와야 보이고, 알림은 사람에게 직접 간다는 차이를 비교한 그림

살아 있는지만 확인하는 감시도 같은 빈틈을 남깁니다. 멈췄는데 아무 알림도 없던 사례를 따로 정리한 적이 있습니다.


자동 갱신이 되는지부터 시험했습니다

알림보다 먼저 떠오른 답은 자동 갱신이었습니다. 브라우저에는 유효 기간이 1년인 장기 쿠키가 여러 개 있었습니다. 이것만 있으면 세션을 다시 살릴 수 있지 않을까 싶었습니다. 짐작으로 판단하지 않고, 쿠키를 세 가지 조합으로 나눠 같은 API 에 직접 요청해 봤습니다.

보낸 쿠키

결과

전체 쿠키

로그인 상태

세션 쿠키 하나만 뺀 나머지 전부

로그아웃

1년짜리 장기 쿠키 세 개만

로그아웃

결과는 분명했습니다. **세션 쿠키 하나가 전부였습니다.** 1년짜리 장기 쿠키가 모두 있어도 세션은 살아나지 않았습니다. '자동 로그인' 체크박스에 해당하는 쿠키도 있었지만, 화면의 체크 상태를 기억할 뿐 자격증명이 아니었습니다.

서버가 쿠키를 새로 내려주는지도 확인했습니다. 응답마다 갱신되는 것은 로드밸런서가 붙이는 쿠키뿐이었습니다. 세션 쿠키는 다시 발급되지 않았습니다. 세션을 계속 사용해도 남은 시간이 늘어나지 않는다는 뜻입니다.

쿠키를 세 가지 조합으로 나눠 요청한 결과, 세션 쿠키 하나가 빠지면 장기 쿠키가 있어도 로그아웃된다는 대조표


남은 선택지를 비교했습니다

장기 쿠키로 되살리는 방법이 실측으로 막히자 선택지는 아래처럼 정리됐습니다. 비교 기준은 사람이 직접 갱신하는 비용이었습니다. 다시 로그인하는 데 일주일에 한 번, 3분이면 됩니다.

방법

판단

장기 쿠키로 세션 되살리기

불가. 세션 쿠키 하나가 전부라는 것을 확인했습니다

비밀번호를 기계에 두고 로그인 자동화

보류. 얻는 것은 주 1회 3분인데 비밀번호를 기계에 두는 위험이 훨씬 큽니다

로그인된 브라우저 프로필을 남겨 클릭만으로 통과

확인하지 않았습니다. 되면 갱신이 명령 하나가 되지만, 로그인된 프로필을 디스크에 두는 것이라 위험의 성격은 위와 같습니다

사람이 갱신하고 기계는 시점만 알림

채택

에이전트가 조작하는 브라우저에서 세션 값을 읽어 오는 방법도 살펴봤습니다. 브라우저 컨텍스트에 접근할 수단이 없어 HttpOnly(스크립트에서 읽을 수 없게 표시된) 세션 쿠키를 가져오지 못했습니다. 세 번째 방법은 버리지 않고, 다음 예고가 올 때 시험해 보기로 남겼습니다.


알림은 두 경로로 나눴습니다

기존 감시 스크립트의 대상 목록에 세션 항목을 추가했고, 남은 날을 계산하는 작은 스크립트를 새로 만들었습니다. 감시 대상은 8개가 됐습니다. 세션 항목은 상태에 따라 두 경로로 나눴습니다.

장애 — 세션 파일이 없거나 이미 만료됐을 때. 기존 장애 경로를 그대로 따릅니다(처음 한 번 알림, 30분마다 다시 알림, 복구되면 복구 알림)

예고 — 남은 날이 2일 이하일 때. 장애 경로와 별도로 하루 한 번만 보냅니다

알림 본문에는 갱신에 필요한 명령 두 줄을 그대로 넣었습니다. 알림을 받은 사람이 무엇을 해야 하는지 찾아보지 않아도 되게 했습니다.

세션 상태에 따라 장애 경로와 예고 경로를 나누고, 예고는 정상 보고와 분리해 하루 한 번만 보내는 알림 흐름도


설계에서 일부러 뺀 것 두 가지

이 작업에서 가장 오래 고민한 것은 무엇을 넣을지가 아니라 무엇을 빼는지였습니다.

첫째, 예고를 '다 정상' 하루 보고에 함께 보내지 않았습니다. 그 보고는 감시 대상 중 하나라도 멈춰 있으면 나가지 않습니다. 하필 다른 문제가 있는 날 예고가 그 보고와 함께 빠지면, 세션은 아무 알림 없이 만료됩니다. 예고는 실패 보고와 다른 경로로 보내야 정상이 아닌 날에도 도착합니다.

둘째, 예고에는 30분마다 다시 알리는 규칙을 쓰지 않았습니다. 이 세션을 갱신할 수 있는 것은 사람 한 명뿐입니다. 남은 이틀 동안 30분마다 울리면 96번입니다. 그 정도로 울리면 사람은 알림을 끕니다. 알림이 꺼진 뒤에는 진짜 장애도 같이 묻힙니다. 기계가 스스로 복구하는 일이면 자주 울려도 되지만, 사람이 복구하는 일이면 하루 한 번이 상한이라고 판단했습니다.


남은 날은 추정이라고 적어 뒀습니다

세션 쿠키에는 만료일이 없습니다. 그래서 파일만 봐서는 서버가 언제 세션을 끊을지 알 수 없습니다. 남은 날은 만료일이 있는 인증 쿠키 중 가장 이른 것을 기준으로 계산했습니다. 실측으로는 로그인 후 7일이었고, 실제로 끊긴 날과 맞았습니다. 그래도 이 값은 상한에 가까운 추정치로 기록해 뒀습니다. 상대 서비스가 기간을 줄이면 예고가 만료 뒤에 도착할 수 있기 때문입니다.

추가한 뒤 상태 파일에는 세션 항목이 정상으로 기록됐습니다. 남은 날이 6일이라 예고 값은 비어 있었고, 이것이 맞는 동작입니다. 만료 예정일은 10월 7일, 예고 예정일은 10월 5일로 계산됐습니다.


이 설계가 맞지 않는 경우

기계가 갱신할 수 있는 자격증명(장기 API 키·서비스 계정)이면 자동 갱신이 정답입니다. 알림은 갱신이 실패했을 때만 있으면 됩니다

받는 사람이 여럿이고 교대 근무가 있으면 30분 반복 알림이 오히려 맞습니다. 반복을 뺀 근거는 복구할 사람이 한 명이라는 조건입니다

예고 문턱 2일은 갱신 3분에 비하면 넉넉하지만, 휴가나 출장이 끼면 부족합니다. 사람의 일정도 알림 설계의 조건입니다


점검해 볼 것

멈춰도 화면이 바로 깨지지 않는 수집·연동이 상태 표시만으로 감시되고 있지 않은가

자동화를 접었다면 왜 안 되는지 실측 근거를 남겼는가

만료 예고가 정상 보고와 같은 경로로 묶여 있지 않은가

반복 알림 주기가 복구하는 주체(기계인지 사람인지)에 맞는가

만료일을 모르는 자격증명의 남은 기간을 추정이라고 적어 두었는가

쿠키 세 조합을 대조하는 데는 30분이면 충분했습니다. 그 30분 덕분에 자동 갱신을 접은 것이 짐작이 아니라 판단으로 남았고, 다음에 같은 생각이 들어도 다시 시험할 필요가 없습니다. 지금은 일주일에 한 번, 이틀 전에 예고가 오면 3분 들여 다시 로그인합니다.

#세션#세션만료#알림설계#운영감시#쿠키#자동화한계