- 발행일
로그인이 계속 풀려서 조건을 바꿨다 — 원인은 setState 바로 다음 줄에 있었다
로그인이 계속 풀려서 조건을 바꿨다
이 글은 2026년 9월에 당시 커밋 이력을 다시 보며 정리한 것입니다. 날짜는 작업한 날 기준입니다.
2020년 11월, 대학 4학년 종합설계로 홈트레이닝 웹 큐피트를 만들고 있었습니다. 편입하고 처음 해 보는 팀 프로젝트였고, 프런트는 거의 제가 맡았어요. 로그인·회원가입·마이페이지·마일리지 화면이 제 몫이었습니다.
11월 14일 밤에 마일리지 화면을 붙였습니다. 로그인하면 마일리지 버튼이 생기고, 누르면 "○○님의 마일은 ○○ 마일 입니다"가 뜨는 화면이에요. 그런데 로그인을 했는데도 버튼을 누르면 "로그인 해주세요" 가 뜨고 로그인 화면으로 튕겼습니다. 다시 로그인해도 같았어요.
새벽 2시의 수정
11월 15일 02:05 커밋(fb6790c)의 제목이 "로그인이 계속 풀려서 다르게 처리"입니다. 바뀐 건 Mileage.js 네 줄이에요.
- else {
+ //로그인이 계속 풀리는 문제가 생겨서 이렇게 처리 함
+ else if (!this.state.userid) {
alert("로그인 해주세요")
window.location.href="/login"
}
마일리지 응답이 없으면 무조건 로그인 화면으로 보내던 걸, userid 쿠키까지 없을 때만 보내게 바꿨습니다. userid는 쿠키에 살아 있었으니 이제 메시지는 안 뜹니다. 마일리지 값도 안 뜨지만요.
그날 확인한 건 거기까지였습니다. "로그인 해주세요"가 안 뜨니 고쳐진 걸로 봤어요.
원인은 로그인 화면에 있었다
이 글을 쓰려고 Login.js를 다시 열었습니다. 11월 11일 첫 커밋(517f3e0)부터 저장소의 마지막 커밋까지, 필드 이름은 바뀌었지만 이 순서는 그대로예요.
if (response.data.login === "True") {
this.setState({
token: response.data.token,
userid: response.data.userid,
level: response.data.level,
login: response.data.login
})
// ... expires 계산
cookie.save("userid", this.state.userid, cookieOptions);
cookie.save("token", this.state.token, cookieOptions);
setState를 부르고 바로 다음 줄에서 this.state.token을 읽어 쿠키에 넣습니다. 클래스 컴포넌트의 setState는 이 자리에서 바로 반영되지 않으니, 저장되는 건 초기값인 빈 문자열이에요. 토큰 쿠키가 늘 비어 있었던 겁니다.
그런데 userid는 살아남았습니다. 로그인 폼에 입력한 값이 이미 this.state.userid에 들어 있었으니까요. 그래서 "로그인은 된 것 같은데 마일리지만 안 되는" 모양이 됐습니다. 마일리지 화면은 Authorization 헤더에 그 빈 토큰을 실어 보냈고, 서버가 마일리지를 안 주니 else로 떨어졌어요.
정리하면 로그인이 풀린 게 아니라 처음부터 토큰이 저장된 적이 없었습니다. 제가 바꾼 조건은 그 사실을 화면에서만 가렸어요.
같은 자리를 세 번 만졌다
커밋을 시간순으로 보면 그날 밤 Mileage.js를 세 번 고쳤습니다.
| 시각 | 커밋 | 바뀐 것 |
|---|---|---|
| 11/14 23:36 | 014920e "마일리지 1차" | 요청에 Authorization 헤더 추가, else if(!this.state.userid) 분기 |
| 11/14 23:59 | de1bda3 "마일리지 2차" | 요청을 클릭 핸들러에서 생성자로 옮기고 분기를 else로 |
| 11/15 02:05 | fb6790c | 다시 else if (!this.state.userid), 주석 추가 |
1차에 있던 조건을 2차에서 없앴다가 3차에서 되돌린 거예요. 그 사이에 토큰이 왜 없는지는 한 번도 안 봤습니다. 요청이 언제 나가는지(클릭 때인지 화면 열릴 때인지)를 바꾸는 데 시간을 썼어요.
곁가지로, 쿠키 옵션에 httponly: false를 적어 뒀는데 브라우저 자바스크립트로 심는 쿠키에 그 옵션은 의미가 없고, react-cookie와 react-cookies가 둘 다 설치돼 있었습니다. 쿠키를 읽고 쓰는 코드는 전부 react-cookies였고, react-cookie는 index.js에서 앱을 감싸는 CookiesProvider 한 줄에만 쓰였어요. 그 Provider가 없어도 react-cookies는 동작하니 사실상 껍데기였습니다.
검증
그날 확인한 것:
- 로그인 뒤 마일리지 버튼을 눌러 "로그인 해주세요"가 안 뜨는 것. 마일리지 값이 비어 있는 건 그대로였습니다.
이 글을 쓰며 git show로 확인한 것:
Login.js의setState직후this.state.token읽기가 첫 커밋(517f3e0)부터 저장소 마지막 커밋(7fc0343, 11/22)까지 그대로인 것.Mileage.js가 11/14~15 세 커밋에서 분기를else if→else→else if로 오간 것.package.json에react-cookie·react-cookies가 같이 있고, 소스에서 import되는 건react-cookies뿐인 것.- 2023년 12월에 쓴 이력서에는 이 프로젝트를 "프런트 전담, 담당은 회원 관리·마이페이지·로그인·로그아웃·식단 조절·운동 페이지·옷 페이지"로 적었는데, 저장소에서 그 파일들의 저자가 전부 저인 것과 맞습니다. 다만 이력서는 개발 인원을 프런트 1명이라 적었고, 저장소에는 다른 팀원의 커밋이 46개 있어요(홈 화면 파일을 GitHub 웹에서 지우고 다시 올린 42개와 4개). 코드를 쓴 사람과 올린 사람이 갈린 흔적입니다.
남은 것 · 한계
- 토큰이 실제로 비어 있었는지는 코드로 추론한 것입니다. 당시 브라우저에서 쿠키를 열어 본 기록이 없어요.
setState의 동작과 코드 순서로 보면 빈 값이 저장됐다고 보는 게 맞지만, 서버가 토큰 없이도 마일리지를 줬을 가능성까지는 확인할 수 없습니다. - 고치지 않았습니다. 저장소 마지막 커밋까지
Login.js는 같은 모양이에요. 발표까지 마일리지 화면이 어떻게 동작했는지는 커밋에 남아 있지 않습니다. - 이 유형은 그 뒤로도 반복됐습니다. 2024년 TripTune에서는 마운트된 적 없는 훅이 401을 처리하고 있었고, 2026년에야 로그인 풀림의 계보를 401 처리 한 곳으로 모으면서 원인부터 보게 됐어요. 증상을 조건으로 덮은 첫 기록이 이 커밋입니다.
관련 글: 큐피트 — 대학 졸업작품으로 만든 홈트레이닝 웹 · Next.js 안에 react-router-dom이 두 달 있었다 · 로그인이 자꾸 풀리던 서비스 — 401 처리를 한곳으로 모으기까지 · 카테고리 하나에 폴더 하나 — 복붙 열한 벌