-
Notifications
You must be signed in to change notification settings - Fork 0
chore: 프로젝트 초기 세팅 추가 (Orval, commitlint, Gemini Code Assist, CodeRabbit) #2
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
base: main
Are you sure you want to change the base?
Conversation
- orval 패키지 설치 및 설정 파일 생성 - React Query 통합 설정 (tags-split 모드) - 커스텀 fetch 인스턴스 생성 (src/lib/api-client.ts) - package.json에 codegen 스크립트 추가
- @commitlint/cli, @commitlint/config-conventional 설치 - commitlint.config.js 설정 (기존 type 컨벤션 유지) - .husky/commit-msg 훅을 commitlint로 대체
- .gemini/config.yml 생성 (리뷰 설정 및 무시 패턴) - .gemini/styleguide.md 생성 (팀 코딩 컨벤션 가이드)
Summary of ChangesHello @tnemnorivnelee, 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은 개발 생산성과 코드 품질을 향상시키기 위한 초기 환경 설정을 추가합니다. Orval을 통해 API 클라이언트 코드 자동 생성 워크플로우를 구축하고, Commitlint를 도입하여 일관된 커밋 메시지 컨벤션을 강제합니다. 또한, Gemini Code Assist를 설정하여 AI 기반의 코드 리뷰 및 스타일 가이드 적용을 지원합니다. 이러한 변경사항들은 개발 초기 단계부터 효율적이고 체계적인 코드 관리를 가능하게 합니다. Highlights
🧠 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. Ignored Files
Using Gemini Code AssistThe 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
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 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
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. 📝 WalkthroughWalkthroughOrval 기반 API 코드 생성 설정, 커스텀 API 클라이언트 구현, commitlint·husky 커밋 규칙 추가, Gemini/CodeRabbit AI 리뷰 설정 및 스타일 가이드 문서가 새로 추가되었습니다. package 스크립트와 devDependencies도 관련 도구로 업데이트되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Browser as Client (React Component)
participant RQ as React Query Hook
participant Gen as Generated API (orval)
participant ClientLib as customInstance
participant API as External API Server
Browser->>RQ: useQuery/useMutation 호출
RQ->>Gen: generated function 호출 (e.g., getUsers)
Gen->>ClientLib: 요청 구성 전달 (url, method, params, data, headers, signal)
ClientLib->>API: HTTP 요청 (fetch)
API-->>ClientLib: HTTP 응답 (JSON / error)
ClientLib-->>Gen: 파싱된 응답 또는 예외
Gen-->>RQ: 결과 반환
RQ-->>Browser: 데이터/에러 제공
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
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.
Code Review
이 PR은 Orval을 사용한 API 코드 자동 생성, commitlint를 사용한 커밋 메시지 린트, Gemini Code Assist 설정을 포함한 프로젝트 초기 세팅을 추가합니다. 전반적으로 개발 생산성과 코드 품질 향상에 기여하는 좋은 변경 사항입니다. 특히 기존 쉘 스크립트 기반의 커밋 메시지 검증을 표준화된 commitlint로 전환한 점은 유지보수성을 크게 향상시킬 것입니다.
| import { defineConfig } from "orval"; | ||
|
|
||
| export default defineConfig({ | ||
| gak: { |
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.
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.
defineconfig 작업할 때 최상위 key naming이 프로젝트 이름이 되어야 하는 건가요?
| headers, | ||
| signal, | ||
| }: RequestConfig): Promise<T> => { | ||
| const baseURL = process.env.NEXT_PUBLIC_API_URL ?? ""; |
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.
baseURL이 process.env.NEXT_PUBLIC_API_URL에서 가져오고, 환경 변수가 설정되지 않은 경우 빈 문자열로 대체됩니다. baseURL이 빈 문자열인 경우 상대 경로로 요청이 전송될 수 있으며, 이는 예상치 못한 동작을 유발할 수 있습니다. 환경 변수가 필수적이라면, 명시적으로 오류를 발생시키거나 개발 환경을 위한 유효한 기본 URL을 제공하는 것이 더 안전합니다.
| const baseURL = process.env.NEXT_PUBLIC_API_URL ?? ""; | |
| const baseURL = process.env.NEXT_PUBLIC_API_URL; | |
| if (!baseURL) { | |
| throw new Error("NEXT_PUBLIC_API_URL is not defined in environment variables."); | |
| } |
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.
그냥 Null 병합 연산자를 쓰기보단 Non-null assertion operator를 쓰는게 좋을 거 같아요. 휴먼에러가 아닌 이상 해당 환경변수는 무조건 있는 건데 단지 typescript가 이거 null 아님? 하는거니까요.
| "Content-Type": "application/json", | ||
| ...headers, |
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.
모든 요청에 Content-Type: application/json 헤더가 기본으로 설정되어 있습니다. 대부분의 REST API 요청에는 적합하지만, 파일 업로드와 같이 다른 Content-Type이 필요한 경우 문제가 될 수 있습니다. data의 존재 여부나 method에 따라 Content-Type을 조건부로 설정하거나, headers prop에서 Content-Type을 완전히 제어할 수 있도록 하는 것이 더 유연할 수 있습니다.
headers: {
...(data && { "Content-Type": "application/json" }),
...headers,
},| throw new Error(`HTTP error! status: ${response.status}`); | ||
| } | ||
|
|
||
| return response.json(); |
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.
response.json() 호출은 응답 본문이 항상 JSON 형식이라고 가정합니다. 만약 API가 JSON이 아닌 형식(예: 일반 텍스트, HTML)의 오류 응답을 반환하는 경우, response.json()은 파싱 오류를 발생시켜 원래의 HTTP 오류 메시지를 가릴 수 있습니다. 응답의 Content-Type 헤더를 확인하여 JSON 파싱을 시도하기 전에 응답 형식을 검증하는 것이 좋습니다.
const contentType = response.headers.get("content-type");
if (contentType && contentType.includes("application/json")) {
return response.json();
} else {
return response.text() as Promise<T>; // 또는 다른 적절한 처리
}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.
이부분은 동의합니다. contentType에 따라서 Discriminated Union 형식으로 함수 구성을 하는 것도 좋을 거 같습니다.
type FetchResponse<T> =
| { status: 'success'; type: 'json'; data: T }
| { status: 'success'; type: 'text'; data: string }
| { status: 'error'; message: string };
async function safeFetch<T>(url: string): Promise<FetchResponse<T>> {
try {
const response = await fetch(url);
// 1. HTTP 에러 상태 처리
if (!response.ok) {
return { status: 'error', message: `HTTP Error: ${response.status}` };
}
const contentType = response.headers.get("content-type");
// 2. JSON 응답 처리
if (contentType?.includes("application/json")) {
const data = await response.json();
return { status: 'success', type: 'json', data };
}
// 3. 일반 텍스트 응답 처리
const textData = await response.text();
return { status: 'success', type: 'text', data: textData };
} catch (e) {
// 4. 네트워크 단절 등 예상치 못한 에러 처리
return { status: 'error', message: e instanceof Error ? e.message : 'Unknown error' };
}
}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.
Pull request overview
This PR sets up foundational development tools for the project to improve code quality and productivity. It adds Orval for API code generation, commitlint for enforcing commit message conventions, and Gemini Code Assist for automated code reviews.
Changes:
- Added Orval configuration with React Query integration for automated API client generation
- Replaced the shell script-based commit message validation with commitlint using conventional commits
- Added Gemini Code Assist configuration with team coding conventions in Korean
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/api-client.ts | Custom fetch instance for Orval-generated API calls with error handling and query parameter support |
| package.json | Added orval, commitlint dependencies and codegen script |
| orval.config.ts | Orval configuration for React Query client generation with custom mutator |
| commitlint.config.js | Commit message linting rules maintaining existing type conventions |
| .husky/commit-msg | Simplified to use commitlint instead of custom shell script |
| .gemini/styleguide.md | Team coding conventions and best practices guide in Korean |
| .gemini/config.yml | Gemini Code Assist configuration for PR summaries and code reviews |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (!response.ok) { | ||
| throw new Error(`HTTP error! status: ${response.status}`); | ||
| } |
Copilot
AI
Jan 21, 2026
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.
The error handling only throws a generic error message with the status code. Consider creating a custom error class that includes the response body, status code, and other useful debugging information. This will make it easier to handle different error scenarios in the application.
| throw new Error(`HTTP error! status: ${response.status}`); | ||
| } | ||
|
|
||
| return response.json(); |
Copilot
AI
Jan 21, 2026
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.
The response is always parsed as JSON with response.json(), but there's no handling for empty responses (204 No Content) or non-JSON responses. This will cause errors for endpoints that don't return JSON. Consider checking the content-type header or response status before parsing.
| return response.json(); | |
| // Handle empty or non-JSON responses safely | |
| if (response.status === 204 || response.status === 205) { | |
| return undefined as T; | |
| } | |
| const contentType = response.headers.get("content-type") || ""; | |
| // If the response is not JSON, return undefined to avoid parsing errors | |
| if (!contentType.toLowerCase().includes("application/json")) { | |
| return undefined as T; | |
| } | |
| // Read as text first to gracefully handle empty bodies | |
| const text = await response.text(); | |
| if (!text) { | |
| return undefined as T; | |
| } | |
| return JSON.parse(text) as T; |
| const searchParams = new URLSearchParams(params); | ||
| const queryString = searchParams.toString(); |
Copilot
AI
Jan 21, 2026
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.
When params is undefined, new URLSearchParams(undefined) is called which creates an empty URLSearchParams object. While this works, it would be clearer to check if params exists before creating the URLSearchParams instance to avoid unnecessary object creation.
| const searchParams = new URLSearchParams(params); | |
| const queryString = searchParams.toString(); | |
| const queryString = params ? new URLSearchParams(params).toString() : ""; |
|
|
||
| export default defineConfig({ | ||
| gak: { | ||
| input: { | ||
| // TODO: 백엔드에서 제공하는 Swagger/OpenAPI 명세 URL 또는 파일 경로로 변경 | ||
| target: "./swagger.json", |
Copilot
AI
Jan 21, 2026
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.
The target points to a non-existent file ./swagger.json. While the TODO comment mentions this should be updated, it would be better to either use a placeholder URL that won't cause errors when running the command, or add a check in the codegen script to ensure the file exists before running orval.
| export default defineConfig({ | |
| gak: { | |
| input: { | |
| // TODO: 백엔드에서 제공하는 Swagger/OpenAPI 명세 URL 또는 파일 경로로 변경 | |
| target: "./swagger.json", | |
| import { existsSync } from "fs"; | |
| const SWAGGER_FILE_PATH = "./swagger.json"; | |
| const FALLBACK_OPENAPI_URL = "https://example.com/openapi.json"; | |
| export default defineConfig({ | |
| gak: { | |
| input: { | |
| // TODO: 백엔드에서 제공하는 Swagger/OpenAPI 명세 URL 또는 파일 경로로 변경 | |
| target: existsSync(SWAGGER_FILE_PATH) ? SWAGGER_FILE_PATH : FALLBACK_OPENAPI_URL, |
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.
저도 이부분은 동의합니다. 상수로 빼서 누구나 명확하게 이게 무엇인지 아는 것이 좋을 거 같습니다.
| ], | ||
| "subject-empty": [2, "never"], | ||
| "type-empty": [2, "never"], | ||
| // 한국어 커밋 메시지 및 고유명사 사용을 위해 비활성화 |
Copilot
AI
Jan 21, 2026
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.
The comment on line 24 mentions "한국어 커밋 메시지" (Korean commit messages), but the rules don't explicitly allow or enforce Korean characters in commit messages. Consider adding a comment clarifying that Korean is allowed in the subject, or adding an explicit rule if needed.
| // 한국어 커밋 메시지 및 고유명사 사용을 위해 비활성화 | |
| // 한국어 커밋 메시지 및 고유명사에 대한 대소문자 강제 규칙을 비활성화 (문자 종류는 제한하지 않음) |
| headers, | ||
| signal, | ||
| }: RequestConfig): Promise<T> => { | ||
| const baseURL = process.env.NEXT_PUBLIC_API_URL ?? ""; |
Copilot
AI
Jan 21, 2026
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.
The api-client.ts uses process.env.NEXT_PUBLIC_API_URL but there is no .env.example file documenting this required environment variable. Consider creating a .env.example file that includes NEXT_PUBLIC_API_URL with a placeholder value to help developers set up their environment correctly.
| type RequestConfig = { | ||
| url: string; | ||
| method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; | ||
| params?: Record<string, string>; |
Copilot
AI
Jan 21, 2026
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.
The params parameter should allow Record<string, any> or Record<string, string | number | boolean> instead of only Record<string, string>. URLSearchParams will convert values to strings anyway, but the type definition is overly restrictive and may cause TypeScript errors when passing numeric IDs or boolean flags as query parameters.
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.
parms를 받을 때 URLSeacchParams를 변환하는 함수를 추후에 추가하면 좋겠네요.
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.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/lib/api-client.ts`:
- Around line 37-42: The code currently always calls response.json(), which will
throw on empty responses like 204 No Content; update the response handling in
the function that checks response.ok to detect empty responses (e.g., if
response.status === 204 or response.headers.get('Content-Length') === '0') and
return null (or an appropriate empty value) instead of calling response.json();
otherwise proceed to return response.json() as before—use the existing response
variable and the same error throw for !response.ok.
🧹 Nitpick comments (3)
.husky/commit-msg (1)
2-2: Quote the shell variable for robustness.The
$1argument should be quoted to handle paths with spaces correctly.🔧 Suggested fix
#!/bin/sh -pnpm exec commitlint --edit $1 +pnpm exec commitlint --edit "$1"src/lib/api-client.ts (2)
27-35: Consider omitting body for GET requests.Setting a body on GET requests, while technically not forbidden, is ignored by most servers and can cause issues with some proxies or CDNs. Additionally, the
Content-Type: application/jsonheader is unnecessary for bodyless requests.♻️ Suggested improvement
const response = await fetch(fullUrl, { method, - headers: { - "Content-Type": "application/json", - ...headers, - }, - body: data ? JSON.stringify(data) : undefined, + headers: + data !== undefined + ? { + "Content-Type": "application/json", + ...headers, + } + : headers, + body: data !== undefined ? JSON.stringify(data) : undefined, signal, });
3-10: Consider makingparamstype more flexible.The current
Record<string, string>type doesn't handleundefinedvalues that might come from optional parameters. This could cause type errors when using the generated Orval code.♻️ Suggested type improvement
type RequestConfig = { url: string; method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; - params?: Record<string, string>; + params?: Record<string, string | undefined>; data?: unknown; headers?: HeadersInit; signal?: AbortSignal; };Then filter out undefined values when building URLSearchParams:
- const searchParams = new URLSearchParams(params); + const searchParams = new URLSearchParams( + Object.entries(params ?? {}).filter(([, v]) => v !== undefined) as [string, string][] + );
- .coderabbit.yaml 생성 (한국어 리뷰, 파일별 리뷰 지침) - 프로젝트 기술 스택에 맞는 린트 도구 설정
작업 내용
개발 생산성 및 코드 품질 향상을 위한 도구 세팅을 추가했습니다.
1. Orval 설정 (API 코드 자동 생성)
orval패키지 설치codegen스크립트 추가2. commitlint 설정 (커밋 메시지 린트)
@commitlint/cli,@commitlint/config-conventional설치3. Gemini Code Assist 설정 (AI 코드 리뷰)
4. CodeRabbit 설정
@coderabbitai review명령어로 수동 리뷰 요청 가능참고 사항
target경로를 수정 후pnpm codegen실행연관 이슈
close #1
Summary by CodeRabbit
Chores
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.