Skip to content

[feature] 지원서 질문 추가/삭제 및 장문형 질문 타입 구현#454

Merged
oesnuj merged 24 commits intodevelop-fefrom
feature/#453-question-add-remove-FE-128
Jun 1, 2025
Merged

[feature] 지원서 질문 추가/삭제 및 장문형 질문 타입 구현#454
oesnuj merged 24 commits intodevelop-fefrom
feature/#453-question-add-remove-FE-128

Conversation

@oesnuj
Copy link
Member

@oesnuj oesnuj commented May 31, 2025

#️⃣연관된 이슈

#453

📝작업 내용

주요 기능

image

  • 질문 추가/삭제: 질문을 실시간으로 추가하고 삭제할 수 있는 기능
  • 장문형 질문: CustomTextArea를 활용한 LongText 질문 타입 추가
  • UI 개선: 질문 추가 버튼 스타일링 및 사용자 경험 향상

새로 추가된 컴포넌트

  • CustomTextArea: 장문 텍스트 입력용 TextArea 컴포넌트
  • LongText: 장문형 질문 전용 컴포넌트

기타 개선사항

  • ShortText → Text로 타입명 통일
  • APPLICATION_FORM 상수에 maxLength 속성 추가

🫡 참고사항

  • 성원님과 2시간 진행한 페어프로그래밍입니다~ 수고많으셨습니다~~
  • Co-Authored-By: Seongwon Seo seongwon0903@gmail.com
  • 트러블슈팅: mswDevSetup 파일명 앞에 의문의 숫자가 포함되어 Windows 환경에서 git checkout이 불가능한 이슈 발생
    • 해당 숫자를 제거하고 mswDevSetup을 정상화하여 해결 (커밋: 8b37602, c1afb35)

image


🐰 토끼 리뷰 후 수정부분

1. 중복 id의 질문 생성 트러블 슈팅

문제점

기존에는 formData.questions.length + 1 방식으로 질문 ID를 생성하고 있었습니다.
하지만 질문을 삭제할 경우, 예를 들어 ID가 1, 2, 3 → 2 삭제 시 → 남은 ID: 1, 3
이 상태에서 새 질문을 추가하면 다시 ID가 3이 되어 ID 중복 문제가 발생합니다.

해결 방법

현재 존재하는 질문들 중 가장 큰 ID 값을 구한 뒤, 그 값에 +1을 더한 값을 새로운 질문의 ID로 할당하도록 변경
즉, 위 예시에서는 다음 질문의 ID가 4가 되어 1, 3, 4 형태로 유지됩니다.

그럼 지원서 제출 시에는 ID가 어떻게 해야하나요?

제출 시에는 배열의 순서에 맞춰 id를 다시 1부터 재정렬해 백엔드에 전송합니다.
즉, 프론트는 고유 ID만 유지하고, 실제 저장은 순서 기준으로 처리됩니다.


2. 짜잘한 리펙토링

  • textarea 입력 불가 문제 해결: React textarea의 value를 children에서 prop으로 변경하여 controlled component 동작 보장 ff1ddbb
  • QuestionMenu width 불일치 문제: 질문 타입별로 너비가 달라지는 문제를 max-width와 width 조합으로 해결 96eabfd

기능 추가

  • CustomTextArea 자동 높이 조절: 입력 내용에 따라 텍스트 영역 높이가 자동으로 조정되는 기능 추가 b373166

🔧 리팩토링

  • 타입 및 네이밍 정리: CustomInputProps → CustomTextAreaProps, Input* → TextArea* 컴포넌트명 통일 8ab82cb, cedced4
  • 불필요한 props 제거: 사용되지 않는 onClear 프로퍼티 제거 1a80126
  • 스타일 개선: disabled 스타일을 pseudo-selector로 변경, padding 및 resize 설정 최적화 312d784, cedced4
  • 타입 추론 활용: LongText에서 불필요한 명시적 타입 제거 770153e
  • Todo 주석 정리: InputField와의 중복 코드 리팩토링 필요성 명시, 불필요한 주석 제거 8f8a8a9, b94ba42



버그 사항

단답형, 장문형 질문 교체시 textarea의 placeholder의 폰트스타일이 사라집니다... 이거 못고치겄음 뭥미
image

Summary by CodeRabbit

  • 신규 기능

    • 커스텀 텍스트 영역 컴포넌트와 스타일이 추가되었습니다.
    • 지원서 양식에 질문 추가 및 삭제 기능이 도입되었습니다.
    • 긴 텍스트(LONG_TEXT) 질문 유형이 지원됩니다.
  • 버그 수정

    • 개발 환경에서 모듈 임포트 경로 오류가 수정되었습니다.
  • 스타일

    • 입력 필드 및 질문 메뉴의 스타일이 개선되어, 비활성화 및 반응형 동작이 향상되었습니다.
    • 지원서 작성 페이지에 질문 추가 버튼 스타일이 추가되었습니다.
  • 기타

    • 각 질문 유형에 최대 글자 수 제한이 적용되었습니다.
    • 일부 타입 및 인터페이스 명칭이 변경되었습니다.

