Skip to content

Comments

[feature] 지원서 저장 시 검증 추가 #1221

Merged
seongwon030 merged 2 commits intodevelop-fefrom
feature/#1219-application-edit-validation-MOA-666
Feb 21, 2026
Merged

[feature] 지원서 저장 시 검증 추가 #1221
seongwon030 merged 2 commits intodevelop-fefrom
feature/#1219-application-edit-validation-MOA-666

Conversation

@seongwon030
Copy link
Member

@seongwon030 seongwon030 commented Feb 21, 2026

#️⃣연관된 이슈

ex) #1219

📝작업 내용

  • validateApplicationForm 함수로 제목/설명 필수 및 최대 길이, 질문 제목, 외부 URL 검증
  • 검증 실패 시 항목별 에러 메시지를 alert으로 표시
  • FormTitle에 maxLength={50} 추가
  • 기존 인라인 URL 검증 로직을 validateApplicationForm으로 통합

중점적으로 리뷰받고 싶은 부분(선택)

리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요

ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요?

논의하고 싶은 부분(선택)

논의하고 싶은 부분이 있다면 작성해주세요.

🫡 참고사항

Summary by CodeRabbit

릴리스 노트

  • 버그 수정
    • 애플리케이션 폼 제출 전 런타임 검증 기능 추가
    • 제목 입력 필드에 최대 50자 길이 제한 적용
    • 외부 애플리케이션 URL 검증을 허용 목록 기반으로 개선하여 승인된 서비스만 등록 가능
    • 폼 검증 오류 발생 시 항목별 상세 오류 메시지 표시로 사용자 안내 강화
  • 동작 개선
    • 폼 제출은 검증 통과 시에만 진행되도록 변경

- validateApplicationForm 함수로 제목/설명 필수 및 최대 길이, 질문 제목, 외부 URL 검증
- 검증 실패 시 항목별 에러 메시지를 alert으로 표시
- FormTitle에 maxLength={50} 추가
- 기존 인라인 URL 검증 로직을 validateApplicationForm으로 통합
@seongwon030 seongwon030 self-assigned this Feb 21, 2026
@seongwon030 seongwon030 added ✨ Feature 기능 개발 💻 FE Frontend labels Feb 21, 2026
@vercel
Copy link

vercel bot commented Feb 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
moadong Ready Ready Preview, Comment Feb 21, 2026 7:02am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2026

Caution

Review failed

The pull request is closed.

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. Received: "**" at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • 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

Walkthrough

폼 제출 전에 validateApplicationForm 모듈로 런타임 검증을 수행하도록 변경하고, ApplicationEditTab에서 하드코딩된 외부 URL 화이트리스트 로직을 제거했으며 제목 입력에 maxLength(50)을 추가했습니다.

Changes

Cohort / File(s) Summary
폼 제출 검증 통합
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
제출 전 validateApplicationForm 호출 추가 및 에러 집계/alert 처리 추가. 기존의 useRef import 및 인라인 외부 URL 허용체크(화이트리스트) 제거. 제목 입력에 maxLength(50) 설정. 제출(create/update) 흐름은 검증 통과 후에만 진행.
폼 검증 모듈 추가
frontend/src/pages/AdminPage/validation/validateApplicationForm.ts
새 파일 추가: ApplicationFormErrors 인터페이스, validateApplicationForm(formData, mode, externalUrl) 구현(제목·설명·질문·외부URL 검증), hasErrors(errors) 유틸 및 내부 ALLOWED_EXTERNAL_URLS 허용목록 정의.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • oesnuj
  • lepitaaar
  • suhyun113
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 PR의 주요 변경 사항인 '지원서 저장 시 검증 추가'를 명확하게 요약하고 있으며, 변경 내용과 완전히 관련이 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/#1219-application-edit-validation-MOA-666

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@lepitaaar lepitaaar left a comment

Choose a reason for hiding this comment

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

클라이언트 검증 좋네요 수고하셨습니다

Copy link
Contributor

@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: 1

🧹 Nitpick comments (3)
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx (2)

189-195: maxLength={50}이 검증 로직의 50자 제한과 일치하여 좋습니다.

입력 단에서의 제한과 검증 로직의 제한이 동기화되어 있어 일관성이 보장됩니다. 다만 이 매직 넘버(50)가 두 곳에 분산되어 있으므로, 상수로 추출하면 유지보수가 더 쉬워질 수 있습니다.

♻️ 상수 추출 제안

validateApplicationForm.ts에서:

+export const APPLICATION_TITLE_MAX_LENGTH = 50;
+export const APPLICATION_DESCRIPTION_MAX_LENGTH = 3000;

