Skip to content

Feat/#107 이메일휴대폰 사전검증 api 연동#113

Merged
ahcgnoej merged 3 commits into
developfrom
feat/#107-이메일휴대폰-사전검증-api-연동
May 26, 2026

Hidden character warning

The head ref may contain hidden characters: "feat/#107-\uc774\uba54\uc77c\ud734\ub300\ud3f0-\uc0ac\uc804\uac80\uc99d-api-\uc5f0\ub3d9"
Merged

Feat/#107 이메일휴대폰 사전검증 api 연동#113
ahcgnoej merged 3 commits into
developfrom
feat/#107-이메일휴대폰-사전검증-api-연동

Conversation

@ahcgnoej
Copy link
Copy Markdown
Contributor

개요

학생 회원가입 및 로그인 API를 연동하고, 토큰 관리 아키텍처를 구축했습니다.


변경 사항

1. API 코드 생성 (orval)

OpenAPI 스펙 기반으로 4개 API의 타입/함수를 자동 생성했습니다.

파일 설명
_generated/auth/ssuAuth.ts 유세인트(U-SAINT) 인증
_generated/auth/signupStudent.ts 학생 회원가입
_generated/auth/loginStudent.ts 학생 로그인
_generated/auth/refreshToken.ts 액세스 토큰 재발급

2. 토큰 관리 아키텍처

저장 전략

토큰 저장소 이유
accessToken Zustand (메모리) 앱 재시작 시 재발급, 메모리 노출 최소화
refreshToken expo-secure-store 앱 재시작 후에도 자동 로그인 유지
userRole expo-secure-store 역할별 라우팅을 위해 영속 저장

주요 파일

  • src/shared/api/token-storage.ts — SecureStore CRUD 유틸
  • src/shared/lib/auth/authStore.ts — accessToken/role Zustand 스토어
  • src/shared/api/auth.tssaveTokens, clearTokens, initAuth, getHomeRouteByRole

401 자동 갱신 (interceptors.ts)

  • 요청 시 Zustand에서 accessToken을 읽어 Authorization 헤더 주입
  • 401 응답 수신 시 저장된 refreshToken으로 자동 재발급 후 원본 요청 재시도
  • 재발급 중 들어온 요청은 큐에 쌓아 재발급 완료 후 일괄 처리
  • 재발급 요청 자체의 401 또는 _retry 플래그로 무한 루프 방지

3. 학생 플로우 API 연동

React Query 훅

  • api/useSSUAuthMutation.ts — U-SAINT WebView 인증 결과 처리
  • api/useSignupMutation.ts — 학생 회원가입 요청
  • api/useLoginStudentMutation.ts — 학생 로그인 (LMS)
  • api/useRefreshTokenMutation.ts — 토큰 재발급

Action 훅 (model 레이어)

  • model/useStudentVerificationAction.ts — U-SAINT WebView 노출/응답 처리, 인증 완료 시 학번·전공·이름 자동 입력
  • model/useStudentSignupAction.ts — 회원가입 요청, 실패 시 로그인 화면으로 이동
  • model/useStudentLoginAction.ts — LMS WebView 노출/응답 처리, 로그인 성공 시 토큰 저장 및 학생 홈으로 이동

4. 자동 로그인

앱 시작 시 initAuth()를 호출해 저장된 refreshToken으로 액세스 토큰을 재발급합니다.
역할(STUDENT / ADMIN / PARTNER)에 따라 각각의 홈 화면으로 자동 이동합니다.

STUDENT  →  /(protected)/student/(tabs)/home
ADMIN    →  /(protected)/admin/(tabs)/home
PARTNER  →  /(protected)/partner/(tabs)/home

5. 리팩토링

useSignupFlowController.ts에 집중돼 있던 로직을 3개 action 훅으로 분리했습니다 (362줄 → 230줄).
동작 변화 없음.


스크린샷 / 플로우

[로그인 화면]
  └─ LMS 학생 로그인 버튼
       └─ U-SAINT WebView 노출
            └─ 인증 성공 → loginStudent API → 토큰 저장 → 학생 홈 이동

[회원가입 플로우]
  └─ 유세인트 인증 단계
       └─ U-SAINT WebView 노출
            └─ 인증 성공 → 학번/전공/이름 자동 입력
                 └─ 가입 정보 입력 완료
                      └─ signupStudent API → 성공 시 다음 단계
                                          → 실패 시 로그인 화면으로 이동

체크리스트

  • 유세인트(U-SAINT) 인증 WebView 연동
  • 학생 회원가입 API 연동
  • 학생 로그인(LMS) API 연동
  • AccessToken 메모리 저장 (Zustand)
  • RefreshToken 암호화 저장 (expo-secure-store)
  • 401 자동 갱신 인터셉터 (무한 루프 방지 포함)
  • 앱 시작 시 자동 로그인 + 역할별 라우팅
  • 회원가입 실패 시 로그인 화면 이동

ahcgnoej and others added 2 commits May 25, 2026 01:10
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- loginStudent / refreshToken API 훅 생성 (orval 자동생성)
- expo-secure-store 기반 토큰 저장소 구현 (refreshToken → SecureStore, accessToken → 메모리)
- axios interceptor 401 자동 갱신 + 무한루프 방지
- 앱 시작 시 역할 기반 자동 로그인 (STUDENT / ADMIN / PARTNER)
- LMS 학생 로그인 버튼 활성화 (SSU WebView 연동)
- useSignupFlowController 리팩토링 (action hook 분리)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added del 쓸모없는 코드나 파일 삭제 feature 새로운 기능 구현 mod 코드 수정 및 내부 파일 수정 labels May 25, 2026
@github-actions
Copy link
Copy Markdown

Thanks for the contribution!
I have applied any labels matching special text in your title and description.

Please review the labels and make any necessary changes.

@ahcgnoej ahcgnoej self-assigned this May 25, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements the student authentication and signup flow, integrating SSU LMS verification via WebView and managing session state with expo-secure-store and Zustand. Feedback highlights a critical omission where authentication tokens are not saved after signup, potentially causing immediate session loss. Other recommendations include removing sensitive data logging in API interceptors, externalizing debug flags to environment variables, and replacing hardcoded user roles with dynamic values from the auth store to improve security and maintainability.

Comment on lines +40 to +49
if (!response.isSuccess) {
Alert.alert(
"회원가입 실패",
response.message ?? "회원가입에 실패했습니다.",
[{ text: "확인", onPress: onFailure }],
);
return;
}

onSuccess();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

회원가입 API 호출 성공 후 서버로부터 반환된 토큰과 사용자 역할을 저장하는 로직이 누락되었습니다. useStudentLoginAction과 동일하게 completeLogin을 호출하여 인증 상태를 유지하고 토큰을 저장해야 합니다. 그렇지 않으면 회원가입 완료 후 홈 화면으로 이동했을 때 인증되지 않은 사용자로 처리되어 다시 로그인 화면으로 이동하게 됩니다.

또한 assertSuccess 유틸리티를 사용하여 응답 검증 로직을 공통화하는 것을 권장합니다. (참고: assertSuccesscompleteLogin 임포트가 필요합니다.)

			if (!response.isSuccess) {
				Alert.alert(
					"회원가입 실패",
					response.message ?? "회원가입에 실패했습니다.",
					[{ text: "확인", onPress: onFailure }],
				);
				return;
			}

			const { tokens, role } = response.result;
			await completeLogin(tokens ?? {}, role);

			onSuccess();

Comment on lines +16 to +21
console.log(
"[API REQ]",
config.method?.toUpperCase(),
config.url,
JSON.stringify(config.data),
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

보안 및 개인정보 보호를 위해 API 요청/응답의 data 전체를 JSON.stringify로 출력하는 것은 위험합니다. 비밀번호, 인증 토큰 등 민감한 정보가 로그에 그대로 노출될 수 있습니다. 운영 환경에서는 이러한 로깅을 반드시 제거하거나, 민감한 필드를 마스킹 처리해야 합니다. 또한 console.log는 디버깅용이므로 배포 전 제거하거나 __DEV__ 환경에서만 동작하도록 처리하는 것이 좋습니다. (이 피드백은 파일 내 다른 로깅 부분에도 동일하게 적용됩니다.)

import { useStudentVerificationAction } from "./useStudentVerificationAction";

export function useSignupFlowController() {
const FORCE_PHONE_VERIFICATION_BYPASS = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

FORCE_PHONE_VERIFICATION_BYPASS와 같은 개발용 디버그 플래그가 코드에 포함되어 있습니다. 이러한 설정은 ENV 파일이나 환경 변수를 통해 관리하고, 프로덕션 코드에서는 제거하는 것이 안전합니다. 실수로 활성화된 채 배포될 경우 보안상의 취약점이 될 수 있습니다.

},
onBottomButtonPress: async () => {
if (step === "complete") {
router.replace(getHomeRouteByRole("STUDENT") as never);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

회원가입 완료 후 홈 화면으로 이동할 때 역할을 "STUDENT"로 하드코딩하고 있습니다. 현재 플로우가 학생 전용일지라도, useAuthStore에 저장된 실제 사용자 역할을 사용하도록 수정하여 코드의 일관성과 유연성을 확보하는 것이 좋습니다.

Base automatically changed from feat/#110-generate-api-스크립트-세팅 to develop May 26, 2026 10:31
@ahcgnoej ahcgnoej merged commit a24c807 into develop May 26, 2026
5 checks passed
@ahcgnoej ahcgnoej deleted the feat/#107-이메일휴대폰-사전검증-api-연동 branch May 26, 2026 10:37
@ahcgnoej ahcgnoej linked an issue May 26, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

del 쓸모없는 코드나 파일 삭제 feature 새로운 기능 구현 mod 코드 수정 및 내부 파일 수정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT/#107] 이메일·휴대폰 사전검증 API 연동

1 participant