오류 대신 로그인 페이지를 주는 서버, 세션 만료를 다루는 법

웹 · 앱 개발5분 읽기

무인으로 매일 도는 자동화 프로그램에서 세션 관리는 눈에 잘 안 띄지만 자주 발목을 잡는 문제입니다. 사람이 화면 앞에 있으면 세션이 풀렸을 때 그냥 다시 로그인하면 그만이지만 사람이 없는 상태에서 프로그램이 이걸 스스로 처리하지 못하면 그날 작업 전체가 조용히 실패합니다. 한 통행료 정산 시스템을 연동할 때 이 문제가 특히 까다로웠습니다. 이 서버는 세션이 만료돼도 정직하게 오류를 주지 않고 태연하게 로그인 페이지를 돌려줬기 때문입니다. 이 글은 그런 서버에서 세션 만료를 감지하고 복구하는 설계를 정리했습니다.

만료를 숨기는 서버의 함정

이상적인 서버라면 세션이 만료됐을 때 명확한 신호를 줍니다. 인증이 필요하다는 상태 코드를 돌려주면 프로그램은 그 신호를 보고 다시 로그인하면 됩니다. 그런데 오래된 시스템 중에는 그렇게 동작하지 않는 것이 많습니다. 이 통행료 시스템은 세션이 풀린 상태에서 데이터 요청을 보내면 실패 신호 없이 정상 응답인 것처럼 로그인 화면을 되돌려 줬습니다. 프로그램 입장에서는 요청이 성공한 것처럼 보이지만 정작 내용물은 데이터가 아니라 로그인 페이지인 상황입니다.

이 함정이 위험한 이유는 실패가 성공으로 위장되기 때문입니다. 프로그램이 이걸 눈치채지 못하면 데이터가 없는 응답을 정상 결과로 착각해 빈 자료를 만들거나 엉뚱한 처리를 이어 갑니다. 조용한 실패는 요란한 실패보다 나쁩니다. 요란하게 멈추면 최소한 무언가 잘못됐다는 것을 알 수 있지만 조용히 잘못된 결과를 내면 아무도 모르는 채로 넘어갑니다. 그래서 첫 번째 과제는 이 위장된 응답을 확실하게 알아채는 것이었습니다.

만료를 확실하게 감지하기

로컬에 남은 세션 쿠키의 존재 여부만으로는 만료를 판단할 수 없었습니다. 서버가 세션을 만료시켜도 프로그램이 들고 있는 쿠키는 그대로 남아 있어서 쿠키가 있으니 유효하다고 착각하기 쉬웠습니다. 진짜 판단 기준은 응답의 내용이어야 했습니다. 그래서 응답을 파싱할 때 기대한 데이터 형식이 아니라 로그인 페이지의 특징이 보이면 이를 세션 만료 신호로 삼도록 했습니다. 이 시스템에서는 응답이 정상 데이터 형식으로 파싱되지 않는 것 자체가 만료의 유력한 징후였습니다.

여기서 한 가지 구분이 중요했습니다. 세션 만료로 인한 실패와 서버가 정상적으로 처리한 뒤 돌려준 업무상의 오류는 성격이 다릅니다. 앞의 것은 다시 로그인하면 풀리지만 뒤의 것은 다시 로그인해도 똑같이 실패합니다. 이 둘을 뭉뚱그리면 로그인만 반복하며 시간을 낭비하게 됩니다. 그래서 만료 신호는 전용 예외로 따로 구분해 정상 처리된 서버 오류와 섞이지 않게 했습니다. 무엇이 재시도로 풀리는 문제이고 무엇이 아닌지를 코드가 분명히 아는 것이 핵심입니다.

한 번만 다시 로그인하고 재시도한다

