-
Notifications
You must be signed in to change notification settings - Fork 0
[Refactor/#114] 사장님 인증 관련 api 수정 #115
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| /// <reference types="next" /> | ||
| /// <reference types="next/image-types/global" /> | ||
| import "./.next/types/routes.d.ts"; | ||
| import "./.next/dev/types/routes.d.ts"; | ||
|
|
||
| // NOTE: This file should not be edited | ||
| // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,4 +29,4 @@ export default function StoreAccountPage() { | |
| </section> | ||
| </main> | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -59,10 +59,15 @@ export default function SignupPage() { | |||||||||||||||||||||||||||||||
| passwordConfirm, | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| onSuccess: () => { | ||||||||||||||||||||||||||||||||
| onSuccess: (res) => { | ||||||||||||||||||||||||||||||||
| const accessToken = res.data.accessToken; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| localStorage.setItem("ownerAccessToken", accessToken); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
|
Comment on lines
+62
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
응답이 비정상일 때 🔧 제안 수정안 onSuccess: (res) => {
- const accessToken = res.data.accessToken;
-
- localStorage.setItem("ownerAccessToken", accessToken);
+ const accessToken = res.data?.accessToken?.trim();
+ if (!accessToken) {
+ console.error("회원가입 응답에 accessToken이 없습니다.");
+ return;
+ }
+ localStorage.setItem("ownerAccessToken", accessToken);
setSignupCompleted(email);
router.push("/signup/business");
},📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||
| setSignupCompleted(email); | ||||||||||||||||||||||||||||||||
| router.push("/signup/business"); | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| onError: (error) => { | ||||||||||||||||||||||||||||||||
| console.log("회원가입 실패", error); | ||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| export function loadDaumPostcode(): Promise<void> { | ||
| return new Promise((resolve, reject) => { | ||
| if (typeof window === "undefined") { | ||
| reject(new Error("window is undefined")); | ||
| return; | ||
| } | ||
|
|
||
| if (window.daum?.Postcode) { | ||
| resolve(); | ||
| return; | ||
| } | ||
|
|
||
| const existingScript = document.querySelector<HTMLScriptElement>( | ||
| 'script[src*="postcode.v2.js"]', | ||
| ); | ||
|
|
||
| if (existingScript) { | ||
| existingScript.addEventListener( | ||
| "load", | ||
| () => { | ||
| if (window.daum?.Postcode) resolve(); | ||
| else reject(new Error("Daum Postcode is not loaded.")); | ||
| }, | ||
| { once: true }, | ||
| ); | ||
|
|
||
| existingScript.addEventListener( | ||
| "error", | ||
| () => reject(new Error("Failed to load Daum Postcode script.")), | ||
| { once: true }, | ||
| ); | ||
|
|
||
| return; | ||
|
Comment on lines
+17
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 기존 스크립트 분기에서 Promise가 영구 대기 상태가 될 수 있습니다. 이미 로드가 끝난 스크립트인데 🔧 제안 수정안 if (existingScript) {
+ const timeoutId = window.setTimeout(() => {
+ reject(new Error("Timed out while waiting for Daum Postcode script."));
+ }, 10000);
+
+ const cleanup = () => window.clearTimeout(timeoutId);
+
existingScript.addEventListener(
"load",
() => {
+ cleanup();
if (window.daum?.Postcode) resolve();
else reject(new Error("Daum Postcode is not loaded."));
},
{ once: true },
);
existingScript.addEventListener(
"error",
- () => reject(new Error("Failed to load Daum Postcode script.")),
+ () => {
+ cleanup();
+ reject(new Error("Failed to load Daum Postcode script."));
+ },
{ once: true },
);
return;
}🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| const script = document.createElement("script"); | ||
| script.src = | ||
| "https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"; | ||
| script.async = true; | ||
|
|
||
| script.onload = () => { | ||
| if (window.daum?.Postcode) resolve(); | ||
| else reject(new Error("Daum Postcode is not loaded.")); | ||
| }; | ||
|
|
||
| script.onerror = () => { | ||
| reject(new Error("Failed to load Daum Postcode script.")); | ||
| }; | ||
|
|
||
| document.head.appendChild(script); | ||
| }); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import { loadDaumPostcode } from "./loadDaumPostcode"; | ||
| import type { | ||
| AddressSearchItem, | ||
| DaumPostcodeData, | ||
| } from "../_types/address-search"; | ||
|
|
||
| export async function openDaumPostcode(): Promise<AddressSearchItem> { | ||
| await loadDaumPostcode(); | ||
|
|
||
| return new Promise((resolve, reject) => { | ||
| if (!window.daum?.Postcode) { | ||
| reject(new Error("Daum Postcode is not loaded.")); | ||
| return; | ||
| } | ||
|
|
||
| new window.daum.Postcode({ | ||
| oncomplete: (data: DaumPostcodeData) => { | ||
| const roadAddress = data.roadAddress || data.address || ""; | ||
| const lotNumberAddress = data.jibunAddress || ""; | ||
|
|
||
| resolve({ | ||
| id: `${data.zonecode}-${roadAddress || lotNumberAddress}`, | ||
| label: roadAddress || lotNumberAddress, | ||
| roadAddress, | ||
| lotNumberAddress, | ||
| zonecode: data.zonecode, | ||
| }); | ||
| }, | ||
| }).open(); | ||
|
Comment on lines
+16
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: Daum 우편번호 서비스의 onclose 콜백은 oncomplete 콜백이 실행된 후에도 호출될 수 있습니다 [1][2]. onclose 콜백은 우편번호 검색창이 닫힐 때 호출되며, 이때 전달되는 state 인자를 통해 닫힌 이유를 구분할 수 있습니다 [2]. FORCE_CLOSE와 COMPLETE_CLOSE의 의미는 다음과 같습니다: 1. COMPLETE_CLOSE: 사용자가 검색 결과 항목을 선택하여 주소 정보가 전달된 후, 우편번호 서비스가 자동으로 닫히는 상태를 의미합니다 [2]. 즉, oncomplete 콜백이 정상적으로 실행 완료된 후에 이 상태로 onclose가 호출됩니다 [1][2]. 2. FORCE_CLOSE: 사용자가 검색 결과 항목을 선택하지 않고, 검색창의 닫기 버튼을 누르거나 외부 영역을 클릭하는 등 강제로 검색창을 닫았을 때 발생하는 상태입니다 [2]. 따라서 oncomplete는 주소 선택 시점에 실행되고, 이후 검색창이 닫히면서 onclose가 호출되는 흐름을 가집니다 [1][2]. 만약 oncomplete 내부에서 페이지 이동(location.href 변경 등)을 수행하면, 페이지가 초기화되어 onclose 콜백이 정상적으로 실행되지 않을 수 있으므로 주의가 필요합니다 [1]. Citations:
주소 선택 없이 팝업을 닫으면 Promise가 resolve/reject 되지 않습니다. 사용자가 주소를 선택하지 않고 닫기 버튼이나 외부 영역을 클릭하면 🔧 제안 수정안 return new Promise((resolve, reject) => {
if (!window.daum?.Postcode) {
reject(new Error("Daum Postcode is not loaded."));
return;
}
+ let settled = false;
+
new window.daum.Postcode({
oncomplete: (data: DaumPostcodeData) => {
+ settled = true;
const roadAddress = data.roadAddress || data.address || "";
const lotNumberAddress = data.jibunAddress || "";
resolve({
id: `${data.zonecode}-${roadAddress || lotNumberAddress}`,
label: roadAddress || lotNumberAddress,
roadAddress,
lotNumberAddress,
zonecode: data.zonecode,
});
},
+ onclose: (state) => {
+ if (!settled && state === "FORCE_CLOSE") {
+ reject(new Error("사용자가 주소 검색을 취소했습니다."));
+ }
+ },
}).open();
});🤖 Prompt for AI Agents |
||
| }); | ||
| } | ||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
Next.js 16 기준으로 next-env.d.ts에서 typed routes 참조 경로는 "./.next/types/routes.d.ts"와 "./.next/dev/types/routes.d.ts" 중 무엇이 공식적으로 권장되나요? dev/prod(typecheck, CI)별 생성 경로 차이도 함께 확인해주세요.💡 Result:
Next.js 16에서 next-env.d.ts 파일 내의 typed routes 참조 경로는 사용자가 직접 수정하거나 선택하는 것이 아니며, Next.js가 실행 환경(dev 또는 build)에 따라 자동으로 관리하는 영역입니다 [1]. 공식적으로 권장되는 특정 경로가 하나로 고정되어 있는 것이 아니라, Next.js의 내부 동작 방식에 따라 다음과 같이 생성됩니다 [1]. 1. 생성 경로 차이: - 개발 환경(next dev):.next/dev/types/routes.d.ts 경로를 참조하도록 생성됩니다 [1]. - 빌드 환경(next build):.next/types/routes.d.ts 경로를 참조하도록 생성됩니다 [1]. 이는 Next.js의 isolatedDevBuild 옵션 도입으로 인해 개발 시의 타입 생성 경로와 빌드 시의 경로가 분리되었기 때문입니다 [1]. 이로 인해 next-env.d.ts 파일 내의 참조 경로가 실행 환경에 따라 토글(toggle)되는 현상이 발생할 수 있으며, 이는 의도된 동작입니다 [1]. 2. 권장 사항: - next-env.d.ts 파일은 Next.js가 자동으로 생성하고 관리하는 파일이므로, 개발자가 직접 이 파일의 참조 경로를 수정해서는 안 됩니다 [2][3]. - 해당 파일은.gitignore에 추가하여 버전 관리에서 제외하는 것이 공식적인 권장 사항입니다 [2][3]. - 프로젝트의 tsconfig.json 파일 내 include 배열에는.next/types//*.ts와 같이 와일드카드를 사용하여 포함시키는 것이 권장됩니다 [2][3]. 이렇게 설정하면 개발 환경과 빌드 환경 모두에서 타입 정의를 올바르게 인식할 수 있습니다 [2][3]. 결론적으로, 특정 경로를 선택하는 것이 아니라 Next.js가 자동으로 생성하는 경로를 그대로 두되, tsconfig.json 설정을 통해 모든 환경에서 타입이 정상적으로 참조되도록 구성하는 것이 올바른 방법입니다 [1][2][3].
Citations:
🏁 Script executed:
Repository: CUK-Compasser/FE
Length of output: 42
🏁 Script executed:
Repository: CUK-Compasser/FE
Length of output: 509
next-env.d.ts의 dev 전용 경로 고정은 빌드/CI 환경에서 타입을 찾지 못해 빌드 실패를 초래합니다.
Line 3에서
./.next/dev/types/routes.d.ts를 하드코딩하면 개발 환경에서는 작동하지만, 프로덕션 빌드 및 CI 환경에서는./.next/types/routes.d.ts를 참조하므로 타입 파일을 찾지 못합니다. 더 근본적으로, Next.js 공식 문서(파일의 5-6줄 주석 참조)에 따르면 next-env.d.ts는 Next.js가 자동으로 생성·관리하는 파일이며 수동 편집 금지입니다. 또한 이 파일은 .gitignore에 추가되어야 하며, tsconfig.json에.next/types/**/*.ts와일드카드를 사용하여 양쪽 환경을 모두 처리해야 합니다.🤖 Prompt for AI Agents