Skip to content

의존성 픽스#55

Merged
Jieunsse merged 26 commits into
mainfrom
feature/team-create-page
Feb 19, 2026
Merged

의존성 픽스#55
Jieunsse merged 26 commits into
mainfrom
feature/team-create-page

Conversation

@Jieunsse

Copy link
Copy Markdown
Contributor

Summary

  • 이 PR에서 변경한 내용 한 줄 요약

Issue

  • Closes #

Scope

  • 포함

    • 변경한 내용
  • 특이사항

@Jieunsse Jieunsse merged commit be1a23b into main Feb 19, 2026
1 check failed
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @Jieunsse, 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은 사용자가 팀을 생성하거나 기존 팀에 참여할 수 있도록 하는 '팀 추가' 기능을 구현합니다. 이 기능은 새로운 UI 컴포넌트, React Query를 활용한 효율적인 데이터 관리, 그리고 API 통신을 위한 견고한 백엔드 통합을 포함합니다. 또한, 환경 변수 처리 로직을 개선하여 애플리케이션의 설정 관리와 개발 편의성을 높였습니다.

Highlights

  • 팀 생성 및 참여 기능 추가: 사용자가 새로운 팀을 생성하거나 기존 팀에 참여할 수 있는 기능이 추가되었습니다. 이를 위한 UI 컴포넌트와 관련 로직이 구현되었습니다.
  • React Query 통합: 데이터 페칭 및 상태 관리를 위해 @tanstack/react-query 라이브러리가 프로젝트에 통합되었습니다. 이를 통해 API 호출 및 캐싱 로직이 개선되었습니다.
  • 환경 변수 관리 개선: API 기본 URL 및 팀 ID와 같은 환경 변수의 유효성 검사 로직이 추가되었으며, 개발 환경에서 인증 헤더를 자동으로 추가하는 기능이 구현되었습니다.
  • API 모듈화 및 타입 정의: 그룹 관련 API 호출을 위한 모듈화된 함수들과 데이터 타입 정의가 추가되어 API 통신의 일관성과 안정성이 향상되었습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • .env.example
    • 예제 환경 변수 파일이 제거되었습니다.
  • package.json
    • @tanstack/react-query 의존성이 추가되었습니다.
  • src/app/addteam/_domain/components/CreateTeamCard.module.css
    • 팀 생성 카드 컴포넌트의 스타일이 추가되었습니다.
  • src/app/addteam/_domain/components/CreateTeamCard.tsx
    • 새로운 팀을 생성하기 위한 UI 컴포넌트가 추가되었습니다.
  • src/app/addteam/_domain/components/FeedbackMessage.module.css
    • 피드백 메시지 컴포넌트의 스타일이 추가되었습니다.
  • src/app/addteam/_domain/components/FeedbackMessage.tsx
    • 팀 생성 과정에서 사용자에게 피드백을 제공하는 컴포넌트가 추가되었습니다.
  • src/app/addteam/_domain/components/JoinTeamCard.module.css
    • 팀 참여 카드 컴포넌트의 스타일이 추가되었습니다.
  • src/app/addteam/_domain/components/JoinTeamCard.tsx
    • 기존 팀에 참여하기 위한 UI 컴포넌트가 추가되었습니다.
  • src/app/addteam/_domain/components/NoTeamState.module.css
    • 팀이 없는 상태를 표시하는 컴포넌트의 스타일이 추가되었습니다.
  • src/app/addteam/_domain/components/NoTeamState.tsx
    • 사용자가 소속된 팀이 없을 때 팀 생성 또는 참여를 유도하는 컴포넌트가 추가되었습니다.
  • src/app/addteam/_domain/constants/createTeam.ts
    • 팀 생성 관련 메시지 상수가 정의되었습니다.
  • src/app/addteam/_domain/hooks/useCreateTeam.ts
    • 팀 생성 로직을 캡슐화한 커스텀 훅이 추가되었습니다.
  • src/app/addteam/_domain/interfaces/feedback.ts
    • 팀 생성 피드백을 위한 TypeScript 인터페이스가 정의되었습니다.
  • src/app/addteam/_domain/styles/common.module.css
    • 공통 Flexbox 유틸리티 스타일이 추가되었습니다.
  • src/app/addteam/_domain/svg/noTeamImg.svg
    • 팀이 없는 상태를 나타내는 SVG 이미지가 추가되었습니다.
  • src/app/addteam/_domain/utils/duplicationCalculator.ts
    • 팀 이름 정규화 및 중복 검사를 위한 유틸리티 함수가 추가되었습니다.
  • src/app/addteam/_domain/utils/getCreateTeamFailureMessage.ts
    • 팀 생성 실패 시 에러 메시지를 처리하는 유틸리티 함수가 추가되었습니다.
  • src/app/addteam/create/page.tsx
    • 팀 생성 페이지가 구현되었습니다.
  • src/app/addteam/join/page.tsx
    • 팀 참여 페이지가 구현되었습니다.
  • src/app/addteam/layout.tsx
    • 팀 추가 기능 페이지를 위한 레이아웃이 정의되었습니다.
  • src/app/addteam/page.module.css
    • 팀 추가 페이지 및 레이아웃에 대한 모듈 스타일이 추가되었습니다.
  • src/app/addteam/page.tsx
    • 팀 추가 기능의 메인 페이지가 구현되었습니다.
  • src/app/layout.tsx
    • 애플리케이션 전반에 걸쳐 React Query Providers가 적용되었습니다.
  • src/app/providers.tsx
    • React Query QueryClientProvider를 설정하는 컴포넌트가 추가되었습니다.
  • src/shared/apis/config.ts
    • 환경 변수 NEXT_PUBLIC_API_BASE_URLNEXT_PUBLIC_API_TEAM_ID에 대한 유효성 검사 로직이 추가되었습니다.
  • src/shared/apis/fetchApi.ts
    • API 호출 유틸리티 fetchApi가 리팩토링되어 HTTP 메서드별 바디 처리, Content-Type 헤더 설정, 개발 환경 인증 토큰 자동 추가 기능이 개선되었습니다.
  • src/shared/apis/groups/group.ts
    • 그룹 생성 API 호출 함수가 추가되었습니다.
  • src/shared/apis/groups/http.ts
    • API 응답 처리 및 에러 핸들링을 위한 HTTP 유틸리티 함수가 추가되었습니다.
  • src/shared/apis/groups/invitation.ts
    • 그룹 초대 정보 조회 및 초대 수락 API 호출 함수가 추가되었습니다.
  • src/shared/apis/groups/member.ts
    • 그룹 멤버 추가, 조회, 삭제 API 호출 함수가 추가되었습니다.
  • src/shared/apis/groups/task.ts
    • 그룹 태스크 조회 API 호출 함수가 추가되었습니다.
  • src/shared/apis/groups/types.ts
    • 그룹 관련 API 요청 및 응답을 위한 TypeScript 인터페이스가 정의되었습니다.
  • src/shared/queries/groups/queryKeys.ts
    • React Query의 그룹 관련 쿼리 키가 정의되었습니다.
  • src/shared/queries/groups/useCreateGroupMutation.ts
    • 그룹 생성을 위한 React Query 뮤테이션 훅이 추가되었습니다.
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.

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

이 PR은 의존성 추가 외에 새로운 팀 생성 및 참여 기능을 구현하고 API 호출 로직을 개선하는 등 많은 변경 사항을 포함하고 있습니다. PR 제목을 "feat: 팀 생성 및 참여 기능 추가"와 같이 변경하면 변경 내용을 더 잘 나타낼 수 있을 것 같습니다.

전반적으로 코드 품질이 우수합니다. 특히 fetchApiconfig.ts의 리팩토링을 통해 API 연동 코드의 안정성과 개발 편의성이 크게 향상되었습니다. 또한 react-query를 도입하고 Providers, 쿼리 키 관리, 커스텀 뮤테이션 훅 등을 체계적으로 구성한 점이 인상적입니다.

다만, .env.example 파일이 삭제되어 새로운 개발자가 프로젝트를 설정할 때 어떤 환경 변수가 필요한지 파악하기 어려울 수 있습니다. 이 파일을 다시 추가하거나, README 등 다른 문서에 필요한 환경 변수 목록을 안내하는 것을 고려해보시는 것이 좋겠습니다.

몇 가지 개선점에 대한 리뷰 의견을 남겼으니 확인 부탁드립니다.

Comment on lines +1 to +42
'use client';

import { BaseButton } from '@/components/Button/base';
import { Input } from '@/components/input';
import joinCardStyles from './JoinTeamCard.module.css';
import clsx from 'clsx';
import commonStyles from '../styles/common.module.css';

interface JoinTeamCardProps {
teamLink: string;
onTeamLinkChange: (value: string) => void;
}

export default function JoinTeamCard({ teamLink, onTeamLinkChange }: JoinTeamCardProps) {
const helperTextId = 'join-team-helper-text';

return (
<div className={clsx(commonStyles.flexColCenter, joinCardStyles.joinCard)}>
<h2 className={joinCardStyles.title}>팀 참여하기</h2>

<div className={clsx(commonStyles.flexCol, joinCardStyles.joinInputSection)}>
<label htmlFor="team-link" className={joinCardStyles.joinLabel}>
팀 링크
</label>
<Input
id="team-link"
value={teamLink}
onChange={(event) => onTeamLinkChange(event.target.value)}
aria-describedby={helperTextId}
placeholder="팀 링크를 입력해주세요."
className={joinCardStyles.teamLinkInput}
/>
</div>

<BaseButton className={joinCardStyles.joinSubmitButton}>참여하기</BaseButton>

<p id={helperTextId} className={joinCardStyles.joinHelperText}>
공유받은 팀 링크를 입력해 참여할 수 있어요.
</p>
</div>
);
}

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.

critical

현재 JoinTeamCard 컴포넌트는 div로 구현되어 있고 '참여하기' 버튼에 onClick 핸들러나 type='submit' 속성이 없어 아무런 동작을 하지 않습니다. 사용자가 팀 링크를 입력하고 버튼을 클릭해도 아무 일도 일어나지 않아 기능이 동작하지 않는 상태입니다.

아래와 같이 컴포넌트를 <form>으로 감싸고 onSubmit 핸들러를 추가하여 이 문제를 해결할 수 있습니다. JoinTeamCardProps에도 onSubmit을 추가해야 하며, 부모 컴포넌트인 JoinTeamPage에서 실제 팀 참여 API를 호출하는 로직을 구현하여 전달해야 합니다.

'use client';

import { type FormEvent } from 'react';
import { BaseButton } from '@/components/Button/base';
import { Input } from '@/components/input';
import joinCardStyles from './JoinTeamCard.module.css';
import clsx from 'clsx';
import commonStyles from '../styles/common.module.css';

interface JoinTeamCardProps {
  teamLink: string;
  onTeamLinkChange: (value: string) => void;
  onSubmit: (e: FormEvent<HTMLFormElement>) => void;
}

export default function JoinTeamCard({ teamLink, onTeamLinkChange, onSubmit }: JoinTeamCardProps) {
  const helperTextId = 'join-team-helper-text';

  return (
    <form className={clsx(commonStyles.flexColCenter, joinCardStyles.joinCard)} onSubmit={onSubmit}>
      <h2 className={joinCardStyles.title}>팀 참여하기</h2>

      <div className={clsx(commonStyles.flexCol, joinCardStyles.joinInputSection)}>
        <label htmlFor="team-link" className={joinCardStyles.joinLabel}>
          팀 링크
        </label>
        <Input
          id="team-link"
          value={teamLink}
          onChange={(event) => onTeamLinkChange(event.target.value)}
          aria-describedby={helperTextId}
          placeholder="팀 링크를 입력해주세요."
          className={joinCardStyles.teamLinkInput}
        />
      </div>

      <BaseButton type="submit" className={joinCardStyles.joinSubmitButton}>
        참여하기
      </BaseButton>

      <p id={helperTextId} className={joinCardStyles.joinHelperText}>
        공유받은 팀 링크를 입력해 참여할 수 있어요.
      </p>
    </form>
  );
}

Comment on lines +11 to +38
export function getCreateTeamFailureMessage(error: unknown) {
if (!(error instanceof Error)) {
return CREATE_TEAM_MESSAGES.defaultFailure;
}

const { message } = error;

if (message === CREATE_TEAM_MESSAGES.emptyTeamNameError) {
return CREATE_TEAM_MESSAGES.emptyTeamNameError;
}

if (
message === CREATE_TEAM_MESSAGES.duplicatedTeamNameError ||
hasStatusMessage(message, DUPLICATED_STATUS)
) {
return CREATE_TEAM_MESSAGES.duplicatedTeamNameFailure;
}

if (hasStatusMessage(message, INVALID_REQUEST_STATUS)) {
return CREATE_TEAM_MESSAGES.invalidRequestFailure;
}

if (UNAUTHORIZED_STATUSES.some((status) => hasStatusMessage(message, status))) {
return CREATE_TEAM_MESSAGES.unauthorizedFailure;
}

return CREATE_TEAM_MESSAGES.defaultFailure;
}

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.

medium

API 에러를 처리할 때 error.message 문자열에 특정 상태 코드 문자열('status: 409' 등)이 포함되어 있는지 확인하는 방식은 불안정하며 유지보수가 어렵습니다. http.ts에서 에러 메시지 형식이 변경되면 이 로직이 예기치 않게 실패할 수 있습니다.

더 안정적인 방법은 http.ts에서 HTTP 상태 코드와 같은 구조화된 정보를 포함하는 커스텀 에러 클래스(예: ApiError)를 정의하고 throw하는 것입니다. 그러면 이 함수에서 instanceof로 에러 타입을 확인하고, error.status와 같이 타입-세이프하게 상태 코드에 접근할 수 있어 코드의 안정성과 가독성이 향상됩니다.

예시:

// In http.ts
export class ApiError extends Error {
  constructor(message: string, public readonly status: number) {
    super(message);
  }
}

// In getCreateTeamFailureMessage.ts
if (error instanceof ApiError) {
  if (error.status === 409) {
    return CREATE_TEAM_MESSAGES.duplicatedTeamNameFailure;
  }
  // ... other status code checks
}

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