[fix] solution/frontend: 2단계에서 로그인을 요구하지 않는다

로그인은 에디터 진입에서 한 번 받는 것이 이 앱의 흐름인데, 장소 API 가 전부 토큰을 요구해서
(place.py) 2단계가 로그인 벽이 되어 있었다. 토큰이 없으면 서버를 부르지 않고 입력한 상호·주소로
신원을 세워 3단계로 넘어간다. 검증은 로그인 뒤에 다시 할 수 있다.
This commit is contained in:
Mina Choi 2026-09-02 09:20:55 +09:00
parent 139a672138
commit 22b7623aeb
2 changed files with 18 additions and 9 deletions

View File

@ -1,7 +1,7 @@
import {useState} from 'react'; import {useState} from 'react';
import {useSearchParams} from 'react-router'; import {useSearchParams} from 'react-router';
import {ArrowRight, Check, MapPin, Phone, Search, TriangleAlert} from 'lucide-react'; import {ArrowRight, Check, MapPin, Phone, Search, TriangleAlert} from 'lucide-react';
import type {PlaceCandidate} from '@/api'; import {getAccessToken, type PlaceCandidate} from '@/api';
import {Badge} from '@/components/ui/badge'; import {Badge} from '@/components/ui/badge';
import {Button} from '@/components/ui/button'; import {Button} from '@/components/ui/button';
import {Input} from '@/components/ui/input'; import {Input} from '@/components/ui/input';
@ -83,6 +83,14 @@ export function Step2PlaceSearch() {
const runSearch = () => { const runSearch = () => {
clearIdentity(); // 상호를 고쳐 다시 찾는 것이므로 앞서 확정한 신원은 물린다 clearIdentity(); // 상호를 고쳐 다시 찾는 것이므로 앞서 확정한 신원은 물린다
setPickedIndex(null); setPickedIndex(null);
// ★ 로그인 전에는 서버를 부르지 않는다. 로그인은 에디터 진입에서 한 번 받는 것이 이 앱의 흐름인데,
// 장소 API 는 전부 토큰을 요구해서(place.py) 여기서 부르면 2단계가 로그인 벽이 된다.
// 입력한 값으로 신원을 세우고 넘어간다 — 검증은 로그인 뒤에 다시 할 수 있다.
if (!getAccessToken()) {
confirmIdentity(search.confirmManual(storeName, location));
goToStep(3);
return;
}
void search.search(storeName, location); void search.search(storeName, location);
}; };
@ -113,6 +121,12 @@ export function Step2PlaceSearch() {
const pickByUrl = async () => { const pickByUrl = async () => {
const url = placeUrl.trim(); const url = placeUrl.trim();
if (!url) return; if (!url) return;
// URL 확인도 서버가 토큰을 요구한다 — 로그인 전에는 입력값으로 넘어간다.
if (!getAccessToken()) {
confirmIdentity(search.confirmManual(storeName, location));
goToStep(3);
return;
}
const identity = await search.confirmByUrl(url); const identity = await search.confirmByUrl(url);
if (!identity) return; if (!identity) return;
confirmIdentity(identity); confirmIdentity(identity);

View File

@ -132,15 +132,10 @@ export function usePlaceSearch(industry: IndustryType, existingPlaceId: string |
// 누른 검색이 토큰 없이 나가 '로그인 만료'로 떨어진다 — 만료가 아니라 경합이다. // 누른 검색이 토큰 없이 나가 '로그인 만료'로 떨어진다 — 만료가 아니라 경합이다.
await ensureAutoSession(); await ensureAutoSession();
// ★ '만료' 가 아니라 **아직 로그인한 적이 없는 것**이다(자동 로그인 계정이 없으면 // ★ 토큰이 없으면 화면(Step2)이 검색을 부르지 않고 입력값으로 넘어간다 — 2단계는 로그인 벽이 아니다.
// ensureAutoSession 이 즉시 끝난다). 지도 검색·URL 확인 모두 서버가 토큰을 요구하므로 // 그래도 여기 도달했다면 세션이 도중에 끊긴 것이므로, 로그인을 요구하지 말고 조용히 물러난다.
// (place.py 전 엔드포인트가 IsValidAccessToken) 이 단계는 로그인 없이는 지나갈 수 없다.
if (!getAccessToken()) { if (!getAccessToken()) {
setState({ setState({...INITIAL});
...INITIAL,
phase: 'unavailable',
unavailableReason: '내 가게 확인은 로그인이 필요합니다. 로그인한 뒤 다시 검색해 주세요.',
});
return; return;
} }