seongwon030 and others added 13 commits May 31, 2025 23:06
Co-Authored-By: 김준서 Junseo Kim <semiwest2@gmail.com>
Co-Authored-By: 김준서 Junseo Kim <semiwest2@gmail.com>
Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
재사용성을 위해 ShortText에서 Text로 props 타입명을 변경했습니다.

Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
질문을 동적으로 추가하고 삭제할 수 있는 기능을 구현했습니다.

Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
질문을 삭제할 수 있는 버튼을 QuestionBuilder에 추가했습니다.

Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
CustomTextArea 컴포넌트를 활용해 텍스트 입력 필드를 구현

Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
내부 로직에 LongText 케이스를 추가하고, 선택지 드롭다운에 장문형 옵션을 포함시켰습니다.

Co-Authored-By: Seongwon Seo <seongwon0903@gmail.com>
@oesnuj oesnuj requested review from Copilot and seongwon030 May 31, 2025 15:21
@oesnuj oesnuj added ✨ Feature 기능 개발 🔨 Refactor 코드 리팩토링 💻 FE Frontend labels May 31, 2025
@netlify
Copy link

netlify bot commented May 31, 2025

Deploy Preview for moadong ready!

Name Link
🔨 Latest commit 1a80126
🔍 Latest deploy log https://app.netlify.com/projects/moadong/deploys/683beecc93d36500081dc3a3
😎 Deploy Preview https://deploy-preview-454--moadong.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 38
Accessibility: 87
Best Practices: 92
SEO: 92
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 31, 2025

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.
  • 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

질문 추가 및 삭제 기능이 포함된 동적 질문 리스트를 지원하도록 어드민 신청 폼이 확장되었습니다. LongText 타입 질문과 커스텀 텍스트에어리어 컴포넌트가 도입되었으며, 각 질문 유형별로 최대 글자 수가 상수로 정의되었습니다. 관련 스타일 파일과 타입 정의도 함께 추가 및 변경되었습니다.

Changes

파일 그룹/이름 변경 요약
frontend/src/components/common/CustomTextArea/CustomTextArea.tsx
CustomTextArea.styles.ts
커스텀 텍스트에어리어 컴포넌트 및 스타일 추가
frontend/src/pages/AdminPage/application/fields/LongText.tsx LongText 컴포넌트 신규 추가
frontend/src/pages/AdminPage/application/fields/ShortText.tsx ShortText 컴포넌트의 props 타입을 TextProps로 변경
frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx LONG_TEXT 타입 지원, 삭제 버튼 및 onRemoveQuestion prop 추가
frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx
CreateApplicationForm.styles.ts
질문 추가/삭제 함수 및 버튼 추가, AddQuestionButton 스타일 컴포넌트 추가
frontend/src/constants/APPLICATION_FORM.ts 각 질문 타입별 maxLength 속성 추가
frontend/src/types/application.ts QuestionBuilderProps에 onRemoveQuestion 추가, ShortTextProps → TextProps로 이름 변경
frontend/src/index.tsx 개발 환경용 worker import 경로 오타 수정

Sequence Diagram(s)

sequenceDiagram
    participant Admin as AdminPage
    participant Form as CreateApplicationForm
    participant Builder as QuestionBuilder
    participant Field as LongText/ShortText

    Admin->>Form: 폼 렌더링
    Form->>Builder: 질문 리스트 렌더링 (각 질문별)
    Builder->>Field: 질문 타입에 따라 필드 렌더링
    Admin->>Form: "질문 추가 +" 버튼 클릭
    Form->>Form: addQuestion() 실행, 질문 배열에 새 질문 추가
    Form->>Builder: 새로운 질문 컴포넌트 렌더링
    Builder->>Form: "삭제" 버튼 클릭
    Form->>Form: removeQuestion() 실행, 해당 질문 삭제
    Form->>Builder: 질문 리스트 업데이트
Loading

Assessment against linked issues

Objective (이슈 번호) Addressed Explanation
질문 추가 기능 구현 (FE-128)
질문 삭제 기능 구현 (FE-128)

Assessment against linked issues: Out-of-scope changes

해당 이슈의 목적과 직접적으로 관련 없는 변경사항은 발견되지 않았습니다.

Possibly related PRs

Suggested labels

🎨 Design

Suggested reviewers

  • seongwon030
    """
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @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.

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
Member

@seongwon030 seongwon030 left a comment

Choose a reason for hiding this comment

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

질문 추가 삭제까지 고생하셨습니다~~

@seongwon030 seongwon030 linked an issue May 31, 2025 that may be closed by this pull request
3 tasks
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Adds support for adding/removing questions and implements a long-form question type.

  • Introduces a new LongText component (with CustomTextArea) for long-form inputs
  • Updates QuestionBuilder to handle the new type and to allow question removal
  • Implements add/remove question logic in CreateApplicationForm with corresponding styles

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
frontend/src/types/application.ts Added onRemoveQuestion, renamed ShortTextProps to TextProps
frontend/src/pages/AdminPage/application/fields/ShortText.tsx Updated props import/type to TextProps
frontend/src/pages/AdminPage/application/fields/LongText.tsx New LongText component using CustomTextArea
frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx Integrated LongText case, added removal button, reordered imports
frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx Added addQuestion/removeQuestion and wired onRemoveQuestion
frontend/src/pages/AdminPage/application/CreateApplicationForm.styles.ts Added styled AddQuestionButton
frontend/src/index.tsx Fixed import path typo for mswDevSetup
frontend/src/constants/APPLICATION_FORM.ts Added maxLength settings for all question types
frontend/src/components/common/CustomTextArea/CustomTextArea.tsx and .styles.ts Added new CustomTextArea component and styles
Comments suppressed due to low confidence (1)

frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx:19

  • [nitpick] The new add/remove question logic isn’t covered by any tests. Consider adding unit tests to verify that questions are added and removed as expected.
const addQuestion = () => {

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: 6

🧹 Nitpick comments (4)
frontend/src/pages/AdminPage/application/CreateApplicationForm.styles.ts (1)

25-36: 버튼 스타일이 잘 정의되었지만 일부 개선사항이 있습니다.

버튼의 기본 스타일링이 적절하게 구현되었습니다. 다음 개선사항을 고려해보세요:

  1. 하드코딩된 색상 값들을 테마 변수나 CSS 변수로 추출하여 일관성 확보
  2. hover, active 등의 인터랙션 상태 스타일 추가
 export const AddQuestionButton = styled.button`
   padding: 8px 12px;
   border-radius: 6px;
   border: 1px solid #ccc;
   font-size: 0.875rem;
   font-weight: 500;
   background: white;
   color: #555;
   margin-top: 8px;
   cursor: pointer;
+
+  &:hover {
+    background-color: #f8f9fa;
+    border-color: #999;
+  }
+
+  &:active {
+    background-color: #e9ecef;
+  }
 `;
frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts (1)

22-48: TextArea 스타일링이 포괄적으로 구현되었지만 개선사항이 있습니다.

에러 상태, 포커스, disabled 상태 처리가 잘 구현되었습니다. 다음 개선사항을 고려해보세요:

  1. 하드코딩된 높이(45px) 대신 min-height 사용으로 텍스트 양에 따른 확장 허용
  2. 색상 값들을 테마 변수로 추출하여 일관성 확보
 export const TextArea = styled.textarea<{ hasError?: boolean }>`
   flex: 1;
-  height: 45px;
+  min-height: 45px;
+  resize: vertical;
   padding: 12px 80px 12px 18px;
   border: 1px solid ${({ hasError }) => (hasError ? 'red' : '#c5c5c5')};
frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx (1)

140-140: 질문 타입 드롭다운 옵션 순서 개선 제안

LONG_TEXT 옵션이 추가되었지만, 사용자 경험을 고려하여 더 일반적인 SHORT_TEXT를 먼저 배치하는 것이 좋겠습니다.

-            <option value='LONG_TEXT'>장문형</option>
             <option value='SHORT_TEXT'>단답형</option>
+            <option value='LONG_TEXT'>장문형</option>
             <option value='CHOICE'>객관식</option>
frontend/src/components/common/CustomTextArea/CustomTextArea.tsx (1)

29-35: 중복된 maxLength 처리 로직 최적화

handleChange에서 maxLength를 체크하고 있지만, native maxLength 속성도 설정되어 있어 중복 처리입니다. 더 나은 사용자 경험을 위해 JavaScript 검증만 사용하는 것을 고려해보세요.

   const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
     const inputValue = e.target.value;
     if (maxLength !== undefined && inputValue.length > maxLength) {
       return;
     }
     onChange?.(e);
   };

그리고 textarea에서 native maxLength 제거:

         <Styled.TextArea
           onChange={handleChange}
           placeholder={placeholder}
-          maxLength={maxLength}
           disabled={disabled}
           hasError={isError}
           value={value}
         />
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between be8b17c and 87b4cbc.

📒 Files selected for processing (10)
  • frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts (1 hunks)
  • frontend/src/components/common/CustomTextArea/CustomTextArea.tsx (1 hunks)
  • frontend/src/constants/APPLICATION_FORM.ts (1 hunks)
  • frontend/src/index.tsx (1 hunks)
  • frontend/src/pages/AdminPage/application/CreateApplicationForm.styles.ts (1 hunks)
  • frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx (2 hunks)
  • frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx (4 hunks)
  • frontend/src/pages/AdminPage/application/fields/LongText.tsx (1 hunks)
  • frontend/src/pages/AdminPage/application/fields/ShortText.tsx (2 hunks)
  • frontend/src/types/application.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
frontend/src/pages/AdminPage/application/fields/ShortText.tsx (1)
frontend/src/types/application.ts (1)
  • TextProps (45-48)
frontend/src/pages/AdminPage/application/fields/LongText.tsx (1)
frontend/src/types/application.ts (1)
  • TextProps (45-48)
🔇 Additional comments (19)
frontend/src/index.tsx (1)

16-16: 보이지 않는 특수문자 제거로 올바른 import 경로 설정
원래 경로에 포함된 보이지 않는 문자가 제거되어 ./mocks/mswDevSetup 모듈을 정상적으로 로드할 수 있습니다.

frontend/src/constants/APPLICATION_FORM.ts (3)

4-4: maxLength 속성 추가가 잘 구현되었습니다.

SHORT_TEXT의 20자 제한이 적절하며, 플레이스홀더 텍스트와 일치하여 사용자 경험이 일관됩니다.


8-8: LONG_TEXT의 maxLength 설정이 적절합니다.

500자 제한은 장문형 질문에 충분하면서도 무제한 입력을 방지하는 합리적인 값입니다.


12-12: CHOICE의 maxLength 설정이 적절합니다.

선택지 텍스트에 20자 제한은 적절하며, SHORT_TEXT와 동일한 제한으로 일관성을 유지합니다.

frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts (3)

3-8: InputContainer 컴포넌트가 잘 구현되었습니다.

동적 width와 최소 너비 보장이 적절하게 구현되었습니다. flex 레이아웃도 올바르게 설정되었습니다.


50-57: CharCount 컴포넌트의 위치 설정이 적절합니다.

문자 수 표시가 우측 하단에 적절하게 배치되었으며, 스타일링도 일관됩니다.


59-69: HelperText 컴포넌트가 잘 구현되었습니다.

에러 메시지 표시를 위한 스타일링이 적절하며, pointer-events: none과 z-index 설정이 사용자 경험을 고려한 좋은 구현입니다.

frontend/src/types/application.ts (2)

32-32: onRemoveQuestion 콜백 추가가 적절합니다.

질문 삭제 기능을 위한 콜백이 올바르게 정의되었습니다. 시그니처도 간단하고 명확합니다.


45-48: ShortTextProps에서 TextProps로의 이름 변경이 적절합니다.

SHORT_TEXT와 LONG_TEXT 모두에서 사용할 수 있도록 하는 좋은 일반화입니다. 인터페이스 구조는 그대로 유지되어 기존 코드와의 호환성을 보장합니다.

frontend/src/pages/AdminPage/application/fields/ShortText.tsx (1)

5-5: 타입 통합 변경사항 승인

ShortTextProps에서 TextProps로 타입 통합이 올바르게 적용되었습니다. 이는 PR 목표에 맞게 LongText 컴포넌트와의 일관성을 위한 변경사항입니다.

Also applies to: 17-17

frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx (2)

4-4: 새로운 LongText 컴포넌트 import 승인

LongText 컴포넌트 import가 올바르게 추가되었습니다.


58-69: LONG_TEXT 케이스 구현 승인

새로운 LONG_TEXT 질문 타입에 대한 렌더링 로직이 올바르게 구현되었습니다. LongText 컴포넌트에 필요한 모든 props가 적절히 전달되고 있습니다.

frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx (3)

33-38: 질문 삭제 함수 구현 승인

질문 삭제 로직이 올바르게 구현되었습니다. 필터링을 통한 안전한 삭제 방식입니다.


121-121: onRemoveQuestion prop 전달 승인

QuestionBuilder 컴포넌트에 삭제 기능이 올바르게 연결되었습니다.


125-127:

Details

✅ Verification successful

질문 추가 버튼 구현 확인 필요

Styled.AddQuestionButton이 스타일 파일에 정의되어 있는지 확인이 필요합니다.

다음 스크립트로 스타일 정의 여부를 확인해주세요:


🏁 Script executed:

#!/bin/bash
# Description: AddQuestionButton 스타일 정의 확인
# Expected: CreateApplicationForm.styles.ts 파일에서 AddQuestionButton export 발견

rg "AddQuestionButton" frontend/src/pages/AdminPage/application/CreateApplicationForm.styles.ts

Length of output: 143


확인 완료: AddQuestionButton 스타일 정의됨

frontend/src/pages/AdminPage/application/CreateApplicationForm.styles.ts에서 AddQuestionButton이 정상적으로 export 되어 있어 추가 작업이 필요하지 않습니다.

frontend/src/pages/AdminPage/application/fields/LongText.tsx (4)

1-6: import 구문 승인

필요한 모든 의존성이 올바르게 import되었습니다.


7-17: 컴포넌트 Props 정의 승인

TextProps 인터페이스를 사용한 props 정의가 올바르게 구현되었습니다. ShortText 컴포넌트와의 일관성이 유지되고 있습니다.


18-44: 컴포넌트 구조 및 렌더링 로직 승인

LongText 컴포넌트의 전체적인 구조가 잘 설계되었습니다:

  • QuestionTitle과 QuestionDescription 재사용으로 일관성 유지
  • mode에 따른 적절한 상태 관리 (builder 모드에서 비활성화, answer 모드에서 글자 수 표시)
  • 이벤트 핸들러의 올바른 타입 정의

32-41:

Details

✅ Verification successful

CustomTextArea 컴포넌트 사용법 확인 필요

CustomTextArea 컴포넌트의 사용법이 올바른지 확인이 필요합니다. 특히 컴포넌트가 존재하고 기대하는 props 인터페이스와 일치하는지 검증해야 합니다.

다음 스크립트로 CustomTextArea 컴포넌트와 APPLICATION_FORM.LONG_TEXT 상수 정의를 확인해주세요:


🏁 Script executed:

#!/bin/bash
# Description: CustomTextArea 컴포넌트와 LONG_TEXT 상수 정의 확인
# Expected: CustomTextArea 컴포넌트 파일과 APPLICATION_FORM 상수에서 LONG_TEXT 정의 발견

echo "=== CustomTextArea 컴포넌트 확인 ==="
fd "CustomTextArea.tsx" frontend/src/components/common/

echo "=== APPLICATION_FORM.LONG_TEXT 상수 확인 ==="
rg "LONG_TEXT" frontend/src/constants/APPLICATION_FORM.ts

Length of output: 355


🏁 Script executed:

#!/bin/bash
# CustomTextArea 컴포넌트의 prop 정의 확인
echo "=== CustomTextAreaProps 인터페이스 확인 ==="
rg "interface CustomTextAreaProps" -A15 frontend/src/components/common/CustomTextArea/CustomTextArea.tsx

echo "=== showMaxChar prop 구현 확인 ==="
rg "showMaxChar" -A5 frontend/src/components/common/CustomTextArea/CustomTextArea.tsx

Length of output: 813


🏁 Script executed:

#!/bin/bash
# CustomTextAreaProps에 placeholder와 maxLength 정의가 있는지 확인
echo "=== CustomTextAreaProps 전체 인터페이스 확인 ==="
rg "interface CustomTextAreaProps" -A20 frontend/src/components/common/CustomTextArea/CustomTextArea.tsx

echo "=== placeholder prop 검색 ==="
rg "placeholder" -B2 -A2 frontend/src/components/common/CustomTextArea/CustomTextArea.tsx

echo "=== maxLength prop 검색 ==="
rg "maxLength" -B2 -A2 frontend/src/components/common/CustomTextArea/CustomTextArea.tsx

# APPLICATION_FORM.LONG_TEXT 객체 구조 확인
echo "=== APPLICATION_FORM.LONG_TEXT 상세 정의 ==="
rg -A10 "LONG_TEXT:" frontend/src/constants/APPLICATION_FORM.ts

Length of output: 1955


CustomTextArea 사용법 정상 확인됨

  • frontend/src/components/common/CustomTextArea/CustomTextArea.tsx에서
    • placeholder?: string
    • maxLength?: number
    • showMaxChar?: boolean
    • disabled?: boolean
    • value?: string
    • onChange?: (e: React.ChangeEvent) => void
    등의 props를 모두 정의 및 처리하고 있습니다.
  • frontend/src/constants/APPLICATION_FORM.tsLONG_TEXT에도
    • placeholder: '답변입력란(최대 500자)'
    • maxLength: 500
    정의가 일치합니다.

위 확인 결과, 해당 코드에 별도의 수정이나 추가 검증은 필요 없습니다.

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: 0

♻️ Duplicate comments (1)
frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx (1)

18-23: 이전 리뷰에서 제기된 ID 중복 문제가 올바르게 해결되었습니다.

기존 질문들의 최대 ID를 기반으로 다음 ID를 계산하는 방식으로 변경되어, 질문 삭제 후에도 ID 중복이 발생하지 않습니다. 함수형 초기화를 사용하여 성능도 최적화되었습니다.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 18-18: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L18
Added line #L18 was not covered by tests


[warning] 21-22: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L21-L22
Added lines #L21 - L22 were not covered by tests

🧹 Nitpick comments (1)
frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx (1)

3-3: 완료된 TODO 코멘트를 제거해주세요.

질문 추가 및 삭제 기능이 이미 구현되었으므로, 해당 TODO 코멘트를 제거하는 것이 좋겠습니다.

-// Todo: 질문 삭제 및 질문 추가 기능 구현
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 87b4cbc and 9ede224.

📒 Files selected for processing (1)
  • frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx (2 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx

[warning] 18-18: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L18
Added line #L18 was not covered by tests


[warning] 21-22: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L21-L22
Added lines #L21 - L22 were not covered by tests


[warning] 25-26: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L25-L26
Added lines #L25 - L26 were not covered by tests


[warning] 33-33: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L33
Added line #L33 was not covered by tests


[warning] 37-37: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L37
Added line #L37 was not covered by tests


[warning] 40-41: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L40-L41
Added lines #L40 - L41 were not covered by tests


[warning] 43-43: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L43
Added line #L43 was not covered by tests


[warning] 128-128: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L128
Added line #L128 was not covered by tests

🔇 Additional comments (4)
frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx (4)

25-38: 질문 추가 기능이 올바르게 구현되었습니다.

새로운 질문 생성 로직이 적절하고, 불변성을 유지하며 상태를 업데이트하고 있습니다. 기본값 설정도 합리적입니다.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 25-26: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L25-L26
Added lines #L25 - L26 were not covered by tests


[warning] 33-33: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L33
Added line #L33 was not covered by tests


[warning] 37-37: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L37
Added line #L37 was not covered by tests


40-45: 질문 삭제 기능이 올바르게 구현되었습니다.

filter 메서드를 사용한 삭제 로직이 적절하고, 불변성을 유지하며 상태를 업데이트하고 있습니다.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 40-41: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L40-L41
Added lines #L40 - L41 were not covered by tests


[warning] 43-43: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L43
Added line #L43 was not covered by tests


128-128: 질문별 삭제 기능 연결이 올바르게 구현되었습니다.

각 QuestionBuilder에 대해 해당 질문의 ID를 바인딩한 삭제 함수를 전달하고 있습니다.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 128-128: frontend/src/pages/AdminPage/application/CreateApplicationForm.tsx#L128
Added line #L128 was not covered by tests


132-134: 질문 추가 버튼이 올바르게 구현되었습니다.

사용자 친화적인 인터페이스를 제공하며, 기능이 명확하게 표현되어 있습니다.

React에서 <textarea>는 value를 children으로 전달하면 uncontrolled로 동작,
value prop이 무시되어 사용자 입력이 반영되지 않을 수 있음
oesnuj added 9 commits June 1, 2025 13:49
1. Input에서 TextArea로 명칭을 변경하여 컴포넌트 역할을 명확히 함
2. padding 및 resize 설정을 수정하여 textarea UI 개선
3. disabled 스타일을 pseudo-selector로 변경하여 코드 가독성 향상
1. 입력 값에 따라 텍스트 영역의 높이가 자동으로 조정되도록 useRef와 useEffect를 추가
2. 스타일 컴포넌트 명칭 변경 및 Wrapper 구조 개선
1. disabled 스타일을 pseudo-selector로 변경
1. width을 max-width와 함께 설정하여 고정
Props 인터페이스 명칭을 CustomInputProps에서 CustomTextAreaProps로 변경
@seongwon030
Copy link
Member

seongwon030 commented Jun 1, 2025

질문 추가 삭제까지 고생하셨습니다~~

질문 번호 중복 시까지 처리 굿입니다~!!!

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: 2

♻️ Duplicate comments (3)
frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx (1)

145-145: ⚠️ Potential issue

삭제 버튼 개선 필요

과거 리뷰에서 지적된 삭제 버튼의 문제점들(스타일링 부재, 접근성 속성 누락, 삭제 확인 다이얼로그 없음)이 여전히 해결되지 않았습니다.

frontend/src/components/common/CustomTextArea/CustomTextArea.tsx (1)

54-74: 🛠️ Refactor suggestion

접근성 개선 필요

label과 textarea 간의 연결, 오류 상태에 대한 ARIA 속성이 누락되어 있습니다.

다음과 같이 접근성을 개선하는 것을 권장합니다:

+import React from 'react';
+
 const CustomTextArea = ({
   // ... props
 }: CustomTextAreaProps) => {
   const textAreaRef = useRef<HTMLTextAreaElement>(null);
+  const textareaId = React.useId();
+  const helperTextId = isError && helperText ? `${textareaId}-helper` : undefined;

   // ... rest of component

   return (
     <Styled.TextAreaContainer width={width}>
-      {label && <Styled.Label>{label}</Styled.Label>}
+      {label && <Styled.Label htmlFor={textareaId}>{label}</Styled.Label>}
       <Styled.TextAreaWrapper>
         <Styled.TextArea
           ref={textAreaRef}
+          id={textareaId}
           onChange={handleChange}
           placeholder={placeholder}
           maxLength={maxLength}
           disabled={disabled}
           hasError={isError}
           value={value}
+          aria-describedby={helperTextId}
+          aria-invalid={isError}
         />
         {showMaxChar && maxLength !== undefined && (
           <Styled.CharCount>
             {value.length}/{maxLength}
           </Styled.CharCount>
         )}
       </Styled.TextAreaWrapper>
       {isError && helperText && (
-        <Styled.HelperText>{helperText}</Styled.HelperText>
+        <Styled.HelperText id={helperTextId}>{helperText}</Styled.HelperText>
       )}
     </Styled.TextAreaContainer>
   );
frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts (1)

24-26: 🛠️ Refactor suggestion

고정 높이 설정 재검토 필요

textarea에 고정 높이(45px)가 설정되어 있어 자동 높이 조정 기능과 충돌할 가능성이 있습니다. 초기 높이로만 사용되도록 명확히 하거나 min-height로 변경하는 것이 좋겠습니다.

다음과 같이 수정하는 것을 권장합니다:

export const TextArea = styled.textarea<{ hasError?: boolean }>`
   flex: 1;
-  height: 45px;
+  min-height: 45px;
   padding: 12px 18px;
   // ... rest of styles
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 24-24: frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts#L24
Added line #L24 was not covered by tests

🧹 Nitpick comments (4)
frontend/src/components/common/CustomTextArea/CustomTextArea.tsx (2)

4-4: TODO 주석에 대한 후속 조치 필요

InputField 컴포넌트와의 중복 코드 리팩토링에 대한 TODO가 있습니다. 코드 중복을 줄이기 위한 구체적인 계획이 필요합니다.

공통 로직을 추출하여 재사용 가능한 훅이나 유틸리티로 분리하는 리팩토링을 도와드릴까요?


33-42: 자동 높이 조정 로직의 성능 최적화 검토

value가 변경될 때마다 DOM 조작이 발생합니다. 빈번한 입력 시 성능에 영향을 줄 수 있습니다.

다음과 같이 debounce를 적용하여 성능을 개선할 수 있습니다:

+import { useCallback } from 'react';
+
+const CustomTextArea = ({
+  // ... props
+}) => {
+  const textAreaRef = useRef<HTMLTextAreaElement>(null);
+
+  const adjustHeight = useCallback(() => {
+    if (disabled) return;
+    const el = textAreaRef.current;
+    if (el) {
+      el.style.height = 'auto';
+      el.style.height = `${el.scrollHeight}px`;
+    }
+  }, [disabled]);
+
   useEffect(() => {
-    if (disabled) {
-      return;
-    }
-    const el = textAreaRef.current;
-    if (el) {
-      el.style.height = 'auto'; // 초기화
-      el.style.height = `${el.scrollHeight}px`;
-    }
+    const timeoutId = setTimeout(adjustHeight, 0);
+    return () => clearTimeout(timeoutId);
   }, [value, adjustHeight]);
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 33-33: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L33
Added line #L33 was not covered by tests


[warning] 35-35: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L35
Added line #L35 was not covered by tests


[warning] 37-37: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L37
Added line #L37 was not covered by tests


[warning] 39-40: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L39-L40
Added lines #L39 - L40 were not covered by tests

frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts (2)

3-3: TODO 주석 처리 필요

InputField 컴포넌트와의 중복 스타일에 대한 리팩토링 계획이 필요합니다. 스타일 중복은 유지보수성을 떨어뜨릴 수 있습니다.

공통 스타일을 추출하여 재사용 가능한 스타일 함수나 mixin으로 분리하는 작업을 도와드릴까요?


52-59: CharCount 위치 조정 필요

CharCount가 절대 위치로 설정되어 있어 다양한 화면 크기에서 레이아웃 문제가 발생할 수 있습니다. 특히 HelperText와 겹칠 가능성이 있습니다.

다음과 같이 더 안전한 위치 지정을 권장합니다:

export const CharCount = styled.span`
-  position: absolute;
   color: #c5c5c5;
-  right: 0;
-  top: 100%;
+  margin-top: 4px;
+  text-align: right;
   font-size: 16px;
   letter-spacing: -0.96px;
`;

그리고 TextAreaWrapper를 flex column으로 변경:

export const TextAreaWrapper = styled.div`
-  position: relative;
   display: flex;
-  align-items: center;
+  flex-direction: column;
`;
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 52-52: frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts#L52
Added line #L52 was not covered by tests

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9ede224 and 1a80126.

📒 Files selected for processing (6)
  • frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts (1 hunks)
  • frontend/src/components/common/CustomTextArea/CustomTextArea.tsx (1 hunks)
  • frontend/src/components/common/InputField/InputField.styles.ts (1 hunks)
  • frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.styles.ts (1 hunks)
  • frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx (4 hunks)
  • frontend/src/pages/AdminPage/application/fields/LongText.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • frontend/src/components/common/InputField/InputField.styles.ts
  • frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.styles.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/pages/AdminPage/application/fields/LongText.tsx
🧰 Additional context used
🪛 GitHub Check: codecov/patch
frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts

[warning] 1-1: frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts#L1
Added line #L1 was not covered by tests


[warning] 5-6: frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts#L5-L6
Added lines #L5 - L6 were not covered by tests


[warning] 12-12: frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts#L12
Added line #L12 was not covered by tests


[warning] 18-18: frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts#L18
Added line #L18 was not covered by tests


[warning] 24-24: frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts#L24
Added line #L24 was not covered by tests


[warning] 52-52: frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts#L52
Added line #L52 was not covered by tests


[warning] 61-61: frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts#L61
Added line #L61 was not covered by tests

frontend/src/components/common/CustomTextArea/CustomTextArea.tsx

[warning] 1-2: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L1-L2
Added lines #L1 - L2 were not covered by tests


[warning] 19-19: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L19
Added line #L19 was not covered by tests


[warning] 31-31: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L31
Added line #L31 was not covered by tests


[warning] 33-33: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L33
Added line #L33 was not covered by tests


[warning] 35-35: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L35
Added line #L35 was not covered by tests


[warning] 37-37: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L37
Added line #L37 was not covered by tests


[warning] 39-40: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L39-L40
Added lines #L39 - L40 were not covered by tests


[warning] 44-45: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L44-L45
Added lines #L44 - L45 were not covered by tests


[warning] 47-47: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L47
Added line #L47 was not covered by tests


[warning] 52-52: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L52
Added line #L52 was not covered by tests


[warning] 78-78: frontend/src/components/common/CustomTextArea/CustomTextArea.tsx#L78
Added line #L78 was not covered by tests

frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx

[warning] 4-4: frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx#L4
Added line #L4 was not covered by tests


[warning] 8-9: frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx#L8-L9
Added lines #L8 - L9 were not covered by tests

🔇 Additional comments (3)
frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx (3)

4-4: LONG_TEXT 타입 지원을 위한 import 추가 확인

LongText 컴포넌트 import가 올바르게 추가되었습니다. 새로운 장문형 질문 타입을 지원하기 위한 필수적인 변경사항입니다.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 4-4: frontend/src/pages/AdminPage/application/components/QuestionBuilder/QuestionBuilder.tsx#L4
Added line #L4 was not covered by tests


58-69: LONG_TEXT 케이스 구현 검토

LongText 컴포넌트를 렌더링하는 새로운 케이스가 올바르게 구현되었습니다. 다른 질문 타입들과 일관된 prop 구조를 유지하고 있어 좋습니다.


139-142:

Details

❓ Verification inconclusive

드롭다운 옵션 순서 및 장문형 추가 확인

장문형(LONG_TEXT) 옵션이 첫 번째로 배치되고 기존 옵션들의 순서가 조정되었습니다. 사용자 경험 관점에서 가장 자주 사용되는 순서로 배치했는지 확인이 필요합니다.

다음 스크립트로 다른 컴포넌트에서 질문 타입 순서에 대한 가정이나 의존성이 있는지 확인해보겠습니다:


🏁 Script executed:

#!/bin/bash
# 질문 타입 순서에 의존하는 코드가 있는지 확인
rg -A 3 -B 3 "LONG_TEXT|SHORT_TEXT|CHOICE" --type tsx --type ts | grep -E "(index|order|순서|first|last)"

Length of output: 133


rg가 tsx 파일 타입을 인식하지 못해 결과가 없습니다. ts/tsx 파일을 glob 패턴으로 검색해 의존성을 재검증해보겠습니다:


🏁 Script executed:

#!/bin/bash
# 질문 타입 순서에 의존하는 코드 재검증
rg -A 3 -B 3 "LONG_TEXT|SHORT_TEXT|CHOICE" -g '*.ts' -g '*.tsx' | grep -E "(index|order|순서|first|last)"

Length of output: 234


드롭다운 옵션 순서 의존성 없음 확인

  • LONG_TEXT, SHORT_TEXT, CHOICE 순서에 의존하는 로직이나 인덱스 기반 처리를 다른 컴포넌트에서 찾지 못했습니다.
  • UX 관점에서 ‘장문형(LONG_TEXT)’을 최상단에 배치한 의도가 명확한지 팀 내에서 한 번 더 검토해 주세요. 자주 쓰이는 질문 유형 순으로 배치했는지 확인이 필요합니다.

@oesnuj
Copy link
Member Author

oesnuj commented Jun 1, 2025

질문 추가 삭제까지 고생하셨습니다~~

질문 번호 중복 시까지 처리 굿입니다~!!!

캬 리뷰 속도 너무 좋은데요 ㅎㅎ
머지할게융

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💻 FE Frontend ✨ Feature 기능 개발 🔨 Refactor 코드 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] FE-128 질문 추가, 삭제 기능 구현하기

3 participants