만료를 감지했으면 복구는 단순합니다. 강제로 한 번 다시 로그인해 새 세션을 얻고 실패했던 요청을 다시 보냅니다. 사람이 세션이 풀렸을 때 다시 로그인하고 하던 일을 이어 가는 것과 똑같습니다. 다만 이 재시도를 무한정 반복하게 두면 안 됩니다. 만약 로그인 자체에 문제가 생겨 매번 만료로 되돌아온다면 프로그램은 다시 로그인하고 다시 실패하기를 끝없이 반복하며 서버를 두드리게 됩니다. 이건 프로그램에도 서버에도 해로운 폭주입니다.

그래서 재로그인에 쿨다운을 두었습니다. 직전 로그인으로부터 아주 짧은 시간 안에 또 재로그인이 필요하다면 이는 정상적인 만료 복구가 아니라 무언가 근본적으로 잘못된 상태입니다. 이럴 때는 조용히 반복하는 대신 분명한 오류를 내고 멈추게 했습니다. 만료되면 한 번 다시 로그인해 재시도하되 그래도 곧바로 또 만료된다면 무한 루프에 빠지지 않고 명확한 실패로 끝나는 것입니다. 무인 운영에서는 이렇게 실패의 경계를 분명히 그어 두는 것이 안전합니다.

두 시스템을 각각 다루되 같은 원칙으로

이 프로젝트는 성격이 다른 두 시스템을 함께 연동했는데, 세션 관리에서도 둘을 섞지 않았습니다. 정산 센터와 가상계좌 시스템은 로그인 방식도 응답 형식도 달라서 만료를 감지하는 구체적인 방법도 각기 달랐습니다. 그래서 세션 만료를 나타내는 신호를 시스템별로 따로 두고 한쪽의 만료 처리가 다른 쪽에 얽히지 않도록 분리했습니다. 다만 감지하고 한 번 재로그인해 재시도하되 폭주는 막는다는 큰 원칙은 두 시스템에 똑같이 적용했습니다.

세션 복구는 화려하지 않지만 무인 자동화가 며칠이고 조용히 잘 도는지 아니면 어느 날 갑자기 빈 결과를 내는지를 가르는 지점입니다. 특히 만료를 오류가 아니라 로그인 페이지로 숨기는 레거시 서버에서는 이 위장을 알아채는 것 하나로 안정성이 크게 달라집니다. 이런 세션 관리가 전체 자동화 안에서 어떤 자리를 차지하는지는 레거시 통행료 시스템 역설계 연동 사례에서, 이 서버와 처음 대화를 트는 프로토콜 해석은 Nexacro 레거시 프로토콜 역설계에서 이어집니다.

자주 묻는 질문

서버가 만료를 오류로 알려주지 않으면 어떻게 감지하나요?

응답의 내용을 기준으로 판단합니다. 이 시스템은 만료 시 오류 대신 로그인 페이지를 정상 응답처럼 돌려줬기 때문에 기대한 데이터 형식으로 파싱되지 않고 로그인 페이지의 특징이 보이면 만료로 간주했습니다. 로컬에 남은 쿠키의 존재 여부는 서버 만료와 무관하므로 판단 기준으로 삼지 않습니다.

만료되면 무조건 다시 로그인하면 되지 않나요?

기본적으로는 그렇지만 무한 반복은 막아야 합니다. 만약 로그인 자체에 문제가 있어 매번 곧바로 다시 만료된다면 재로그인을 끝없이 반복하며 서버를 두드리게 됩니다. 그래서 아주 짧은 시간 안에 재로그인이 다시 필요하면 정상 복구가 아니라고 보고 반복 대신 명확한 오류로 멈추게 했습니다.

세션 만료와 업무 오류를 왜 구분하나요?

세션 만료는 다시 로그인하면 풀리지만 서버가 정상 처리한 뒤 돌려준 업무상의 오류는 다시 로그인해도 똑같이 실패합니다. 둘을 구분하지 않으면 풀리지 않을 문제에 대고 로그인만 반복하게 됩니다. 그래서 만료 신호를 전용 예외로 따로 두어 재시도로 풀리는 문제와 아닌 문제를 코드가 분명히 구분하도록 했습니다.

#세션관리#레거시연동#무인운영#재시도#안정성

업무자동화 구축이 필요하신가요?

무료 상담 신청