Skip to content

온보딩 버튼 비활성화 직#45

Merged
dasosann merged 4 commits intomainfrom
feat/main-api
Mar 16, 2026
Merged

온보딩 버튼 비활성화 직#45
dasosann merged 4 commits intomainfrom
feat/main-api

Conversation

@dasosann
Copy link
Copy Markdown
Contributor

No description provided.

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

MBTI 유효성 검사 및 온보딩 버튼 활성화 조건 개선

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• MBTI 유효성 검사 로직 추가 및 정규화 처리
• 성별, MBTI, 연락빈도 선택 상태 추적으로 버튼 활성화 조건 강화
• 비활성화 상태에서 그림자 효과 제거
• 버튼 스타일 적용 순서 개선으로 disabled 상태 우선 처리
Diagram
flowchart LR
  A["사용자 입력"] -->|MBTI 정규화| B["isValidMBTI 검증"]
  B -->|유효성 확인| C["선택 상태 추적"]
  C -->|hasSelected 플래그| D["버튼 활성화 조건"]
  D -->|조건 충족| E["다음 단계 진행"]
  F["Button 컴포넌트"] -->|disabled 상태| G["그림자 제거 및 스타일 우선순위"]
Loading

Grey Divider

File Changes

1. app/profile-builder/_components/ScreenProfileBuilder.tsx ✨ Enhancement +50/-8

MBTI 검증 및 선택 상태 추적 로직 강화

• MBTI 유효성 검사를 위한 mbtiSetisValidMBTI 함수 추가
• 성별, MBTI, 연락빈도 선택 상태를 추적하는 hasSelected* 상태 변수 추가
• 각 선택 항목의 핸들러 함수 추가로 선택 상태 기록
• 단계별 유효성 검사에 선택 상태 플래그와 MBTI 정규화 검증 적용
• MBTI 저장 시 대문자 정규화 및 유효성 검사 추가

app/profile-builder/_components/ScreenProfileBuilder.tsx


2. components/ui/Button.tsx 🐞 Bug fix +6/-7

비활성화 상태 스타일 처리 개선

disabled 상태일 때 그림자 효과 제거 조건 추가
• 버튼 스타일 적용 순서 개선으로 disabled 상태를 우선 처리
• className 적용 로직 재구성으로 disabled 상태 스타일 보장

components/ui/Button.tsx


Grey Divider

Qodo Logo


✨ Describe tool usage guide:

Overview:
The describe tool scans the PR code changes, and generates a description for the PR - title, type, summary, walkthrough and labels. The tool can be triggered automatically every time a new PR is opened, or can be invoked manually by commenting on a PR.

When commenting, to edit configurations related to the describe tool (pr_description section), use the following template:

/describe --pr_description.some_config1=... --pr_description.some_config2=...

With a configuration file, use the following template:

[pr_description]
some_config1=...
some_config2=...
Enabling\disabling automation
  • When you first install the app, the default mode for the describe tool is:
pr_commands = ["/describe", ...]

meaning the describe tool will run automatically on every PR.

  • Markers are an alternative way to control the generated description, to give maximal control to the user. If you set:
pr_commands = ["/describe --pr_description.use_description_markers=true", ...]

the tool will replace every marker of the form pr_agent:marker_name in the PR description with the relevant content, where marker_name is one of the following:

  • type: the PR type.
  • summary: the PR summary.
  • walkthrough: the PR walkthrough.
  • diagram: the PR sequence diagram (if enabled).

Note that when markers are enabled, if the original PR description does not contain any markers, the tool will not alter the description at all.

Custom labels

The default labels of the describe tool are quite generic: [Bug fix, Tests, Enhancement, Documentation, Other].

If you specify custom labels in the repo's labels page or via configuration file, you can get tailored labels for your use cases.
Examples for custom labels:

  • Main topic:performance - pr_agent:The main topic of this PR is performance
  • New endpoint - pr_agent:A new endpoint was added in this PR
  • SQL query - pr_agent:A new SQL query was added in this PR
  • Dockerfile changes - pr_agent:The PR contains changes in the Dockerfile
  • ...

The list above is eclectic, and aims to give an idea of different possibilities. Define custom labels that are relevant for your repo and use cases.
Note that Labels are not mutually exclusive, so you can add multiple label categories.
Make sure to provide proper title, and a detailed and well-phrased description for each label, so the tool will know when to suggest it.

Inline File Walkthrough 💎

For enhanced user experience, the describe tool can add file summaries directly to the "Files changed" tab in the PR page.
This will enable you to quickly understand the changes in each file, while reviewing the code changes (diffs).

To enable inline file summary, set pr_description.inline_file_summary in the configuration file, possible values are:

  • 'table': File changes walkthrough table will be displayed on the top of the "Files changed" tab, in addition to the "Conversation" tab.
  • true: A collapsable file comment with changes title and a changes summary for each file in the PR.
  • false (default): File changes walkthrough will be added only to the "Conversation" tab.
Utilizing extra instructions

The describe tool can be configured with extra instructions, to guide the model to a feedback tailored to the needs of your project.

Be specific, clear, and concise in the instructions. With extra instructions, you are the prompter. Notice that the general structure of the description is fixed, and cannot be changed. Extra instructions can change the content or style of each sub-section of the PR description.

Examples for extra instructions:

[pr_description]
extra_instructions="""- The PR title should be in the format: '<PR type>: <title>'
- The title should be short and concise (up to 10 words)
- ...
"""

Use triple quotes to write multi-line instructions. Use bullet points to make the instructions more readable.

More PR-Agent commands

To invoke the PR-Agent, add a comment using one of the following commands:

  • /review: Request a review of your Pull Request.
  • /describe: Update the PR title and description based on the contents of the PR.
  • /improve [--extended]: Suggest code improvements. Extended mode provides a higher quality feedback.
  • /ask <QUESTION>: Ask a question about the PR.
  • /update_changelog: Update the changelog based on the PR's contents.
  • /help_docs <QUESTION>: Given a path to documentation (either for this repository or for a given one), ask a question.
  • /add_docs 💎: Generate docstring for new components introduced in the PR.
  • /generate_labels 💎: Generate labels for the PR based on the PR's contents.
  • /analyze 💎: Automatically analyzes the PR, and presents changes walkthrough for each component.

See the tools guide for more details.
To list the possible configuration parameters, add a /config comment.

See the describe usage page for a comprehensive guide on using this tool.

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review bot commented Mar 15, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Prefill blocks progression 🐞 Bug ✓ Correctness
Description
ScreenProfileBuilder now requires hasSelectedGender/MBTI/Frequency to be true, but these flags start
false and are only set by click handlers, so prefilled selections (from profile/localStorage) can
leave the bottom button disabled. Users resuming onboarding or revisiting the page must re-click
already-selected options to proceed/complete.
Code

app/profile-builder/_components/ScreenProfileBuilder.tsx[R202-206]

+        return !!selectedGender && hasSelectedGender;
      case 3:
-        return !!selectedMBTI;
+        return isValidMBTI(selectedMBTI) && hasSelectedMBTI;
      case 4:
-        return !!selectedFrequency;
+        return !!selectedFrequency && hasSelectedFrequency;
Evidence
The page preloads selected values from profile/localStorage and passes them as defaultValue into
steps, but the new hasSelected* flags are initialized to false and only flip to true when the step
components invoke the callbacks (which happens only on user interaction). Since isStepValid now
requires both a selected value and the corresponding hasSelected* flag, the bottom Button remains
disabled even when a selection is already present/visible.

app/profile-builder/_components/ScreenProfileBuilder.tsx[64-105]
app/profile-builder/_components/ScreenProfileBuilder.tsx[125-207]
app/profile-builder/_components/ScreenProfileBuilder.tsx[229-285]
app/profile-builder/_components/Step2Gender.tsx[17-22]
app/profile-builder/_components/Step3MBTI.tsx[15-35]
app/profile-builder/_components/Step4ContactFrequency.tsx[15-20]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`ScreenProfileBuilder` introduced `hasSelectedGender/MBTI/Frequency` flags to gate step validity, but they default to `false` and are only flipped by user click handlers. When values are prefilled (from profile/localStorage) and shown via `defaultValue`, the bottom CTA remains disabled until the user re-clicks the same option.

### Issue Context
- Initial values can come from `profile` or `localStorage`.
- Step components do **not** call the `on*Select` callbacks on mount for `defaultValue` (they only call them on user interaction / when MBTI becomes length 4).

