설명
백엔드 refactor/login-agreement 브랜치에서 Google 로그인 응답에 SIGNUP_REQUIRED 분기와 임시 signupToken, 가입 완료 엔드포인트 POST /auth/google/signup이 추가됐다.
프론트는 이를 사용해 약관 동의 시점을 로그인 전 → 신규 가입자 한정으로 로그인 후로 옮긴다.
요구사항 (UX)
- 로그인 화면: 약관 UI 없음. Google 로그인 버튼만 노출.
- 콜백 처리: Google 인증 후 백엔드 응답에 따라 분기
- 기존 회원, 약관 최신 → 즉시 로그인 완료
- 신규 가입자 → 약관 동의 페이지로 리다이렉트
- 기존 회원, 약관 갱신 필요 → 약관 재동의 안내 → 동의 후 다시 로그인 시도
- 약관 동의 페이지(신규 가입): 약관 표시 + 전체 동의 → 가입 완료 → 로그인 상태로 전환
백엔드 API 스펙 (이번 브랜치 기준)
POST /auth/google/login
요청: { "code": "..." } (약관 동의 여부는 더 이상 필수로 함께 보낼 필요 없음, 보내려면 agreementsAccepted: true)
응답 분기:
| 케이스 |
상태 |
body |
쿠키 |
| 기존 회원 + 약관 최신 |
200 |
없음 |
access/refresh 발급 |
기존 회원 + 약관 변경됨 + agreementsAccepted=true |
200 |
없음 |
access/refresh 발급 |
| 기존 회원 + 약관 변경됨, 동의 없음 |
401 AGREEMENTS_REACCEPTANCE_REQUIRED |
에러 |
없음 |
| 신규 + 동의 없음 |
200 |
{ "status":"SIGNUP_REQUIRED", "signupToken":"...", "expiresInSeconds":600 } |
없음 |
신규 + agreementsAccepted=true |
200 |
없음 |
access/refresh 발급 (즉시 가입) |
POST /auth/google/signup (신규)
요청: { "signupToken": "...", "agreementsAccepted": true }
- 200 → 쿠키 발급, body 없음 (가입 완료)
- 400
AGREEMENTS_NOT_ACCEPTED → 동의 누락/false
- 401
GOOGLE_SIGNUP_TOKEN_NOT_FOUND → 토큰 없음/만료/재발급으로 무효화/형식 오류
GET /api/agreements/current (변경 없음 / 이미 사용 중)
약관 동의 페이지에서 사용. 인증 불필요. contentFormat=MARKDOWN.
POST /api/users/me/agreements (변경 없음 / 이미 사용 중)
로그인된 상태의 재동의용. 이번 흐름에선 사용 안 함.
알아둘 점
signupToken은 opaque UUID, TTL 10분. 값에서 의미를 추론하지 말 것, 영구 저장 금지(메모리/sessionStorage 권장).
- 같은 Google 계정으로 로그인을 다시 시도하면 이전 signupToken은 즉시 무효화됨 (마지막 시도만 유효). 약관 화면을 띄워둔 채 다른 탭/창에서 재로그인하면 가입 완료가 실패할 수 있음 — 그 경우
GOOGLE_SIGNUP_TOKEN_NOT_FOUND(401)로 떨어지므로 재로그인 안내가 필요.
expiresInSeconds(600초) 만료 후에도 동일하게 GOOGLE_SIGNUP_TOKEN_NOT_FOUND로 처리됨.
- 신규 가입자가 첫 로그인 요청에
agreementsAccepted=true를 같이 보내면 백엔드는 SIGNUP_REQUIRED를 거치지 않고 즉시 가입한다. 이번 UX 의도(약관을 로그인 후로 옮기기)대로 가려면 신규 흐름에선 agreementsAccepted를 보내지 않는다.
- 기존 회원 재동의 흐름:
AGREEMENTS_REACCEPTANCE_REQUIRED(401)가 떨어졌을 때, 프론트는 약관 화면 → 동의 → 다시 Google 로그인 시작(이번엔 agreementsAccepted=true 포함)으로 처리. (로그인 안 된 상태라 POST /api/users/me/agreements는 사용 불가)
signupToken/응답 분기 처리는 BFF route handler가 백엔드 응답(상태코드 + body)을 그대로 흘려보낼 수 있어야 함 — 현재 POST /api/auth/google route는 body 패스스루 + Set-Cookie 전달이라 큰 변경은 없지만, 200 + JSON body 케이스가 새로 생긴다는 점만 유의.
POST /auth/google/signup도 동일하게 쿠키 패스스루 BFF route가 필요함.
브랜치 정책
- 이 변경은 백엔드
refactor/login-agreement 브랜치 전용. main, dev 어디에도 머지되어 있지 않다.
- 백엔드는 양측 합의 전까지
main/dev에 머지하지 않는다. 프론트 작업 완료 + 함께 확인된 시점에만 통합 반영.
- 프론트 작업도 별도 브랜치에서 진행하고, 백엔드 통합 시점이 확정될 때까지 프론트
dev/main에 머지하지 말 것.
실행 경로 (백엔드 띄우기)
cd <백엔드 레포 경로>
git fetch origin
git checkout refactor/login-agreement
git pull origin refactor/login-agreement
docker compose --env-file .env.dev \
-f compose.db.dev.yaml -f compose.app.dev.yaml up -d --build
docker compose --env-file .env.dev \
-f compose.db.dev.yaml -f compose.app.dev.yaml down
- 앱:
http://localhost:8080
- Swagger:
http://localhost:8080/swagger-ui/index.html
- PostgreSQL
5433, MongoDB 27017, Redis 기본 포트
main은 약관 엔드포인트 자체가 없고, dev는 약관은 있지만 SIGNUP_REQUIRED 흐름이 없다. 반드시 refactor/login-agreement 브랜치를 띄울 것.
참고
- 백엔드 설계:
docs/superpowers/specs/2026-06-08-google-signup-token-design.md, docs/superpowers/specs/2026-06-08-backend-agreements-design.md
- 에러 코드:
AGREEMENTS_NOT_ACCEPTED, AGREEMENTS_REACCEPTANCE_REQUIRED, GOOGLE_SIGNUP_TOKEN_NOT_FOUND, AGREEMENT_CONFIGURATION_INVALID
설명
백엔드
refactor/login-agreement브랜치에서 Google 로그인 응답에SIGNUP_REQUIRED분기와 임시signupToken, 가입 완료 엔드포인트POST /auth/google/signup이 추가됐다.프론트는 이를 사용해 약관 동의 시점을 로그인 전 → 신규 가입자 한정으로 로그인 후로 옮긴다.
요구사항 (UX)
백엔드 API 스펙 (이번 브랜치 기준)
POST /auth/google/login요청:
{ "code": "..." }(약관 동의 여부는 더 이상 필수로 함께 보낼 필요 없음, 보내려면agreementsAccepted: true)응답 분기:
agreementsAccepted=trueAGREEMENTS_REACCEPTANCE_REQUIRED{ "status":"SIGNUP_REQUIRED", "signupToken":"...", "expiresInSeconds":600 }agreementsAccepted=truePOST /auth/google/signup(신규)요청:
{ "signupToken": "...", "agreementsAccepted": true }AGREEMENTS_NOT_ACCEPTED→ 동의 누락/falseGOOGLE_SIGNUP_TOKEN_NOT_FOUND→ 토큰 없음/만료/재발급으로 무효화/형식 오류GET /api/agreements/current(변경 없음 / 이미 사용 중)약관 동의 페이지에서 사용. 인증 불필요.
contentFormat=MARKDOWN.POST /api/users/me/agreements(변경 없음 / 이미 사용 중)로그인된 상태의 재동의용. 이번 흐름에선 사용 안 함.
알아둘 점
signupToken은 opaque UUID, TTL 10분. 값에서 의미를 추론하지 말 것, 영구 저장 금지(메모리/sessionStorage 권장).GOOGLE_SIGNUP_TOKEN_NOT_FOUND(401)로 떨어지므로 재로그인 안내가 필요.expiresInSeconds(600초) 만료 후에도 동일하게GOOGLE_SIGNUP_TOKEN_NOT_FOUND로 처리됨.agreementsAccepted=true를 같이 보내면 백엔드는 SIGNUP_REQUIRED를 거치지 않고 즉시 가입한다. 이번 UX 의도(약관을 로그인 후로 옮기기)대로 가려면 신규 흐름에선agreementsAccepted를 보내지 않는다.AGREEMENTS_REACCEPTANCE_REQUIRED(401)가 떨어졌을 때, 프론트는 약관 화면 → 동의 → 다시 Google 로그인 시작(이번엔agreementsAccepted=true포함)으로 처리. (로그인 안 된 상태라POST /api/users/me/agreements는 사용 불가)signupToken/응답 분기 처리는 BFF route handler가 백엔드 응답(상태코드 + body)을 그대로 흘려보낼 수 있어야 함 — 현재POST /api/auth/googleroute는 body 패스스루 + Set-Cookie 전달이라 큰 변경은 없지만, 200 + JSON body 케이스가 새로 생긴다는 점만 유의.POST /auth/google/signup도 동일하게 쿠키 패스스루 BFF route가 필요함.브랜치 정책
refactor/login-agreement브랜치 전용.main,dev어디에도 머지되어 있지 않다.main/dev에 머지하지 않는다. 프론트 작업 완료 + 함께 확인된 시점에만 통합 반영.dev/main에 머지하지 말 것.실행 경로 (백엔드 띄우기)
http://localhost:8080http://localhost:8080/swagger-ui/index.html5433, MongoDB27017, Redis 기본 포트참고
docs/superpowers/specs/2026-06-08-google-signup-token-design.md,docs/superpowers/specs/2026-06-08-backend-agreements-design.mdAGREEMENTS_NOT_ACCEPTED,AGREEMENTS_REACCEPTANCE_REQUIRED,GOOGLE_SIGNUP_TOKEN_NOT_FOUND,AGREEMENT_CONFIGURATION_INVALID