Skip to content
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

[Api] axios, react-query setting #26

Merged
merged 30 commits into from
Jun 4, 2023
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e153b8e
Update common export&import
hyeongrok7874 May 25, 2023
d162b53
Update tsconfig
hyeongrok7874 May 25, 2023
a74fdd3
Update common
hyeongrok7874 May 25, 2023
4420a2d
Add api workspace
hyeongrok7874 May 25, 2023
e3791cf
Add api workspace
hyeongrok7874 May 25, 2023
dd6a627
Add urlController
hyeongrok7874 May 25, 2023
cd1348d
Add axios instance
hyeongrok7874 May 25, 2023
650d752
Add Post type
hyeongrok7874 May 25, 2023
6b8c207
Add queryClient
hyeongrok7874 May 26, 2023
452a93e
Add peerDependencies
hyeongrok7874 May 26, 2023
2a0e6ff
Update PostListType
hyeongrok7874 May 26, 2023
79be16f
Update ajax request function
hyeongrok7874 May 26, 2023
0379029
Add queryKeys
hyeongrok7874 May 26, 2023
d0be44d
Add dependency
hyeongrok7874 May 29, 2023
8afdcdc
Add admin setting
hyeongrok7874 May 29, 2023
b844861
Add useGetPostDetail
hyeongrok7874 May 29, 2023
02d0069
Add useGetPostList
hyeongrok7874 May 29, 2023
9fe6bb7
Add QueryClient & QueryDevtools
hyeongrok7874 May 29, 2023
e499925
Add example codes
hyeongrok7874 May 29, 2023
68d522f
Add .env.example
hyeongrok7874 May 30, 2023
2c7c056
Merge branch 'develop' into feature/axiosSetting
hyeongrok7874 May 31, 2023
0196a91
Update instance, client split
hyeongrok7874 May 31, 2023
52fe772
Update get post list fn
hyeongrok7874 Jun 2, 2023
18e4d3b
Merge branch 'develop' into feature/axiosSetting
hyeongrok7874 Jun 3, 2023
13ee8e1
Update api absolute path
hyeongrok7874 Jun 4, 2023
eee6740
Merge branch 'develop' into feature/axiosSetting
hyeongrok7874 Jun 4, 2023
4c98a2d
Update query client
hyeongrok7874 Jun 4, 2023
b135342
Update instance naming
hyeongrok7874 Jun 4, 2023
a9a9270
Add eslint in api workspace
hyeongrok7874 Jun 4, 2023
84b0f03
Add todo comment
hyeongrok7874 Jun 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/admin/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CLIENT_API_URL = 'client-api-url'
14 changes: 13 additions & 1 deletion apps/admin/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,22 @@
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
transpilePackages: ["ui", "common"],
transpilePackages: ["ui", "common", "api"],
compiler: {
emotion: true,
},
rewrites: async () => {
return [
{
source: "/api/client/:path*",
destination: `${process.env.CLIENT_API_URL}/api/:path*`,
},
// {
// source: "/api/admin/:path*",
// destination: `${process.env.ADMIN_API_URL}/api/:path*`,
// },
];
},
};

module.exports = nextConfig;
3 changes: 3 additions & 0 deletions apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
"dependencies": {
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@tanstack/react-query": "^4.29.7",
"@tanstack/react-query-devtools": "^4.29.7",
"@types/node": "20.1.4",
"@types/react": "18.2.6",
"@types/react-dom": "18.2.4",
"api": "workspace:^",
"common": "workspace:^",
"eslint": "8.40.0",
"next": "13.4.2",
Expand Down
12 changes: 9 additions & 3 deletions apps/admin/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"use client";

import GlobalStyle from "common/styles/GlobalStyle";
import { GlobalStyle } from "common";
import { queryClient } from "api/common";
import { QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";

export default function RootLayout({
children,
Expand All @@ -20,8 +23,11 @@ export default function RootLayout({
/>
</head>
<body>
<GlobalStyle />
{children}
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools />
<GlobalStyle />
{children}
</QueryClientProvider>
Copy link
Member

Choose a reason for hiding this comment

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

layout 에서 provider 컴포넌트를 사용하는게 일반적인 컨벤션인가요?

Copy link
Member Author

@hyeongrok7874 hyeongrok7874 Jun 3, 2023

Choose a reason for hiding this comment

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

react query - nextjs13

위 공식 문서 참고하시면 root layout에서 provider를 사용하는 것을 확인 하실 수 있습니다

단지 위 공식 문서와 제 방식의 차이점은

  • 공식 문서에서는 QueryClientProvider를 커스텀하여 모듈을 분리해 사용하고 있지만, 저는 별 다른 분리 없이 그대로 사용하였습니다
  • queryClient를 const [queryClient] = React.useState(() => new QueryClient()) 이런 형태로 선언하여,
    setter 함수를 선언하지 않음으로써 참조 동일성을 유지하고, 방식으로 작성되어 있습니다.

제가 이해한 공식문서에서 QueryClientProvider를 커스텀한 이유는 아래와 같습니다.

  • 'use client' 선언을 커스텀 QueryClientProvider 모듈에만 추가하기 위함
    • useState는 client component에서 사용 가능하기 때문 (server component에서는 사용할 수 없습니다.)
  • useState로 queryClient를 선언하기 위함
    • 참조 동일성을 유지하고, 서로 다른 사용자와 요청 간에 데이터를 공유하지 않고 구성 요소 수명 주기당 한 번만 QueryClient를 생성(공식 문서 인용)
  • <Hydrate> 사용을 위해 useState로 queryClient 선언이 필요하다.

현재 제 구성은 <Hydrate> 사용을 고려하지 못한 구성인 듯 하여 공식 문서대로 수정을 할 예정입니다.

Copy link
Member Author

@hyeongrok7874 hyeongrok7874 Jun 4, 2023

Choose a reason for hiding this comment

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

현재 제 구성은 <Hydrate> 사용을 고려하지 못한 구성인 듯 하여 공식 문서대로 수정을 할 예정입니다.

4c98a2d

추후 <Hydrate> 사용을 위한 방식으로 수정 완료했습니다!

</body>
</html>
);
Expand Down
9 changes: 9 additions & 0 deletions apps/admin/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
"use client";

import { Header } from "components";
import { useGetPostDetail, useGetPostList } from "api/client";

export default function Home() {
// example
const { data: postList, isLoading } = useGetPostList("NOTICE", 0);

const { data: postDetail } = useGetPostDetail(1);

console.log(postList);
console.log(postDetail);

return (
<div>
<Header hasNotification={false} name={"정문정"} />
Expand Down
1 change: 1 addition & 0 deletions apps/admin/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"jsx": "preserve",
"baseUrl": "./src",
"paths": {
"client": ["../../../packages/api/client"],
"admin/*": ["*"]
}
},
Expand Down
2 changes: 1 addition & 1 deletion apps/storybook/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Preview } from "@storybook/react";
import GlobalStyle from "common/styles/GlobalStyle";
import { GlobalStyle } from "common";
import React from "react";

const preview: Preview = {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"client": "pnpm --filter client",
"admin": "pnpm --filter admin",
"storybook": "pnpm --filter storybook",
"api": "pnpm --filter api",
"common": "pnpm --filter common",
"ui": "pnpm --filter ui",
"tsconfig": "pnpm --filter tsconfig",
Expand Down
1 change: 1 addition & 0 deletions packages/api/client/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./src";
1 change: 1 addition & 0 deletions packages/api/client/src/hooks/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./post";
2 changes: 2 additions & 0 deletions packages/api/client/src/hooks/api/post/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./useGetPostDetail";
export * from "./useGetPostList";
10 changes: 10 additions & 0 deletions packages/api/client/src/hooks/api/post/useGetPostDetail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useQuery } from "@tanstack/react-query";
import { postUrl, get, PostDetailType, postQueryKeys } from "client";

export const useGetPostDetail = (seq: number) => {
const query = useQuery<PostDetailType>(postQueryKeys.getPostDetail(seq), () =>
get(postUrl.postDetail(seq))
);

return query;
};
24 changes: 24 additions & 0 deletions packages/api/client/src/hooks/api/post/useGetPostList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useQuery } from "@tanstack/react-query";
import {
PostCategoryType,
PostListType,
get,
postQueryKeys,
postUrl,
} from "client";

export const useGetPostList = (
category: PostCategoryType,
pageNumber: number
) => {
const query = useQuery<PostListType>(
postQueryKeys.getPostList(category, pageNumber),
() => get(postUrl.postList(category, pageNumber)),
{
cacheTime: Infinity,
staleTime: Infinity,
}
);

return query;
};
1 change: 1 addition & 0 deletions packages/api/client/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./api";
3 changes: 3 additions & 0 deletions packages/api/client/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./hooks";
export * from "./libs";
export * from "./types";
34 changes: 34 additions & 0 deletions packages/api/client/src/libs/api/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { instance } from "./instance";

export const get = async (...args: Parameters<typeof instance.get>) => {
try {
const { data } = await instance.get(...args);
return data;
} catch (error) {
return error;
}
};

export const post = async <T>(...args: Parameters<typeof instance.post>) => {
try {
await instance.post<T>(...args);
} catch (error) {
return error;
}
};

export const patch = async <T>(...args: Parameters<typeof instance.patch>) => {
try {
await instance.patch<T>(...args);
} catch (error) {
return error;
}
};

export const del = async <T>(...args: Parameters<typeof instance.delete>) => {
try {
await instance.delete<T>(...args);
} catch (error) {
return error;
}
};
2 changes: 2 additions & 0 deletions packages/api/client/src/libs/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./client";
export * from "./instance";
6 changes: 6 additions & 0 deletions packages/api/client/src/libs/api/instance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import axios from "axios";

export const instance = axios.create({
baseURL: "/api/client",
Copy link
Member

Choose a reason for hiding this comment

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

dev와 Prod의 base url이 동일한가요?

그리고 instance라는 네이밍은 너무 포괄적이군요

Copy link
Member Author

@hyeongrok7874 hyeongrok7874 Jun 3, 2023

Choose a reason for hiding this comment

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

dev와 Prod의 base url이 동일한가요?

baseUrl 관리는 next.config.js에서 하고 있고,
현재는 test 서버만 존재하기 때문에 prod, dev baseUrl 조건식을 작성해놓지 않았습니다.

해당 설정은 클라이언트(프론트)의 주소 (ex. localhost:3000/api/client)로 요청을 보내도록 작성한 코드입니다.

next.config.jsrewrites 속성으로 인해,
클라이언트(프론트)/api/client/*로 요청 시, 클라이언트 서비스 서버/api/*로 요청이 rewrites 되게끔 구성되어 있는 상태입니다.

next-config-js/rewrites

Copy link
Member Author

Choose a reason for hiding this comment

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

instance라는 네이밍은 너무 포괄적이군요

https://axios-http.com/kr/docs/instance

공식 문서나 여러 소스 코드들을 살펴보았을 때, instance라는 네이밍이 일반적인 듯 하여 이렇게 작성했습니다!

좀 더 의도가 명확한 네이밍 (ex. clientInstance) 으로 변경하는게 아무래도 직관적인 듯 하여 수정하겠습니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

좀 더 의도가 명확한 네이밍 (ex. clientInstance) 으로 변경하는게 아무래도 직관적인 듯 하여 수정하겠습니다!

b135342

수정 완료했습니다!

withCredentials: true,
});
7 changes: 7 additions & 0 deletions packages/api/client/src/libs/clientUrlController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { PostCategoryType } from "../types";

hyeongrok7874 marked this conversation as resolved.
Show resolved Hide resolved
export const postUrl = {
postList: (category: PostCategoryType, pageNumber: number) =>
`/post?category=${category}&pageNumber=${pageNumber}`,
postDetail: (postSeq: number) => `/post/${postSeq}`,
} as const;
3 changes: 3 additions & 0 deletions packages/api/client/src/libs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./clientUrlController";
export * from "./api";
export * from "./queryKeys";
11 changes: 11 additions & 0 deletions packages/api/client/src/libs/queryKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { PostCategoryType } from "client";

export const postQueryKeys = {
getPostList: (category: PostCategoryType, pageNumber: number) => [
"post",
"list",
category,
pageNumber,
],
getPostDetail: (postSeq: number) => ["post", "detail", postSeq],
};
1 change: 1 addition & 0 deletions packages/api/client/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./post";
28 changes: 28 additions & 0 deletions packages/api/client/src/types/post/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export type PostCategoryType = "NOTICE" | "FAMILY_NEWSLETTER" | "EVENT_GALLERY";

export interface PostDetailType {
postTitle: string;
postWriter: string;
postContent: string;
createdAt: string;
fileInfo: FileInfoType[];
}

interface FileInfoType {
fileUrl: string;
fileName: string;
fileExtension: string;
}

export interface PostListType {
content: ContentType[];
}

export interface ContentType {
postSeq: number;
postTitle: string;
postWriter: string;
createdAt: string;
thumbnailUrl: string;
fileIsExist: boolean;
}
1 change: 1 addition & 0 deletions packages/api/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./src";
1 change: 1 addition & 0 deletions packages/api/common/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./libs";
1 change: 1 addition & 0 deletions packages/api/common/src/libs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./queryClient";
5 changes: 5 additions & 0 deletions packages/api/common/src/libs/queryClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { QueryClient } from "@tanstack/react-query";

export const queryClient = new QueryClient({
// defaultOptions: {},
});
15 changes: 15 additions & 0 deletions packages/api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "api",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@types/node": "20.1.4",
"axios": "^1.4.0"
},
"devDependencies": {
"tsconfig": "workspace:^"
},
"peerDependencies": {
"@tanstack/react-query": "^4.29.7"
}
}
9 changes: 9 additions & 0 deletions packages/api/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "tsconfig/base.json",
"compilerOptions": {
"rootDir": ".",
"baseUrl": "."
},
"include": ["**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
1 change: 1 addition & 0 deletions packages/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./src";
2 changes: 1 addition & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "common",
"version": "0.0.0",
"private": true,
"license": "MIT",
"main": "./index.ts",
"dependencies": {
"@emotion/react": "^11.10.6",
"emotion-reset": "^3.0.1",
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./styles";
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Global, css } from "@emotion/react";
import emotionReset from "emotion-reset";

export default function GlobalStyle() {
export const GlobalStyle = () => {
return (
<Global
styles={css`
Expand Down Expand Up @@ -29,4 +29,4 @@ export default function GlobalStyle() {
`}
/>
);
}
};
1 change: 1 addition & 0 deletions packages/common/src/styles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./GlobalStyle";
3 changes: 1 addition & 2 deletions packages/tsconfig/base.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "es5",
"target": "es6",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
Expand Down
1 change: 1 addition & 0 deletions packages/tsconfig/nextjs.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"compilerOptions": {
"jsxImportSource": "@emotion/react",
"jsx": "preserve",
"noEmit": true,
"plugins": [
{
"name": "next"
Expand Down
Loading