### Fix Focus Areas
- app/profile-builder/_components/ScreenProfileBuilder.tsx[64-110]
- app/profile-builder/_components/ScreenProfileBuilder.tsx[116-127]
- app/profile-builder/_components/ScreenProfileBuilder.tsx[176-207]

### Suggested fix
Option A (recommended): initialize flags based on `initialValues`:
- `useState(!!initialValues.gender)`
- `useState(isValidMBTI(initialValues.mbti))`
- `useState(!!initialValues.frequency)`

Option B: drop `hasSelected*` from `isStepValid` and rely on actual selected values/validation.

If the intended behavior is “force re-confirmation”, then also adjust `currentStep` initialization (avoid jumping to step 4 when `allFilled` is true) or explicitly clear prefilled values so the UI state matches the disabled CTA.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 온보딩 경험을 개선하기 위해 MBTI 유효성 검사 및 버튼 비활성화 로직을 강화합니다. 이를 통해 사용자 흐름의 견고성과 시각적 일관성을 확보합니다.

Highlights

  • MBTI 유효성 검사 로직 추가: MBTI 유형 목록을 정의하고 입력된 MBTI 값의 유효성을 검사하는 mbtiSetisValidMBTI 함수를 추가했습니다.
  • 온보딩 완료 로직 개선: 온보딩 완료 시 mbti 필드의 유효성을 isValidMBTI 함수를 사용하여 검사하도록 업데이트하여 데이터의 정확성을 높였습니다.
  • 사용자 상호작용 추적 상태 도입: 사용자가 성별, MBTI, 연락 빈도를 선택했는지 여부를 추적하는 hasSelectedGender, hasSelectedMBTI, hasSelectedFrequency 상태 변수를 추가했습니다.
  • 단계별 유효성 검사 강화: 단계별 유효성 검사 로직을 수정하여 새로운 상호작용 추적 상태 변수들을 확인하도록 하여, 사용자가 각 단계를 실제로 완료했는지 더욱 정확하게 판단합니다.
  • 선택 핸들러 함수 리팩토링: 성별, MBTI, 연락 빈도 선택을 위한 새로운 핸들러 함수(handleGenderSelect, handleMBTISelect, handleFrequencySelect)를 추가하여 선택된 값과 상호작용 추적 상태를 동시에 업데이트하도록 했습니다.
  • 버튼 그림자 로직 수정: 버튼이 비활성화될 때 그림자가 표시되지 않도록 hasShadow 계산 로직을 수정하여 UI 일관성을 개선했습니다.
  • 버튼 비활성화 스타일 적용 개선: 버튼의 비활성화 상태에 따른 스타일 적용 로직을 리팩토링하여 className 속성 적용 순서를 조정하고 일관된 비활성화 스타일을 보장합니다.
Changelog
  • app/profile-builder/_components/ScreenProfileBuilder.tsx
    • MBTI 유형 목록을 정의하고 유효성을 검사하는 mbtiSetisValidMBTI 함수를 추가했습니다.
    • 온보딩 완료 시 mbti 필드의 유효성을 isValidMBTI 함수를 사용하여 검사하도록 업데이트했습니다.
    • 사용자가 성별, MBTI, 연락 빈도를 선택했는지 여부를 추적하는 hasSelectedGender, hasSelectedMBTI, hasSelectedFrequency 상태 변수를 추가했습니다.
    • handleGenderSelect, handleMBTISelect, handleFrequencySelect 함수를 추가하여 해당 값을 설정하고 선택 여부 상태를 업데이트하도록 했습니다.
    • 단계별 유효성 검사 로직을 수정하여 hasSelectedGender, hasSelectedMBTI, hasSelectedFrequency 상태를 확인하도록 했습니다.
    • Step4ContactFrequency, Step3MBTI, Step2Gender 컴포넌트의 onFrequencySelect, onMBTISelect, onGenderSelect prop에 새로 추가된 핸들러 함수를 연결했습니다.
    • handleComplete 함수에서 selectedMBTI를 대문자로 정규화하고 isValidMBTI를 사용하여 유효한 경우에만 mbti 필드를 설정하도록 로직을 변경했습니다.
  • components/ui/Button.tsx
    • hasShadow 계산 로직을 수정하여 버튼이 disabled 상태일 때는 그림자가 적용되지 않도록 했습니다.
    • 버튼의 className 속성 적용 순서를 조정하여 disabled 상태의 스타일이 올바르게 적용되도록 리팩토링했습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

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

