Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔀 로그인 페이지 리팩토링 진행 #63

Merged
merged 6 commits into from
Dec 18, 2024
Merged

Conversation

Ethen1264
Copy link
Contributor

@Ethen1264 Ethen1264 commented Dec 17, 2024

💡 배경 및 개요

로그인 페이지 리팩토링 진행

📃 작업내용

로그인 페이지 리팩토링 진행

Summary by CodeRabbit

  • 신규 기능

    • 사용자 로그인 및 회원가입 기능을 위한 새로운 API 호출 및 훅 추가.
    • SMS 코드 확인 및 전송을 위한 새로운 훅 도입.
    • 사용자 로그인 및 회원가입 시 성공 및 오류 처리 로직 개선.
  • 버그 수정

    • SMS 전송 및 확인 과정에서의 상태 관리 개선.
  • 문서화

    • 새로운 API 및 훅에 대한 설명 추가.
  • 리팩토링

    • 기존 API 호출을 훅으로 대체하여 코드 가독성 및 유지보수성 향상.

@Ethen1264 Ethen1264 added ⚡️performance 성능 개선 📬 Type: API 서버 API 통신 labels Dec 17, 2024
@Ethen1264 Ethen1264 self-assigned this Dec 17, 2024
Copy link

coderabbitai bot commented Dec 17, 2024

Walkthrough

이 풀 리퀘스트는 사용자 인증 프로세스와 관련된 여러 파일의 리팩토링을 포함합니다. 주요 변경 사항은 React Query 훅을 사용하여 로그인, 회원가입, SMS 인증과 같은 인증 관련 기능을 모듈화하고 간소화하는 것입니다. 기존의 직접적인 API 호출 방식에서 벗어나 더 구조화되고 재사용 가능한 훅 기반의 접근 방식으로 전환했습니다.

Changes

파일 변경 요약
src/entities/signIn/api/postSignin.ts 로그인 API 요청을 위한 새로운 인터페이스와 함수 추가
src/entities/signIn/model/useSignin.ts 로그인 뮤테이션 훅 추가
src/entities/signIn/ui/SignInForm/index.tsx 로그인 폼 컴포넌트 훅 기반으로 리팩토링
src/entities/signUp/api/* SMS 및 회원가입 관련 API 함수 재구성
src/entities/signUp/model/* SMS 인증, 회원가입, 타이머 관련 훅 추가
src/entities/signUp/ui/SignUpForm/index.tsx 회원가입 폼 컴포넌트 훅 기반으로 리팩토링

Poem

🐰 코드의 토끼, 훅을 타고
인증의 길을 새롭게 열어
쿼리와 뮤테이션의 춤을 추며
간결하고 멋진 로직을 만들어
🚀 더 나은 인증, 더 쉬운 여정!

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🧹 Nitpick comments (8)
src/entities/signIn/model/useSignin.ts (1)

6-9: 중복된 인터페이스 제거 필요

SignInData 인터페이스가 API 파일과 중복되어 있습니다. 타입 정의를 한 곳으로 통합하여 관리하는 것이 좋습니다.

postSignin.ts에서 인터페이스를 export하고 여기서 import하여 사용하세요:

-interface SignInData {
-  nickname: string;
-  password: string;
-}
+import { SignInData } from '../api/postSignin';
src/entities/signIn/ui/SignInForm/index.tsx (2)

21-21: 로딩 상태 처리 개선 필요

mutation의 로딩 상태를 더 효과적으로 활용할 수 있습니다.

다음과 같이 개선하는 것을 제안드립니다:

-const { mutate: signin } = useSignin();
+const { mutate: signin, isLoading } = useSignin();

-        (data) => signin(data),
+        async (data) => {
+          try {
+            await signin(data);
+          } catch (error) {
+            // 에러 처리
+          }
+        },

그리고 버튼의 disabled 속성을 다음과 같이 수정하세요:

-<Button disabled={isSubmitting} type="submit" text="로그인" />
+<Button disabled={isSubmitting || isLoading} type="submit" text={isLoading ? "로그인 중..." : "로그인"} />

Also applies to: 26-26


Line range hint 41-49: 비밀번호 유효성 검사 개선 필요

비밀번호 유효성 검사 로직을 더 명확하고 재사용 가능하게 개선할 수 있습니다.

상수와 유틸리티 함수로 분리하는 것을 추천드립니다:

+const PASSWORD_VALIDATION = {
+  minLength: 8,
+  pattern: /^(?=.*[A-Z])(?=.*[!@#$%^&*])(?=.{8,})/,
+  messages: {
+    required: '비밀번호를 입력해주세요.',
+    invalid: '비밀번호는 8자리 이상, 대문자 1개, 특수문자 1개 이상을 포함해야 합니다.',
+  },
+};

-          pattern: {
-            value: /^(?=.*[A-Z])(?=.*[!@#$%^&*])(?=.{8,})/,
-            message:
-              '비밀번호는 8자리 이상, 대문자 1개, 특수문자 1개 이상을 포함해야 합니다.',
-          },
+          pattern: {
+            value: PASSWORD_VALIDATION.pattern,
+            message: PASSWORD_VALIDATION.messages.invalid,
+          },
src/entities/signUp/ui/SignUpForm/index.tsx (3)

31-36: 훅 사용 시 의존성 관리 필요

useCheckSmsCode 훅에 watch('phoneNumber')watch('code')를 인자로 전달하고 있습니다. 이러한 watch 함수는 컴포넌트가 렌더링될 때마다 호출되어 성능에 영향을 줄 수 있습니다. 훅 내부에서 필요한 시점에 값을 참조하도록 수정하는 것을 권장합니다.


135-135: SMS 코드 확인 시 입력 값 검증 필요

checkSmsCode() 호출 전에 phoneNumbercode 값이 유효한지 확인하는 로직을 추가해주세요. 값이 없을 경우 예기치 않은 에러가 발생할 수 있습니다.


144-144: SMS 전송 함수 호출 시 입력 값 전달 방식 확인

sendSms(watch('phoneNumber'))로 전화번호를 전달하는 방식이 적절합니다. 하지만 phoneNumber 값이 유효한지 확인하는 검증 로직이 추가되면 더 견고한 코드가 될 것입니다.

src/entities/signUp/model/useSendSms.ts (1)

9-19: mutation 설정 개선 필요

mutation 설정에 retry 로직과 로딩 상태 처리를 추가하는 것이 좋습니다.

   return useMutation({
     mutationFn: (phoneNumber: string) => postSendSms(phoneNumber),
+    retry: 1,
     onSuccess: () => {
       setIsSmsSent(true);
       setTimer(180);
       toast.success('문자 메시지 전송이 완료되었습니다.');
     },
     onError: () => {
       toast.error('문자 메시지 전송에 실패했습니다.');
     },
+    onMutate: () => {
+      toast.info('문자 메시지를 전송중입니다...');
+    }
   });
src/entities/signUp/model/useSignup.ts (1)

6-12: 인터페이스에 문서화를 추가하면 좋을 것 같습니다.

각 필드의 용도와 제약사항을 명확히 하기 위해 JSDoc 문서화를 추가하는 것이 좋겠습니다.

다음과 같이 문서화를 추가해보세요:

+/**
+ * 회원가입에 필요한 사용자 데이터 인터페이스
+ * @interface SignUpData
+ */
 interface SignUpData {
+  /** 사용자의 실명 */
   name: string;
+  /** 사용자의 닉네임 */
   nickname: string;
+  /** 사용자의 이메일 주소 */
   email: string;
+  /** 사용자의 비밀번호 */
   password: string;
+  /** 사용자의 전화번호 */
   phoneNumber: string;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 48bdbdd and 66f079d.

📒 Files selected for processing (14)
  • src/entities/signIn/api/postSignin.ts (1 hunks)
  • src/entities/signIn/model/useSignin.ts (1 hunks)
  • src/entities/signIn/ui/SignInForm/index.tsx (2 hunks)
  • src/entities/signUp/api/checkSmsCode.ts (0 hunks)
  • src/entities/signUp/api/getCheckSmsCode.ts (1 hunks)
  • src/entities/signUp/api/postSendSms.ts (1 hunks)
  • src/entities/signUp/api/postSignup.ts (1 hunks)
  • src/entities/signUp/api/sendSms.ts (0 hunks)
  • src/entities/signUp/api/signup.ts (0 hunks)
  • src/entities/signUp/model/useCheckSmsCode.ts (1 hunks)
  • src/entities/signUp/model/useSendSms.ts (1 hunks)
  • src/entities/signUp/model/useSignup.ts (1 hunks)
  • src/entities/signUp/model/useTimer.ts (1 hunks)
  • src/entities/signUp/ui/SignUpForm/index.tsx (4 hunks)
💤 Files with no reviewable changes (3)
  • src/entities/signUp/api/checkSmsCode.ts
  • src/entities/signUp/api/signup.ts
  • src/entities/signUp/api/sendSms.ts
🔇 Additional comments (5)
src/entities/signUp/ui/SignUpForm/index.tsx (2)

7-9: 사용자 정의 훅을 통한 코드 모듈화

useCheckSmsCode, useSendSms, useSignup 훅을 임포트하여 인증 관련 로직의 재사용성과 모듈화가 향상되었습니다.


38-38: 타이머 훅에 상태 변경 함수 추가

useTimer 훅에 setIsSmsSent를 인자로 추가하여 타이머 종료 시 SMS 전송 상태를 관리하는 로직이 명확해졌습니다.

src/entities/signUp/model/useCheckSmsCode.ts (1)

4-10: 사용자 정의 훅의 올바른 구현

useCheckSmsCode 훅에서 useQuery를 적절히 활용하여 SMS 코드 검증 로직을 구현하였습니다. enabled: false 옵션을 사용하여 필요 시에만 refetch로 호출하는 방식이 효율적입니다.

src/entities/signUp/model/useSignup.ts (2)

1-4: 필요한 의존성들이 잘 구성되어 있습니다!

각 라이브러리의 사용 목적이 명확하고 적절합니다.


14-27: 🛠️ Refactor suggestion

에러 처리와 사용자 경험을 개선할 수 있습니다.

현재 구현에서 몇 가지 개선할 점이 있습니다:

다음과 같이 개선해보세요:

 export const useSignup = () => {
   const router = useRouter();
 
   return useMutation({
     mutationFn: (data: SignUpData) => postSignup(data),
     onSuccess: () => {
       toast.success('회원가입이 완료되었습니다.');
-      router.push('/signIn');
+      // 토스트 메시지를 볼 수 있도록 약간의 지연 후 리다이렉트
+      setTimeout(() => router.push('/signIn'), 1500);
     },
-    onError: () => {
-      toast.error('회원가입에 실패했습니다.');
+    onError: (error: any) => {
+      const errorMessage = error?.response?.data?.message || '회원가입에 실패했습니다.';
+      toast.error(errorMessage);
     },
   });
 };

추가로 고려할 사항:

  1. 로딩 상태를 사용자에게 표시
  2. 중복 제출 방지
  3. 네트워크 오류와 서버 오류를 구분하여 처리

API 응답 형식을 확인하기 위해 다음 스크립트를 실행하세요:

✅ Verification successful

Let me check the error handling implementation in the API layer to verify if we need additional error type information.


Let me check the axios configuration and error handling setup.


Let me check the API client configuration one last time.


사용자 경험 개선을 위한 제안사항입니다.

현재 구현에서 다음과 같은 개선이 필요합니다:

 export const useSignup = () => {
   const router = useRouter();
 
   return useMutation({
     mutationFn: (data: SignUpData) => postSignup(data),
     onSuccess: () => {
       toast.success('회원가입이 완료되었습니다.');
-      router.push('/signIn');
+      // 토스트 메시지를 볼 수 있도록 약간의 지연 후 리다이렉트
+      setTimeout(() => router.push('/signIn'), 1500);
     },
     onError: () => {
       toast.error('회원가입에 실패했습니다.');
     },
   });
 };
  1. 토스트 메시지가 표시되기 전에 페이지가 이동되는 문제를 해결하기 위해 지연시간 추가
  2. 기본 에러 메시지만 사용하는 것이 적절함 (apiClient 설정과 다른 컴포넌트들의 에러 처리 패턴 확인 결과)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# API 응답 형식 확인
rg -A 10 "postSignup" src/

Length of output: 1576


Script:

#!/bin/bash
# Check API error handling implementation
ast-grep --pattern 'catch ($_) {
  $$$
}'

# Check if there are any custom error types defined
rg -g '*.ts' -g '*.tsx' 'type.*Error' src/

Length of output: 88


Script:

#!/bin/bash
# Check axios configuration and error handling
rg -g '*.ts' -g '*.tsx' "axios\.(create|interceptors)" src/

# Check if there are any common error handling utilities
fd -e ts -e tsx --exec grep -l "error\|Error" {} \; src/

Length of output: 514


Script:

#!/bin/bash
# Check API client configuration
cat src/shared/libs/apiClient.ts

# Check for any global error handling
rg -g '*.ts' -g '*.tsx' "toast\.(error|success)" src/

Length of output: 3296

Comment on lines +8 to +11
export const postSignin = async (data: SignInData) => {
const response = await axios.post('/api/auth/signin', data);
return response;
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

API 응답 타입 및 에러 처리 개선 필요

API 호출 구현에 다음 사항들이 보완되어야 합니다:

  1. 응답 데이터의 타입 정의가 누락되었습니다
  2. 에러 처리 로직이 없습니다
  3. axios 인터셉터 설정이 필요할 수 있습니다

다음과 같이 개선하는 것을 제안드립니다:

+interface SignInResponse {
+  accessToken: string;
+  // 기타 응답 필드들...
+}

-export const postSignin = async (data: SignInData) => {
+export const postSignin = async (data: SignInData): Promise<SignInResponse> => {
   try {
-    const response = await axios.post('/api/auth/signin', data);
+    const response = await axios.post<SignInResponse>('/api/auth/signin', data);
     return response.data;
   } catch (error) {
+    if (axios.isAxiosError(error)) {
+      throw new Error(error.response?.data?.message || '로그인에 실패했습니다');
+    }
+    throw error;
   }
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const postSignin = async (data: SignInData) => {
const response = await axios.post('/api/auth/signin', data);
return response;
};
interface SignInResponse {
accessToken: string;
// 기타 응답 필드들...
}
export const postSignin = async (data: SignInData): Promise<SignInResponse> => {
try {
const response = await axios.post<SignInResponse>('/api/auth/signin', data);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
throw new Error(error.response?.data?.message || '로그인에 실패했습니다');
}
throw error;
}
};

Comment on lines +14 to +23
return useMutation({
mutationFn: (data: SignInData) => postSignin(data),
onSuccess: () => {
toast.success('로그인이 완료되었습니다.');
router.push('/');
},
onError: () => {
toast.error('로그인에 실패했습니다.');
},
});
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

mutation 설정 개선 필요

mutation 구성에 몇 가지 중요한 설정이 누락되었습니다:

다음 설정들을 추가하는 것을 추천드립니다:

 return useMutation({
   mutationFn: (data: SignInData) => postSignin(data),
+  retry: 1,
   onSuccess: () => {
     toast.success('로그인이 완료되었습니다.');
+    // 로그인 후 관련 쿼리들 무효화
+    queryClient.invalidateQueries({ queryKey: ['user'] });
     router.push('/');
   },
   onError: () => {
     toast.error('로그인에 실패했습니다.');
   },
+  onSettled: () => {
+    // 로딩 상태 처리
+  }
 });

Committable suggestion skipped: line range outside the PR's diff.

@@ -126,10 +129,10 @@ const SignUpForm = () => {
type="text"
placeholder="인증 번호 입력"
style={{ width: '80%' }}
disabled={!isSmsSent}
disabled={!isSmsSent && watch('code') !== null}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

입력 필드 비활성화 조건 로직 수정 필요

disabled={!isSmsSent && watch('code') !== null} 조건에서 watch('code') !== null은 항상 참(true)일 수 있습니다. 이는 입력 필드가 의도치 않게 비활성화되지 않는 원인이 될 수 있으므로 조건 로직을 재검토해주세요.

적용 예시:

-disabled={!isSmsSent && watch('code') !== null}
+disabled={!isSmsSent || !watch('code')}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
disabled={!isSmsSent && watch('code') !== null}
disabled={!isSmsSent || !watch('code')}


return (
<form
onSubmit={handleSubmit(
(data) => signUp(data, router),
(data) => signup(data),
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

서버로 전달되는 데이터 필터링 필요

signup 함수 호출 시 data를 그대로 전달하고 있어 checkPasswordcode 같은 불필요한 데이터가 서버로 보내질 수 있습니다. 민감한 정보나 불필요한 데이터는 서버로 전달되지 않도록 필요한 필드만 선별하여 전달하는 것을 권장합니다.

적용 예시:

(data) => signup({
  name: data.name,
  nickname: data.nickname,
  email: data.email,
  password: data.password,
  phoneNumber: data.phoneNumber,
})
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(data) => signup(data),
(data) => signup({
name: data.name,
nickname: data.nickname,
email: data.email,
password: data.password,
phoneNumber: data.phoneNumber,
}),

Comment on lines +10 to +11
const response = await axios.post('/api/auth/sms', { phoneNumber });
return response;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

API 호출 시 에러 처리 필요

axios.post 요청 중 발생할 수 있는 에러에 대한 처리가 없습니다. 네트워크 오류나 서버 오류에 대비하기 위해 try-catch 구문을 사용하여 에러를 처리하는 것을 권장합니다.

적용 예시:

export const postSendSms = async (phoneNumber: string) => {
  if (!phoneNumber) {
    throw new Error('전화번호를 입력해주세요.');
  }
+ try {
    const response = await axios.post('/api/auth/sms', { phoneNumber });
    return response;
+ } catch (error) {
+   throw error;
+ }
};

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +11 to +13
export const postSignup = async (data: SignUpData) => {
const response = await axios.post('/api/auth/signup', data);
return response;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

API 호출 시 에러 처리 필요

axios.post 요청 시 발생할 수 있는 에러를 처리하지 않고 있습니다. 서버 응답 오류나 네트워크 장애에 대비하여 try-catch 구문으로 에러를 처리하는 것을 권장합니다.

적용 예시:

export const postSignup = async (data: SignUpData) => {
+ try {
    const response = await axios.post('/api/auth/signup', data);
    return response;
+ } catch (error) {
+   throw error;
+ }
};
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const postSignup = async (data: SignUpData) => {
const response = await axios.post('/api/auth/signup', data);
return response;
export const postSignup = async (data: SignUpData) => {
try {
const response = await axios.post('/api/auth/signup', data);
return response;
} catch (error) {
throw error;
}
};

Comment on lines +10 to +12
const response = await axios.get(
`/api/auth/sms?phoneNumber=${phoneNumber}&code=${code}`,
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

URL 매개변수 인코딩 필요

URL 매개변수에 특수 문자가 포함될 수 있으므로 encodeURIComponent를 사용하여 안전하게 인코딩해야 합니다.

-    `/api/auth/sms?phoneNumber=${phoneNumber}&code=${code}`,
+    `/api/auth/sms?phoneNumber=${encodeURIComponent(phoneNumber)}&code=${encodeURIComponent(code)}`,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const response = await axios.get(
`/api/auth/sms?phoneNumber=${phoneNumber}&code=${code}`,
);
const response = await axios.get(
`/api/auth/sms?phoneNumber=${encodeURIComponent(phoneNumber)}&code=${encodeURIComponent(code)}`,
);

Comment on lines +4 to +14
export const getCheckSmsCode = async (phoneNumber: string, code: string) => {
if (!phoneNumber || !code) {
toast.error('전화번호와 인증 번호를 입력해주세요.');
return;
}

const response = await axios.get(
`/api/auth/sms?phoneNumber=${phoneNumber}&code=${code}`,
);
return response;
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

에러 처리 및 타입 안전성 개선 필요

함수의 반환 타입을 명시하고 에러 처리를 개선하는 것이 좋습니다.

-export const getCheckSmsCode = async (phoneNumber: string, code: string) => {
+interface SmsVerificationResponse {
+  success: boolean;
+  message: string;
+}
+
+export const getCheckSmsCode = async (
+  phoneNumber: string,
+  code: string
+): Promise<SmsVerificationResponse> => {
   if (!phoneNumber || !code) {
     toast.error('전화번호와 인증 번호를 입력해주세요.');
-    return;
+    throw new Error('전화번호와 인증 번호는 필수입니다.');
   }

-  const response = await axios.get(
-    `/api/auth/sms?phoneNumber=${phoneNumber}&code=${code}`,
-  );
-  return response;
+  try {
+    const response = await axios.get<SmsVerificationResponse>(
+      `/api/auth/sms?phoneNumber=${encodeURIComponent(phoneNumber)}&code=${encodeURIComponent(code)}`,
+    );
+    return response.data;
+  } catch (error) {
+    toast.error('인증 확인 중 오류가 발생했습니다.');
+    throw error;
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const getCheckSmsCode = async (phoneNumber: string, code: string) => {
if (!phoneNumber || !code) {
toast.error('전화번호와 인증 번호를 입력해주세요.');
return;
}
const response = await axios.get(
`/api/auth/sms?phoneNumber=${phoneNumber}&code=${code}`,
);
return response;
};
interface SmsVerificationResponse {
success: boolean;
message: string;
}
export const getCheckSmsCode = async (
phoneNumber: string,
code: string
): Promise<SmsVerificationResponse> => {
if (!phoneNumber || !code) {
toast.error('전화번호와 인증 번호를 입력해주세요.');
throw new Error('전화번호와 인증 번호는 필수입니다.');
}
try {
const response = await axios.get<SmsVerificationResponse>(
`/api/auth/sms?phoneNumber=${encodeURIComponent(phoneNumber)}&code=${encodeURIComponent(code)}`,
);
return response.data;
} catch (error) {
toast.error('인증 확인 중 오류가 발생했습니다.');
throw error;
}
};

Comment on lines 8 to +18
useEffect(() => {
if (timer > 0) {
const intervalId = setInterval(() => {
setTimer((prev) => prev - 1);
}, 1000);

return () => clearInterval(intervalId);
} else if (timer === 0) {
setIsSmsSent(false);
}
}, [timer, setTimer]);
}, [timer, setTimer, setIsSmsSent]);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

타이머 로직 개선 필요

타이머 로직에 몇 가지 개선이 필요합니다:

 useEffect(() => {
+  let intervalId: NodeJS.Timeout;
   if (timer > 0) {
-    const intervalId = setInterval(() => {
+    intervalId = setInterval(() => {
       setTimer((prev) => prev - 1);
     }, 1000);
-
-    return () => clearInterval(intervalId);
   } else if (timer === 0) {
     setIsSmsSent(false);
   }
+  return () => {
+    if (intervalId) {
+      clearInterval(intervalId);
+    }
+  };
 }, [timer, setTimer, setIsSmsSent]);
  1. 메모리 누수 방지를 위한 cleanup 함수 개선
  2. 타이머가 0이 되었을 때의 처리 로직 명확화
  3. 인터벌 ID 관리 개선
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (timer > 0) {
const intervalId = setInterval(() => {
setTimer((prev) => prev - 1);
}, 1000);
return () => clearInterval(intervalId);
} else if (timer === 0) {
setIsSmsSent(false);
}
}, [timer, setTimer]);
}, [timer, setTimer, setIsSmsSent]);
useEffect(() => {
let intervalId: NodeJS.Timeout;
if (timer > 0) {
intervalId = setInterval(() => {
setTimer((prev) => prev - 1);
}, 1000);
} else if (timer === 0) {
setIsSmsSent(false);
}
return () => {
if (intervalId) {
clearInterval(intervalId);
}
};
}, [timer, setTimer, setIsSmsSent]);

toast.success('문자 메시지 전송이 완료되었습니다.');
},
onError: () => {
toast.error('문제 매시지 전송에 실패했습니다.');
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

오타 수정 필요

에러 메시지의 오타를 수정해야 합니다.

-      toast.error('문제 매시지 전송에 실패했습니다.');
+      toast.error('문자 메시지 전송에 실패했습니다.');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
toast.error('문제 매시지 전송에 실패했습니다.');
toast.error('문자 메시지 전송에 실패했습니다.');

@Ethen1264 Ethen1264 merged commit 170b288 into develop Dec 18, 2024
2 checks passed
@Ethen1264 Ethen1264 deleted the refector/signin branch December 23, 2024 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⚡️performance 성능 개선 📬 Type: API 서버 API 통신
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants