로그인 통합과 ERP/포탈 권한 분리 (세션 유지)
한 번 로그인하면 모든 모듈을 자유롭게 오갈 수 있어야 한다 — 목표는 단순했습니다. 그런데 인증 상태를 어디에, 어떤 모양으로 저장할지를 처음에 못 박지 않자, 서로 다른 모양의 인증 저장소가 두 벌 생겼습니다. 둘 다 “로그인됨”이라 멀쩡해 보였지만, 한 영역에서 다른 영역으로 넘어가는 경계에서 그 미세한 어긋남이 로그인 튕김 버그로 돌아왔습니다. 토큰은 멀쩡한데 로그인 화면으로 튕긴 것입니다.
용어부터 — SSO와 두 종류의 토큰
섹션 제목: “용어부터 — SSO와 두 종류의 토큰”한 번 로그인, 끝까지 유지 — 의도된 트레이드오프
섹션 제목: “한 번 로그인, 끝까지 유지 — 의도된 트레이드오프”사내 업무 앱의 UX 목표는 분명했습니다. 출근해서 한 번 로그인하면, 하루 종일 다시 묻지 않고 쓰게 하자. 그래서 인증을 짧은 수명의 access 토큰과 매우 긴 수명의 refresh 토큰으로 나눴습니다. refresh는 사실상 로그아웃 전까지 유지하고, access는 짧게 둬서 로그아웃의 즉시성을 보완합니다 — 로그아웃하면 곧 만료될 짧은 access 덕분에, 긴 refresh를 쓰면서도 “로그아웃은 빨리 먹히게” 만든 것입니다.
이건 보안과 내부 UX 사이의 의도된 절충입니다. 긴 refresh는 편하지만 노출 창이 커지고, 짧은 access는 안전하지만 자주 갱신해야 합니다. 둘의 균형점을 “내부 직원용 업무 앱”이라는 맥락에 맞춰 잡은 것입니다.
진짜 함정 — 인증 상태가 두 모양으로 갈라졌다
섹션 제목: “진짜 함정 — 인증 상태가 두 모양으로 갈라졌다”진짜 함정은 토큰 수명이 아니라 인증 상태를 담는 그릇이었습니다. 포탈 영역과 전자결재 영역이 각자 편한 방식으로 인증 정보를 브라우저에 저장했습니다. 한쪽은 평평한 모양으로, 다른 한쪽은 상태 관리 라이브러리가 한 겹 감싼 모양으로 — 같은 사용자 정보인데 저장 키도 다르고 구조도 달랐습니다.
겉보기엔 둘 다 “로그인됨”이라 문제없어 보였습니다. 그런데 두 영역을 오갈 때, 한쪽이 다른 쪽의 그릇을 못 알아보는 경계가 있었습니다. 그 경계를 넘으면 토큰이 멀쩡한데도 로그인 화면으로 튕겼습니다. 실제로 이 튕김 현상을 근본 해소한 수정이 2026년 6월 12일에 있었는데, 원인은 토큰 만료가 아니라 두 저장소의 키·모양 불일치였습니다.
| ”로그인 통합”에 대한 통념 | 실제로 중요한 것 |
|---|---|
| 토큰만 공유하면 된다 | 토큰을 담는 그릇(키·구조)을 통일해야 한다 |
| 둘 다 “로그인됨”이면 OK | 영역 경계에서 서로의 그릇을 읽을 수 있어야 OK |
| 튕기면 토큰이 만료된 것 | 토큰은 멀쩡하고 그릇 모양이 안 맞을 수 있다 |
| 저장소는 영역마다 편한 대로 | ”누가 정본인가”를 하나로 정해야 한다 |
왜 이런 버그는 늦게 발견되나
섹션 제목: “왜 이런 버그는 늦게 발견되나”이 종류의 버그가 특히 까다로운 건, 대부분의 경로에서는 멀쩡하기 때문입니다. 한 영역 안에서만 움직이면 자기 그릇만 읽으니 아무 문제가 없습니다. 어긋남은 오직 “한 영역 → 다른 영역”이라는 특정 경계를 건널 때만 드러납니다. 그래서 일반적인 로그인 테스트는 통과하고, 실제로 두 영역을 오가는 사용 흐름에서만 재현됩니다.
| 사용 흐름 | 결과 | 왜 |
|---|---|---|
| 포탈 안에서만 이동 | 정상 | 자기 그릇만 읽음 |
| 전자결재 안에서만 이동 | 정상 | 자기 그릇만 읽음 |
| 포탈 → 전자결재 경계 통과 | 로그인으로 튕김 | 상대 그릇 모양을 못 읽어 “인증 안 됨”으로 오해 |
이런 버그는 “토큰 만료겠지”라는 잘못된 가설로 시간을 잡아먹기 쉽습니다. 토큰 수명을 늘려 봐도 안 고쳐지는데, 그건 애초에 만료 문제가 아니기 때문입니다. 진짜 원인(그릇 모양 불일치)에 도달하려면, “토큰은 멀쩡한가?”를 먼저 확인하는 규율이 필요했습니다.
바로잡기 — 단일 권위 + 관용적 읽기
섹션 제목: “바로잡기 — 단일 권위 + 관용적 읽기”해법은 두 가지였습니다.
- 단일 권위를 정한다. 인증 상태의 정본을 어느 한쪽으로 정하고, 다른 쪽은 그 정본에서 파생된 캐시로 취급합니다. “둘 다 정본”이면 둘이 어긋날 수 있지만, “하나는 정본, 하나는 캐시”면 어긋날 자리 자체가 없어집니다.
- 읽는 쪽을 너그럽게 만든다. 인증 상태를 읽는 코드가 두 모양을 모두 해석할 수 있게 합니다. 어느 그릇으로 들어와도 같은 사용자 정보를 꺼낼 수 있으면, 경계에서 오해가 생기지 않습니다.
처음에 못 박았어야 할 것
섹션 제목: “처음에 못 박았어야 할 것”되돌아보면, 로그인 통합을 설계할 때 가장 먼저 정했어야 할 건 토큰 수명이 아니라 인증 상태의 저장 규약이었습니다. 키 이름, 데이터 구조, 그리고 “어느 쪽이 정본이고 어느 쪽이 캐시인가”를 처음에 하나로 정해 뒀다면, 두 모양으로 갈라지지도 않았고 경계 튕김 버그도 없었을 것입니다. 영역이 둘 이상이면, 그 경계는 설계 단계에서 명시적으로 다뤄야 하는 1급 대상이지 나중에 발견할 사고 지점이 아닙니다.
이 글은 SL.AIMS를 만들며 겪은 현장 회고 중 하나입니다. 전체 그림은 〈사례연구: SL.AIMS〉에, 관련 글은 〈메뉴/기능 권한 설계를 초기에 안 한 것〉에 있습니다.