인증 만료를 프론트가 판단하지 않기로 했다 — 서버 만료일 기준 재인증 플로우
임직원·법인 회원의 인증 만료를 프론트에서 계산하면, 서버 데이터와 어긋나는 순간 신뢰할 수 없는 판정이 된다. 만료 시점 자체는 서버가 내려주고, 프론트는 현재 시각과 비교만 하도록 역할을 나눈 재인증 플로우를 설계한 과정.
관련 프로젝트: B2C 리뉴얼 — 멤버십 인증·분석 재설계
임직원·법인 회원은 일반 회원과 다른 인증이 필요했다. 회사명·도메인으로 신원을 확인하고, 일정 기간이 지나면 만료시켜 재인증을 요구한다. 여기서 제일 먼저 부딪힌 질문은 암호화 방식도, UI 흐름도 아니었다. "만료됐다"는 판정을 어디서 내릴 것인가였다.
문제 — 만료 계산을 프론트에 두면 두 개의 진실이 생긴다
가장 손쉬운 방법은 프론트가 인증 승인 시점을 저장해두고, "그로부터 N개월이 지났으면 만료"라고 직접 계산하는 것이다. 하지만 이 방식은 조용히 위험하다.
- 서버의 회원 상태와 프론트의 계산 결과가 어긋날 수 있다. 정책이 바뀌거나, 서버 쪽에서 개별 회원의 만료일을 수동으로 조정하면 프론트의 계산식은 즉시 낡은 값이 된다.
- "판단 로직"이 두 곳에 존재하게 된다. 서버는 회원 데이터를 갖고 있고, 프론트는 별도로 만료 여부를 계산한다. 둘이 다른 답을 낼 가능성이 항상 열려 있다.
인증 만료 같은 민감한 판정에서 "두 개의 진실"은 결국 하나가 사고로 이어진다.
접근 — 판정은 서버가, 비교는 프론트가
역할을 명확히 나눴다. 만료 시점(employeeExpireDate) 자체는 서버가 응답으로 내려준다. 프론트는 그 값을 받아 현재 시각과 비교하는 것 딱 하나만 한다.
// 개념 스케치 — 역할 분리 (실제 구현 아님)
function isExpired(employeeExpireDate) {
return new Date() > new Date(employeeExpireDate);
}계산식이 아니라 비교식이라는 게 핵심이다. "언제 만료되는가"를 결정하는 로직은 전부 서버에 있고, 프론트는 그 결정을 그대로 신뢰해 시각만 비교한다. 정책이 바뀌어도, 개별 회원의 만료일이 수동 조정돼도, 서버가 내려주는 값만 최신이면 프론트는 항상 맞는 답을 낸다.
만료 이후의 갈림길
만료됐다고 판정되면 그 다음이 또 문제였다. 무조건 로그아웃시키면 사용성이 나쁘고, 그렇다고 계속 임직원 혜택을 주면 정책 위반이다. 그래서 만료 시점에 갈림길을 뒀다.
- 재인증 — 회사명·도메인을 다시 확인해 임직원 상태를 갱신
- 일반회원 전환 — 재인증을 원하지 않으면 임직원 혜택 없이 일반 회원으로 계속 이용
"나중에 하기"를 선택한 경우의 분기도 별도로 다뤄, 매번 로그인할 때마다 재인증을 강제하지 않으면서도 만료 상태 자체는 계속 유지되게 했다.
정리
| 구분 | before(프론트 계산) | after(서버 판정 + 프론트 비교) |
|---|---|---|
| 만료 시점 결정 | 프론트가 승인일 + 기간으로 계산 | 서버가 employeeExpireDate로 응답 |
| 정책 변경 시 | 프론트 계산식도 함께 수정 필요 | 서버 응답만 바뀌면 프론트는 자동 반영 |
| 판단 로직 위치 | 서버·프론트 두 곳 | 서버 한 곳 (프론트는 비교만) |
| 회원 개별 조정 | 프론트 계산과 어긋날 위험 | 서버 값이 곧 진실이라 어긋날 일 없음 |
"언제 만료되는가"와 "지금 만료됐는가"는 다른 질문이다. 전자는 도메인 정책이라 서버가 답할 문제고, 후자는 그 답을 현재 시각과 대조하는 순수 비교다. 이 둘을 한 곳(프론트)에 몰아넣지 않은 것이, 정책이 바뀌어도 프론트 코드를 건드리지 않아도 되는 이유였다.