feat: 카카오 JS SDK 전환 - 앱 직접 실행으로 로그인 UX 개선

- claim_form.html, my_page_login.html 카카오 버튼을 JS SDK Kakao.Auth.authorize()로 전환
- 카카오톡 앱 설치 시 앱으로 직접 전환 (원탭 로그인), 미설치 시 웹 폴백
- JS SDK 로드 실패 시 기존 서버 리다이렉트(/claim/kakao/start) 폴백 유지
- app.py: /claim, /my-page 라우트에서 kakao_state 생성하여 템플릿에 전달
- kakao_client.py: birthyear 스코프 제거 (미승인 → KOE205 에러 방지)
- docs/kakao-oauth-setup.md: 플랫폼 키, JS SDK 비교, 다른 계정 적립 안내, 콘솔 설정 문서화

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
thug0bin
2026-02-25 10:55:51 +09:00
parent f969756caa
commit d868a494c2
5 changed files with 231 additions and 36 deletions

View File

@@ -649,7 +649,15 @@ def claim():
except Exception as e:
logging.warning(f"품목 조회 실패 (transaction_id={transaction_id}): {e}")
return render_template('claim_form.html', token_info=token_info, sale_items=sale_items)
# JS SDK용 카카오 state 생성 (CSRF 보호)
csrf_token = secrets.token_hex(16)
state_data = {'t': token_param, 'csrf': csrf_token}
kakao_state = base64.urlsafe_b64encode(
json.dumps(state_data).encode()
).decode()
session['kakao_csrf'] = csrf_token
return render_template('claim_form.html', token_info=token_info, sale_items=sale_items, kakao_state=kakao_state)
@app.route('/api/claim', methods=['POST'])
@@ -876,6 +884,11 @@ def claim_kakao_callback():
kakao_phone_raw = user_info.get('phone_number')
kakao_phone = normalize_kakao_phone(kakao_phone_raw)
# 카카오에서 받은 생년월일 조합 (YYYY-MMDD)
kakao_birthday = None
if user_info.get('birthyear') and user_info.get('birthday'):
kakao_birthday = f"{user_info['birthyear']}-{user_info['birthday'][:2]}-{user_info['birthday'][2:]}"
# 7. 분기: 전화번호가 있으면 자동 적립, 없으면 폰 입력 폼
if kakao_phone:
# 자동 적립
@@ -883,8 +896,13 @@ def claim_kakao_callback():
if existing_user_id:
user_id = existing_user_id
is_new = False
# 생년월일이 있으면 업데이트
if kakao_birthday:
conn = db_manager.get_sqlite_connection()
conn.cursor().execute("UPDATE users SET birthday = ? WHERE id = ? AND birthday IS NULL", (kakao_birthday, user_id))
conn.commit()
else:
user_id, is_new = get_or_create_user(kakao_phone, kakao_name)
user_id, is_new = get_or_create_user(kakao_phone, kakao_name, birthday=kakao_birthday)
link_kakao_identity(user_id, kakao_id, user_info)
@@ -1006,7 +1024,14 @@ def my_page():
phone = request.args.get('phone', '')
if not phone:
return render_template('my_page_login.html')
# JS SDK용 카카오 state 생성
csrf_token = secrets.token_hex(16)
state_data = {'purpose': 'mypage', 'csrf': csrf_token}
kakao_state = base64.urlsafe_b64encode(
json.dumps(state_data).encode()
).decode()
session['kakao_csrf'] = csrf_token
return render_template('my_page_login.html', kakao_state=kakao_state)
# 전화번호로 사용자 조회
phone = phone.replace('-', '').replace(' ', '')