두 파일 모두에서 이 상수를 참조하면 변경 시 한 곳만 수정하면 됩니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx`
around lines 189 - 195, Extract the magic number 50 into a shared constant (e.g.
MAX_TITLE_LENGTH) and use it both in the input component and in the validation
module: replace the hardcoded maxLength in Styled.FormTitle (where
handleFormTitleChange is used) with MAX_TITLE_LENGTH and update
validateApplicationForm (the validation function) to import and use the same
MAX_TITLE_LENGTH constant so both input-level restriction and validation logic
remain synchronized; add the constant to a common constants file or export it
from the validation module and update imports accordingly.

119-134: 검증-에러 표시 흐름이 잘 구현되어 있습니다. 단, UX 관련 개선 여지가 있습니다.

검증 실패 시 alert로 모든 에러를 한꺼번에 보여주는 방식은 기능적으로 동작하지만, 에러가 많을 경우 사용자 경험이 좋지 않을 수 있습니다. 향후에는 각 필드 옆에 인라인 에러 메시지를 표시하는 방식을 고려해 보세요. ApplicationFormErrors 인터페이스가 이미 필드별 에러를 지원하는 구조이므로 확장이 용이합니다.

또한 Line 129의 Object.values(validationErrors.questions ?? {})는 객체 key 순서에 의존하므로, 질문 ID가 비순차적일 경우 에러 메시지 순서가 화면 상 질문 순서와 다를 수 있습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx`
around lines 119 - 134, The current flow uses alert(...) to show all
validationErrors (from validateApplicationForm + hasErrors) and flattens
question errors with Object.values(validationErrors.questions ?? {}), which can
misorder messages; replace the alert UX by storing validationErrors in component
state (e.g., setValidationErrors) and render per-field inline messages in the
form using the ApplicationFormErrors shape (show title/description/externalUrl
errors next to their inputs and map question errors to the matching question row
by question id), and when you still need a consolidated list, build it by
iterating formData.questions in display order and collecting
validationErrors.questions[question.id] to preserve ordering instead of
Object.values(...).
frontend/src/pages/AdminPage/validation/validateApplicationForm.ts (1)

25-29: 제목 길이 검증이 trim() 전 원본 길이를 기준으로 합니다.

Line 25에서 trim()으로 빈 값을 확인하지만, Line 27에서는 formData.title.length로 원본(공백 포함) 길이를 검사합니다. " a " (길이 51)처럼 앞뒤 공백이 많은 경우, 실제 내용은 짧지만 길이 초과 에러가 발생할 수 있습니다.

ApplicationEditTab.tsx에서 maxLength={50}을 input에 적용하고 있어 실질적 위험은 낮지만, 서버에서 trim 후 저장한다면 검증 로직도 trim() 후 길이를 체크하는 것이 일관적입니다. Description(Line 33)도 동일합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/pages/AdminPage/validation/validateApplicationForm.ts` around
lines 25 - 29, The title (and description) length checks use the raw
formData.title.length which counts surrounding whitespace; change validation in
validateApplicationForm.ts to trim first (e.g., compute a trimmedTitle =
formData.title?.trim()) and use trimmedTitle for both the empty check and the
>50 length check, and do the same for formData.description so
errors.title/errors.description reflect trimmed content length consistently with
ApplicationEditTab.tsx.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/pages/AdminPage/validation/validateApplicationForm.ts`:
- Around line 3-9: The current startsWith-based whitelist
(ALLOWED_EXTERNAL_URLS) allows host-prefix bypasses like
"https://forms.gle.evil.com"; replace the naive check with a robust URL/hostname
check: parse the input with the URL constructor, ensure protocol === 'https:',
then compare parsed.hostname against a whitelist of hostnames (e.g.,
ALLOWED_HOSTNAMES) using exact equality or .endsWith(`.${host}`) to allow
subdomains only of the intended domains; update the validation function that
currently uses ALLOWED_EXTERNAL_URLS (and the checks around lines ~59-61) to use
this isAllowedExternalUrl logic and return false on URL parse errors.

---

Nitpick comments:
In `@frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx`:
- Around line 189-195: Extract the magic number 50 into a shared constant (e.g.
MAX_TITLE_LENGTH) and use it both in the input component and in the validation
module: replace the hardcoded maxLength in Styled.FormTitle (where
handleFormTitleChange is used) with MAX_TITLE_LENGTH and update
validateApplicationForm (the validation function) to import and use the same
MAX_TITLE_LENGTH constant so both input-level restriction and validation logic
remain synchronized; add the constant to a common constants file or export it
from the validation module and update imports accordingly.
- Around line 119-134: The current flow uses alert(...) to show all
validationErrors (from validateApplicationForm + hasErrors) and flattens
question errors with Object.values(validationErrors.questions ?? {}), which can
misorder messages; replace the alert UX by storing validationErrors in component
state (e.g., setValidationErrors) and render per-field inline messages in the
form using the ApplicationFormErrors shape (show title/description/externalUrl
errors next to their inputs and map question errors to the matching question row
by question id), and when you still need a consolidated list, build it by
iterating formData.questions in display order and collecting
validationErrors.questions[question.id] to preserve ordering instead of
Object.values(...).

In `@frontend/src/pages/AdminPage/validation/validateApplicationForm.ts`:
- Around line 25-29: The title (and description) length checks use the raw
formData.title.length which counts surrounding whitespace; change validation in
validateApplicationForm.ts to trim first (e.g., compute a trimmedTitle =
formData.title?.trim()) and use trimmedTitle for both the empty check and the
>50 length check, and do the same for formData.description so
errors.title/errors.description reflect trimmed content length consistently with
ApplicationEditTab.tsx.

@seongwon030 seongwon030 merged commit 990bb53 into develop-fe Feb 21, 2026
3 of 4 checks passed
@seongwon030 seongwon030 deleted the feature/#1219-application-edit-validation-MOA-666 branch February 21, 2026 07:03
@seongwon030 seongwon030 linked an issue Feb 21, 2026 that may be closed by this pull request
2 tasks
This was referenced Feb 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend ✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] MOA-666 지원서 수정 요청 시 입력필드 검증

2 participants