이번 PR은 온보딩 과정에서 사용자가 값을 선택했음에도 버튼이 비활성화되는 문제를 해결하는 데 중점을 둔 것으로 보입니다. 사용자 상호작용을 추적하기 위해 hasSelected... 상태를 추가하고, 이를 검증 로직에 반영한 점이 좋습니다. 또한, 비활성화된 버튼의 그림자 효과를 제거하여 UI의 시각적 일관성을 개선했습니다.

코드 리뷰에서는 두 가지 주요 개선점을 제안했습니다.

  1. ScreenProfileBuilder.tsx에서 기존에 입력된 값이 있는 경우, 사용자가 다시 선택하지 않아도 '다음' 버튼이 활성화되도록 상태 초기화 로직을 수정할 것을 제안했습니다. 이는 사용자 경험을 크게 개선하며, 사용자 입력 값 유지에 대한 규칙을 따릅니다.
  2. Button.tsx 컴포넌트의 cn 함수 사용법을 더 간결하고 명확하게 리팩토링하여 코드 가독성과 유지보수성을 높이는 방안을 제안했습니다.

전반적으로 올바른 방향의 수정이며, 제안된 내용을 반영하면 더 완성도 높은 코드가 될 것이라 생각합니다.

@dasosann
Copy link
Copy Markdown
Contributor Author

@gemini-code-assist review

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

이번 PR은 QA 페이지, 비밀번호 재설정 기능 추가 및 프로필 빌더 로직 개선 등 여러 중요한 변경 사항을 포함하고 있습니다. 전반적으로 기능 구현은 잘 이루어졌으나, 몇 가지 개선점을 제안합니다.

가장 중요한 점은 비밀번호 재설정 흐름에서 발견된 심각한 보안 취약점입니다. 현재 sessionStorage를 이용한 클라이언트 측 인증은 쉽게 우회될 수 있으므로, 서버에서 발급하는 보안 토큰 방식으로 반드시 변경해야 합니다.

또한, QA 페이지에서는 React의 key prop 사용법을 개선하고, 일부 컴포넌트에서는 사용하지 않는 상태와 import를 정리하여 코드 품질을 높일 것을 제안합니다. 마지막으로, 스타일 가이드에 따라 조건부 클래스를 cn 유틸리티로 리팩토링하는 것을 권장합니다.

Comment on lines +24 to +32
useEffect(() => {
const verified = sessionStorage.getItem("reset_verified");
if (verified !== "true") {
alert("잘못된 접근입니다.");
router.replace("/reset/password");
} else {
Promise.resolve().then(() => setIsVerified(true));
}
}, [router]);
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-critical critical

보안 취약점: 클라이언트 측 인증 우회 가능

sessionStorage를 사용하여 페이지 접근 권한을 확인하는 방식은 심각한 보안 취약점을 가집니다. 개발자 도구를 통해 sessionStorage.setItem("reset_verified", "true")를 실행하면 이메일 인증 절차를 건너뛰고 바로 비밀번호 변경 페이지에 접근할 수 있습니다.

권장 해결 방안:
서버에서 생성한 일회용 보안 토큰(예: JWT)을 사용해야 합니다.

  1. 인증번호 확인 성공 시, 서버는 비밀번호 변경 전용 일회용 토큰을 발급하여 클라이언트에게 전달합니다.
  2. 클라이언트는 이 토큰을 URL 파라미터 등으로 포함하여 새 비밀번호 설정 페이지로 이동합니다.
  3. 새 비밀번호를 제출할 때 이 토큰을 함께 서버로 전송합니다.
  4. 서버는 토큰의 유효성(서명, 만료 시간, 일회성 여부)을 검증한 후에만 비밀번호 변경을 처리합니다.

이 방식은 클라이언트 측 조작으로 인증 단계를 우회하는 것을 원천적으로 방지합니다.

References
  1. 서버 액션이나 API 접근 시 권한 확인 로직이 누락되지 않았는지 검토해야 합니다. 현재 구현은 클라이언트 측에서 쉽게 조작될 수 있는 sessionStorage에 의존하고 있어, 적절한 서버 측 권한 확인 로직이 누락되었습니다. (link)

@dasosann dasosann merged commit e588091 into main Mar 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant