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

feat: login #13

Merged
merged 4 commits into from
Mar 5, 2023
Merged

feat: login #13

merged 4 commits into from
Mar 5, 2023

Conversation

chaaerim
Copy link
Member

๐Ÿš€ ์ž‘์—… ๋‚ด์šฉ

  • ๋กœ๊ทธ์ธ ๋กœ์ง์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์—๋Ÿฌ ์ฒ˜๋ฆฌ๋ฅผ ๋ณด๋‹ค ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก axios ์—๋Ÿฌ๋ฅผ ์ปค์Šคํ…€ํ–ˆ์Šต๋‹ˆ๋‹ค.

โœ๏ธ ์ƒ์„ธ ์„ค๋ช…

  • ํ† ํฐ์€ localStorage์— ์ €์žฅํ•˜๊ณ  ํ—ค๋”์— ๋„ฃ์–ด ์„œ๋ฒ„์™€ ํ†ต์‹ ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • axios response interceptors๋ฅผ ์ด์šฉํ•˜์—ฌ aT์™€ rT ๋งŒ๋ฃŒ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ณ ์ž ํ–ˆ๋Š”๋ฐ ์ด ๋ถ€๋ถ„์€ api ์ž‘์—…์ด ๋งˆ๋ฌด๋ฆฌ๋˜๊ณ  ์ถ”๊ฐ€ํ•ด๋‘๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ“ท ์Šคํฌ๋ฆฐ์ƒท

๐Ÿ“ ์ฐธ๊ณ  ์ž๋ฃŒ

@github-actions github-actions bot added the Type: Feature ์œ ํ˜•: ๊ธฐ๋Šฅ ์ถ”๊ฐ€ label Feb 26, 2023
Copy link

@be-student be-student left a comment

Choose a reason for hiding this comment

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

์™€ ์ง„์งœ ์‹ ๊ธฐํ–ˆ์–ด์š” ๋งŽ์ด ๋ฐฐ์›Œ๊ฐ‘๋‹ˆ๋‹ค!!!
๋˜๊ฒŒ ์„ธ์‹ฌํ•œ ๋ถ€๋ถ„๊นŒ์ง€ ๋‹ค ํ•˜๋‚˜ํ•˜๋‚˜ ์‹ ๊ฒฝ์จ์ฃผ์‹œ๋„ค์š”

baseURL: process.env.NODE_ENV === 'development' ? DEV_SERVER_URL : PROD_SERVER_URL,
headers: {
Authorization: `Bearer ${authToken.access}`,
'Content-Type': 'application/json; charset=utf-8',

Choose a reason for hiding this comment

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

์™€ ์ด๊ฑธ ๋‹ค ์‹ ๊ฒฝ์จ์ฃผ์‹œ๋„ค์š” ์ €๊ฑฐ ์“ฐ๋Š” ๊ฒƒ ์ฒ˜์Œ๋ด์š”

Copy link
Member

Choose a reason for hiding this comment

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

๐Ÿ‘๐Ÿ‘๐Ÿ‘

Comment on lines +51 to 55
try {
return (error as EffError).isEffError === true;
} catch {
return false;
}

Choose a reason for hiding this comment

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

error ๊ฐ€ null ์ด ๋“ค์–ด์˜ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด

return (error as EffError).isEffError===true;

์ด๋ ‡๊ฒŒ ์ ์–ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”

Copy link
Member

Choose a reason for hiding this comment

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

์กฐ๊ธˆ ๋” ์ค„์ผ ์ˆ˜ ์žˆ์„ ๊ฑฐ ๊ฐ™์•„์š”!

return (error as EffError).isEffError; 

Choose a reason for hiding this comment

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

์ด๋ ‡๊ฒŒ ๋˜์—ˆ์„ ๋•Œ, isEffError ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด undefined ๊ฐ™์€ ๊ฐ’์ด ์˜ฌ ์ˆ˜๋„ ์žˆ๊ณ , ๋งŒ์•ฝ ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์—ˆ๋‹ค๋ฉด, isEffError ์— ์ด์ƒํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ด๊ฒจ์„œ ์˜ฌ ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์š” as ๋กœ ์บ์ŠคํŒ… ํ•œ ์ดํ›„์— ๊ฐ€์ ธ์˜ค๋‹ˆ๊นŒ์š”
๊ทธ๋ž˜์„œ ๊ฒ€์ฆ ๊ณผ์ •์œผ๋กœ ===true ๋ฅผ ๋ถ™ํžˆ๋Š” ์ชฝ์ด ์ข‹์•„๋ณด์—ฌ์š”

Copy link
Member

Choose a reason for hiding this comment

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

ํƒ€์ž… ๋‹จ์–ธ ๋•Œ๋ฌธ์ด๊ตฐ์š”~ ํ™•์‹คํžˆ as ์‚ฌ์šฉ ๋•Œ๋ฌธ์— ์• ๋งคํ•  ์ˆ˜ ์žˆ๊ฒ ๋„ค์š” === true๋กœ ์ฒดํฌํ•ด์ฃผ๋Š”๊ฒŒ ๋” ํ™•์‹คํ•˜๊ฒ ๋„ค์š” ๐Ÿ‘€

Copy link
Member Author

Choose a reason for hiding this comment

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

๋„ต ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์€ ์ค„์—ฌ๋ณผ๊ฒŒ์š” !

error: unknown
): error is AxiosError & { response: AxiosResponse } {
try {
return axios.isAxiosError(error) && error.response?.data != null;

Choose a reason for hiding this comment

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

์—ฌ๊ธฐ๋„ try catch ๋ฌธ์ด ์—†์–ด๋„ ๊ดœ์ฐฎ์„ ๊ฒƒ ๊ฐ™์•„์š”!

return axios.isAxiosError(error)&&error.response?.data!==null;

Copy link
Member Author

Choose a reason for hiding this comment

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

axios ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์—๋Ÿฌ๊ฐ€ ๋‚ฌ์„ ๋•Œ ๋” ์ด์ƒ ๋‹ค์Œ ๋™์ž‘์ด ์‹คํ–‰์ด ์•ˆ๋˜๋Š”๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์–ด์„œ ๊ผผ๊ผผํ•˜๊ฒŒ try catch๋กœ ์ฒ˜๋ฆฌํ•˜๋ ค๊ณ  ํ–ˆ๋Š”๋ฐ ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง„ ๊ฐ์ด ์žˆ๊ตฐ์š” ์—ฌ๊ธฐ๋„ ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„์€ ์ค„์—ฌ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค!

if (config?.headers == null) {
throw new Error(`config.header is undefined`);
}
config.headers['Content-Type'] = 'application/json; charset=utf-8';

Choose a reason for hiding this comment

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

์™€ ์—ฌ๊ธฐ๋„ ๋ฉ‹์žˆ๋„ค์š”

Copy link
Member Author

Choose a reason for hiding this comment

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

์•„ํœด ์•„๋‹™๋‹ˆ๋‹ค ํ—ˆํ—ˆ ..

baseURL: process.env.NODE_ENV === 'development' ? DEV_SERVER_URL : PROD_SERVER_URL,
headers: {
Authorization: `Bearer ${authToken.access}`,
'Content-Type': 'application/json; charset=utf-8',
Copy link
Member

Choose a reason for hiding this comment

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

๐Ÿ‘๐Ÿ‘๐Ÿ‘

Comment on lines +51 to 55
try {
return (error as EffError).isEffError === true;
} catch {
return false;
}
Copy link
Member

Choose a reason for hiding this comment

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

์กฐ๊ธˆ ๋” ์ค„์ผ ์ˆ˜ ์žˆ์„ ๊ฑฐ ๊ฐ™์•„์š”!

return (error as EffError).isEffError; 

Comment on lines +69 to +72
//axios์—๋Ÿฌ๋ฅผ ์ปค์Šคํ…€ํ•œ ์—๋Ÿฌ๋กœ ๋ณ€ํ™˜
function createEffErrorFromAxiosError(error: AxiosError): EffErrorResponse | AxiosError {
if (isAxiosErrorWithResponseData(error)) {
const effError = error as EffError;
Copy link
Member

Choose a reason for hiding this comment

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

์—๋Ÿฌ ํ™•์ธํ•˜๊ณ  ์ปค์Šคํ…€ ์—๋Ÿฌ ๋งŒ๋“œ๋Š” ๋กœ์ง๋“ค์€ ๋”ฐ๋กœ apisํด๋” ์•ˆ์— utils ํŒŒ์ผ ๊ฐ™์€๊ฑฐ๋กœ ๋”ฐ๋กœ ์ •๋ฆฌํ•ด๋„ ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”!

๋„ค์ด๋ฐ์ด ๋ช…ํ™•ํžˆ ์ž˜๋˜์–ด ์žˆ๊ณ  ๋™์ž‘๋„ ๊ฐ„๋‹จํ•ด์„œ ๊ตณ์ด ํ•˜๋‚˜์”ฉ ์ฝ์œผ๋ฉด์„œ ํ™•์ธํ•  ํ•„์š” ์—†์„ ๊ฑฐ ๊ฐ™์•„์š”.

Comment on lines +94 to +103
axiosClient.interceptors.request.use(
function (config) {
if (config?.headers == null) {
throw new Error(`config.header is undefined`);
}
config.headers['Content-Type'] = 'application/json; charset=utf-8';
config.headers['Authorization'] = authToken.access;

export const patch = <T>(...args: Parameters<typeof axiosClient.patch>) => {
return axiosClient.patch<T, T>(...args);
};
return config;
},
Copy link
Member

Choose a reason for hiding this comment

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

isAxiosErrorWithResponseData ์ฒ˜๋Ÿผ ์•ˆ์— ํ•จ์ˆ˜๋„ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•ด์ฃผ๋ฉด ์ถ”์ƒํ™” ๋‹จ๊ณ„๊ฐ€ ๋™์ผํ•ด์„œ ๋” ์ฝ๊ธฐ ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”!

๊ทธ๋ฆฌ๊ณ  axiosClient๋ฅผ ์ƒ์„ฑํ•  ๋•Œ Content-Type๊ณผ Authorization๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋Š”๋ฐ ๋”ฐ๋กœ ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ํ†ตํ•ด ๋„ฃ์–ด์ฃผ๋Š” ์ด์œ ๊ฐ€ ์žˆ์„๊นŒ์š”?

Copy link
Member Author

Choose a reason for hiding this comment

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

request ์š”์ฒญ์‹œ ํ˜น์‹œ ๋ชจ๋ฅด๊ฒŒ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” auth์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ request์—์„œ ํ•œ ๋ฒˆ ๋” ์ฒ˜๋ฆฌํ•ด์ฃผ๋ ค๊ณ  ํ–ˆ์–ด์š” !

Comment on lines +125 to +127
function delay(time: number) {
return new Promise(res => setTimeout(res, time));
}
Copy link
Member

Choose a reason for hiding this comment

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

delay๋Š” ์ด๊ณณ ์ €๊ณณ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ ๊ฐ™์•„์„œ ๋”ฐ๋กœ utils ํด๋”๋กœ ๋ถ„๋ฆฌํ•˜๋ฉด ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”~!

Copy link
Member Author

Choose a reason for hiding this comment

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

๋„ต axios ํ•˜๋‹จ์— utils ํด๋” ํ•˜๋‚˜ ์ƒ์„ฑํ•ด๋‘๊ฒ ์Šต๋‹ˆ๋‹น

src/apis/client.ts Show resolved Hide resolved
Comment on lines 23 to 26
<Button variant="largePrimary" onClick={onClick}>
ํ™•์ธ
</Button>
</>
Copy link
Member

Choose a reason for hiding this comment

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

๐Ÿ‘๐Ÿ‘ CD๊ฐ€ ๋Œ์•„๊ฐ€๊ฒ ๊ตฐ์š”~~

const isDisabled = !isDirty || !isValid;

const isRequiredText = useCallback(
(text: string) => (text === '๋น„๋ฐ€๋ฒˆํ˜ธ' ? `${text}๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.` : `${text}์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.`),
Copy link
Member

Choose a reason for hiding this comment

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

(text: string) => `${text}๋ฅผ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.`

์ด๋ ‡๊ฒŒ ํ‘œํ˜„ํ•ด๋„ ๊ดœ์ฐฎ์ง€ ์•Š๋‚˜์š”!?

Copy link
Member Author

Choose a reason for hiding this comment

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

๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฐ™์€ ๊ฒฝ์šฐ ๋’ค์— ๋ฅผ์ด ๋“ค์–ด๊ฐ€์•ผํ•˜๊ณ  ์ด๋ฉ”์ผ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์„์ด ๋“ค์–ด๊ฐ€์•ผํ•ด์„œ ์š”๋ ‡๊ฒŒ ์ฒ˜๋ฆฌํ–ˆ์–ด์š” ํ—ˆํ—ˆ

Copy link
Member

Choose a reason for hiding this comment

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

์•„ํ•˜ ์„,๋ฅผ ์ฐจ์ด๋ฅผ ์ œ๊ฐ€ ๋ชป ๋ดค์—ˆ๋„ค์š”..!

Comment on lines +42 to +58
const { mutate: loginMutation } = useMutation(async () => {
const { email, password } = getValues();
try {
const data = await postLogin(email, password);
if (data) {
const { accessToken, refreshToken } = data;
localStorage.setItem('accessToken', accessToken);
localStorage.setItem('refreshToken', refreshToken);
}
// ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€์— ์ œ๋Œ€๋กœ aT, rT ๋“ค์–ด๊ฐ”์œผ๋ฉด ์นดํ…Œ๊ณ ๋ฆฌ ์„ ํƒ ํŽ˜์ด์ง€๋กœ ๋ผ์šฐํŒ…
} catch (error: unknown) {
if (isEffError(error)) {
// TODO: toast ์ถ”๊ฐ€
console.log(error.message, error.errorCode);
}
}
});
Copy link
Member

Choose a reason for hiding this comment

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

react-query ๊ด€๋ จ ๋ถ€๋ถ„์€ ๋”ฐ๋กœ hook์œผ๋กœ ๋นผ์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋” ์ข‹์„ ๊ฑฐ ๊ฐ™์•„์š”!!

์ถ”๊ฐ€๋กœ ์—๋Ÿฌ ๊ด€๋ จ ์ฒ˜๋ฆฌ๋Š” ErrorBoundary ํ™œ์šฉํ•ด์„œ ์„ ์–ธ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด ์–ด๋–จ๊นŒ์š”!?

Copy link
Member Author

Choose a reason for hiding this comment

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

์ €๋„ ์ด๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ๊ณ ๋ฏผ์ด ๋งŽ์•˜๋Š”๋ฐ form hook์—์„œ submit๊นŒ์ง€ ํ•ธ๋“ค๋งํ•˜๋Š”๊ฒŒ useForm๋“ค์˜ ์—ญํ• ์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด์„œ ์—ฌ๊ธฐ์— ๋‘์—ˆ์–ด์š”! ์ €๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ๋ฐ˜๋ณตํ•ด์„œ ์‚ฌ์šฉ๋˜๋Š” react-query hook์ด ์•„๋‹ˆ๋ผ๋ฉด ์—ญํ• ์— ๋งž๋Š” ๊ณณ์— ์œ„์น˜ํ•˜๋Š”๊ฒŒ ์ฝ”๋“œ๋ฅผ ๋ณด๋Š” ์ž…์žฅ, ์ž‘์„ฑํ•˜๋Š” ์ž…์žฅ์—์„œ๋„ ํŽธ๋ฆฌํ•  ๊ฒƒ ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“œ๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์‹œ๋‚˜์š”?!?!

Copy link
Member

Choose a reason for hiding this comment

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

์•„ํ•˜ ๊ทธ๋ ‡๊ตฐ์š”..! ์ €๋Š” ๊ฐœ์ธ์ ์œผ๋กœ react-query๋ฅผ hook์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋ฐ˜๋ณต ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์—์„œ ์„ ์–ธ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์–ด์š”. useForm์„ ์‚ฌ์šฉํ•  ๋•Œ login mutation์— ๋Œ€ํ•œ ๊ตฌํ˜„์„ ๊ตณ์ด ์•Œ ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ์š”!

Copy link
Member

@L2HYUNN L2HYUNN left a comment

Choose a reason for hiding this comment

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

LGTM

@chaaerim chaaerim merged commit 1a9573a into dev Mar 5, 2023
@chaaerim chaaerim deleted the feat/login branch March 5, 2023 05:33
L2HYUNN pushed a commit that referenced this pull request Mar 10, 2023
* feat: ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž… ๋ ˆ์ด์•„์›ƒ ๋ฐ ๋กœ๊ทธ์ธ ๋กœ์ง ๊ตฌํ˜„

* feat: axios ์—๋Ÿฌ ์ปค์Šคํ…€

* chore: ์ฃผ์„ ์ถ”๊ฐ€

* feat: axios request interceptors ์ถ”๊ฐ€
chaaerim added a commit that referenced this pull request Mar 23, 2023
* feat: input ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#2)

* feat: input ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* fix: install pnpm

* refactor: ํƒ€์ดํฌ ํ† ํฐ ์ ์šฉ

* feat: modal ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#4)

* feat: modal ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ

* feat: modal ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* refactor: type ๋ณ€๊ฒฝ ๋ฐ ๋ฆฌ๋ทฐ ๋ฐ˜์˜

* refactor: modal interface ์ œ๊ฑฐ

* feat: icon ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#3)

* feat: svg ์ €์žฅ

* feat: icon ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* refactor: icon ๋ฐ”๋กœ export

* refactor: span ํƒœ๊ทธ๋กœ ๋ณ€๊ฒฝ

* refactor: icon type

* feat: button ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#6)

* fix: rem์„ ์œ„ํ•œ html fontSize ์ˆ˜์ •

* refactor: text ์ปดํฌ๋„ŒํŠธ type ์„ ์–ธ ์œ„์น˜ ๋ณ€๊ฒฝ

* style: ๋ˆ„๋ฝ ๋ฐ ๋ณ€๊ฒฝ๋œ theme ์ถ”๊ฐ€

* feat(button): button ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€

* chore(button): button ์ปดํฌ๋„ŒํŠธ ์˜ˆ์ œ ์ถ”๊ฐ€

* refactor(text): text ์ปดํฌ๋„ŒํŠธ ์Šคํƒ€์ผ ํƒ€์ž…๋ช… ๋ณ€๊ฒฝ

* feat: jest, react-testing-library setting (#5)

* feat: jest, react-testing-library setting

* chore: paths ์ˆ˜์ •

* fix: fix conflict

* feat: select ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#7)

* feat: mount, update ๊ด€๋ จ hooks ์ถ”๊ฐ€

* feat: void callback type ์ถ”๊ฐ€

* feat: select ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€

* feat: select ์ปดํฌ๋„ŒํŠธ ์˜ˆ์ œ ์ฝ”๋“œ ์ถ”๊ฐ€

* chore: local pnpm ํŒจํ‚ค์ง€ ์ œ๊ฑฐ

* style: select ์ปดํฌ๋„ŒํŠธ margin top ์ถ”๊ฐ€

* feat: header ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#9)

* feat: sign up ๋ ˆ์ด์•„์›ƒ๊ณผ ๋กœ์ง ๊ตฌํ˜„ (#10)

* feat: ํšŒ์›๊ฐ€์ž… ๋ ˆ์ด์•„์›ƒ ๋ฐ ๋กœ์ง ์ž‘์—…

* feat: sign up validation check ๋กœ์ง ์ถ”๊ฐ€

* feat: signUp ์„ฑ๊ณต์‹œ ๋ชจ๋‹ฌ์ฐฝ ๋ณด์—ฌ์ฃผ๊ธฐ

* chore: console ์‚ญ์ œ ๋ฐ ์ฃผ์„ ๋‹ฌ๊ธฐ

* feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ์ตœ๋Œ€ ๊ธธ์ด 20์ž๋กœ ์ œํ•œ

* refactor: button ์ปดํฌ๋„ŒํŠธ ๋ฆฌํŒฉํ† ๋ง (#11)

* style: reset css ๋ฒ„ํŠผ disabled cursor ์กฐ๊ฑด ์ถ”๊ฐ€

* style: theme ๋””์ž์ธ ์‹œ์Šคํ…œ ๋ณ€๊ฒฝ ์ ์šฉ

* refactor: button ์ปดํฌ๋„ŒํŠธ ๋ฆฌํŒฉํ† ๋ง

* feat: toast component ๊ตฌํ˜„ (#14)

* feat: login  (#13)

* feat: ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž… ๋ ˆ์ด์•„์›ƒ ๋ฐ ๋กœ๊ทธ์ธ ๋กœ์ง ๊ตฌํ˜„

* feat: axios ์—๋Ÿฌ ์ปค์Šคํ…€

* chore: ์ฃผ์„ ์ถ”๊ฐ€

* feat: axios request interceptors ์ถ”๊ฐ€

* feat: ๋‹ต๋ณ€ Bubble ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#16)

* feat: ๋‹ต๋ณ€ Bubble ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„

* chore: ํด๋” rename

* refactor: ์ค‘๋ณต ์ฝ”๋“œ ์ œ๊ฑฐ

* feat: user answer bubble ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#17)

* feat: input bubble ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ (#18)

* refactor: toast design system ์ ์šฉ (#21)

* setting: jest eslint ์„ค์ • ์ถ”๊ฐ€ ๋ฐ ์œ ํ‹ธ ํŒŒ์ผ ์ถ”๊ฐ€ (#19)

* chore: jest ๊ด€๋ จ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํŒจํ‚ค์ง€ ์ œ๊ฑฐ

* chore: ์ง€์†์ ์œผ๋กœ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋Š” Home ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ œ๊ฑฐ

* chore: main์— button์—์„œ ๋ฐœ์ƒํ•˜๋˜ ๋ฌธ์ œ ํ•ด๊ฒฐ

* feat: jest ๊ด€๋ จ eslint plugins ์ถ”๊ฐ€

* feat: jest eslint plugin ์„ค์ • ์ ์šฉ

* chore: testing library ํŒจํ‚ค์ง€ ์žฌ์„ค์น˜

* fix: jest-dom eslint ์„ค์ • ์˜คํƒˆ์ž ์ˆ˜์ •

* fix: jest ์„ค์ • ๋ณ€๊ฒฝ

* feat: ์ปค์Šคํ…€ ๋žœ๋”๋ฅผ ์œ„ํ•œ testUtils ์ถ”๊ฐ€

* feat: button ๋žœ๋”๋ง ๋ฐ ์ž‘๋™ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€

* chore: ๋ถˆํ•„์š”ํ•œ export ์ œ๊ฑฐ

* fix: button test describe ์ด๋ฆ„ ๋ณ€๊ฒฝ

* setting: test CI ๋ฐ codecov ๋ถ€์ฐฉ (#20)

* feat: test ci ์ถ”๊ฐ€

* feat: codecov ์„ค์ • ๋ฐ CI ์ถ”๊ฐ€

* fix: ์Šคํฌ๋ฆฝํŠธ ์˜คํƒˆ์ž ์ˆ˜์ •

* feat: ๋กœ๊ทธ์ธ ๋กœ์ง ์ž‘์—… ์™„๋ฃŒ ๋ฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ • ๋ ˆ์ด์•„์›ƒ (#22)

* feat: ๋กœ๊ทธ์ธ ๋กœ์ง ์ž‘์—… ์™„๋ฃŒ ๋ฐ ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ • ๋ ˆ์ด์•„์›ƒ

* refactor: console ์‚ญ์ œ

* refactor: ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ ์šฉ

* feat: ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌ์„ค์ • api fetching (#23)

* feat: category ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#24)

* feat: useBackGroundColor hook ์ถ”๊ฐ€

* feat: layout์— background color ์ ์šฉ

* refactor: ๊ณตํ†ต hook ํด๋” ๋ถ„๋ฆฌ

* fix: axios request interceptors ํ—ค๋” Bearer ์ถ”๊ฐ€

* feat(hooks): useMounted hook ์ถ”๊ฐ€

* feat: client suspense ์ถ”๊ฐ€

* feat: client suspense ์ ์šฉ

* feat: ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์ดํ›„ ์นดํ…Œ๊ณ ๋ฆฌ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์ถ”๊ฐ€

* feat: main ์นดํ…Œ๊ณ ๋ฆฌ ํ˜ธ์ถœ api ๋กœ์ง ์ถ”๊ฐ€

* fix: select ์ปดํฌ๋„ŒํŠธ๊ฐ€ undefined ๋˜ํ•œ ์ฃผ์ž… ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ์„ค์ • ์ถ”๊ฐ€

* feat: bottom fixed button ์ถ”๊ฐ€

* feat: category ํŽ˜์ด์ง€ ์ถ”๊ฐ€

* feat: production env ํŒŒ์ผ git ignore ์ถ”๊ฐ€

* feat: dynamic category ํŽ˜์ด์ง€ ์ถ”๊ฐ€

* feat: single bottom fixed button ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€

* feat: category detail ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#25)

* feat: category ํŽ˜์ด์ง€ getStaticProps ๋ฆฌํ„ด ํƒ€์ž… ์ถ”๊ฐ€

* fix: suspense ๋ฌธ์ œ ์ž„์‹œ ์กฐ์น˜

* feat: mid category api ๊ด€๋ จ ๋กœ์ง ์ถ”๊ฐ€

* feat: next ์™ธ๋ถ€ ์ด๋ฏธ์ง€ ์‚ฌ์šฉ ์„ค์ • ์ถ”๊ฐ€

* feat: category detail ํŽ˜์ด์ง€ ์ถ”๊ฐ€

* fix: next config image hostname ๋ณ€๊ฒฝ

* feat: question ํŽ˜์ด์ง€ ๊ตฌํ˜„ (#26)

* feat: question ๊ด€๋ จ api ๋กœ์ง ์ถ”๊ฐ€ ๋ฐ ์ผ๋ถ€ ๋„ค์ด๋ฐ ์ˆ˜์ •

* fix: ๋ณ€๊ฒฝ๋œ api ์ด๋ฆ„ ์ ์šฉ

* fix: question dynamic route path ๋ณ€๊ฒฝ

* refactor: useBackGroundColor route ๋กœ์ง ๊ฐœ์„ 

* feat: question ํŽ˜์ด์ง€ ์ถ”๊ฐ€

* fix: next config s3 url ์ˆ˜์ •

* refactor: early return์„ ํ†ตํ•œ ํƒ€์ž… undefined ๋ฌธ์ œ ๊ฐœ์„ 

* refactor: category ํŽ˜์ด์ง€ early return์„ ํ†ตํ•œ ํƒ€์ž… undefined ๋ฌธ์ œ ๊ฐœ์„ 

* feat: onboarding page ์ž‘์—… ์™„๋ฃŒ (#27)

* feat: chip component ๊ตฌํ˜„ (#28)

* feat: chip component ๊ตฌํ˜„

* chore: ๊ณต๋ฐฑ ์‚ญ์ œ

* test: Icon ์ปดํฌ๋„ŒํŠธ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ (#30)

* feat: jest svg ๊ด€๋ จ ์„ค์ • ์ˆ˜์ • ๋ฐ ์ถ”๊ฐ€

* refactor: icon import ๋ฐฉ์‹ ๋ณ€๊ฒฝ

* test: icon ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€

* feat: question answer ๊ธฐ๋Šฅ ๊ตฌํ˜„ (#31)

* feat: main ์นดํ…Œ๊ณ ๋ฆฌ ํ˜ธ์ถœ api ๋กœ์ง ์ถ”๊ฐ€

* feat: mid category api ๊ด€๋ จ ๋กœ์ง ์ถ”๊ฐ€

* feat: question ๊ด€๋ จ api ๋กœ์ง ์ถ”๊ฐ€ ๋ฐ ์ผ๋ถ€ ๋„ค์ด๋ฐ ์ˆ˜์ •

* feat: question ํŽ˜์ด์ง€ ์ถ”๊ฐ€

* feat: question answer ๊ด€๋ จ api ๋กœ์ง ์ถ”๊ฐ€

* feat: double bottom fixed button ์ถ”๊ฐ€

* feat: question answer ๋กœ์ง ์ถ”๊ฐ€

* chore: ๋ถˆํ•„์š”ํ•œ ๋ณ€๊ฒฝ ์ œ๊ฑฐ

* feat: token refetch ๋กœ์ง ์ถ”๊ฐ€ (#32)

* feat: analytics tools ์ถ”๊ฐ€ (#34)

* feat: google analytics ์„ค์ • ์ถ”๊ฐ€

* feat: hotjar ์„ค์ • ์ถ”๊ฐ€

* feat: mypage ์ž‘์—… ์™„๋ฃŒ (#33)

* feat: mypage ์ž‘์—… ์™„๋ฃŒ

* chore: tsconfig ์ˆ˜์ •

* fix: ์˜คํƒ€ ์ˆ˜์ •

* fix: querykey ๋ฐ”๋€ ๊ฒƒ ์ˆ˜์ •

* feat: 404page ์ž‘์—…  (#35)

* feat: 404 page ๊ตฌํ˜„

* chore: fix lint error

* setting: playwright ์„ค์ • ๋ฐ ์˜ˆ์ œ ์ถ”๊ฐ€ (#36)

* feat: playwright ์„ค์ • ๋ฐ ์˜ˆ์ œ ์ถ”๊ฐ€

* feat: playwright eslint plugin ์ถ”๊ฐ€ ๋ฐ ์ ์šฉ

* chore: jest test ignore pattern ์ถ”๊ฐ€

* chore: response.d.ts lint ์ ์šฉ

* test: ๋น„๋กœ๊ทธ์ธ์‹œ ํ™ˆํ™”๋ฉด์— ๋Œ€ํ•œ e2e ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€

* feat: question ํŽ˜์ด์ง€ ๊ตฌํ˜„ v2 (#37)

* refactor: api base url ์ˆ˜์ • ๋ฐ deprecated api ๋ช…์‹œ

* refactor: deprecated response ๋ช…์‹œ

* refactor: ์งˆ๋ฌธ ์ƒ์„ฑ api v2 ์ถ”๊ฐ€ ๋ฐ ์ ์šฉ

* feat: ์งˆ๋ฌธ ๋‹ต๋ณ€ ์ €์žฅ api ๋ฐ mutation hook ์ถ”๊ฐ€

* feat: ์งˆ๋ฌธ api v2 ์ถ”๊ฐ€ ๋ฐ query hook ์ถ”๊ฐ€

* refactor: question api ๋ณ€๊ฒฝ์  ์ถ”๊ฐ€ ๋ฐ ์ ์šฉ

* feat: question ์ปดํฌ๋„ŒํŠธ ์ถ”๊ฐ€

* feat: questions ํŽ˜์ด์ง€ ๊ตฌํ˜„

* refactor: AIBubble ๋ณ€๊ฒฝ๋œ ๋””์ž์ธ ์ ์šฉ (#39)

* refactor: api base url ์ˆ˜์ • ๋ฐ deprecated api ๋ช…์‹œ

* feat: ์งˆ๋ฌธ api v2 ์ถ”๊ฐ€ ๋ฐ query hook ์ถ”๊ฐ€

* refactor: question api ๋ณ€๊ฒฝ์  ์ถ”๊ฐ€ ๋ฐ ์ ์šฉ

* refactor: bubble์— chip ์ปดํฌ๋„ŒํŠธ ์ ์šฉ

* refactor: ๋ณ€๊ฒฝ๋œ AI ๋‹ต๋ณ€ ํ…์ŠคํŠธ ๋””์ž์ธ ์ ์šฉ

* feat: ํ—ค๋” ๋ณ€๊ฒฝ ๋ฐ favicon, og tag ์ ์šฉ (#40)

* feat: ์นดํ…Œ๊ณ ๋ฆฌ ํ—ค๋” ์ ์šฉ ๋ฐ ๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ ํด๋ฆญ์‹œ ๋ชจ๋‹ฌ overlay

* feat: right icon ์ƒ‰ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์ˆ˜์ •

* feat: favicon, og-tag ์ ์šฉ

* feat: responsive ๋””์ž์ธ ์ ์šฉ (#41)

* feat: desktop media query theme ์ถ”๊ฐ€

* feat: ๋””์ž์ธ์— ๋”ฐ๋ฅธ desktop ๋ฐ˜์‘ํ˜• ์ ์šฉ

* setting: auto release tag action ์ถ”๊ฐ€ (#42)

* chore: ๋ฐฐํฌ ๋ฒ„์ „ ๋ช…์‹œ

* feat: auto release tag action ์ถ”๊ฐ€

* hotfix: Release 1.0.0 deploy error ํ•ด๊ฒฐ (#44)

* fix: ๋ณ€๊ฒฝ๋œ s3 url ์ ์šฉ

* fix: useShowLoginModal prop undefined ์—๋Ÿฌ ์ž„์‹œ ์กฐ์น˜

* feat: useModal Dimmer ๋ฐ˜์‘ํ˜• ์ ์šฉ

* fix: useQuestionAnswer hook api import ์—๋Ÿฌ ํ•ด๊ฒฐ

* fix: useModal import warning ํ•ด๊ฒฐ

* feat: title ,description seo ์ถ”๊ฐ€

* fix: page api ์บ์‹ฑ์œผ๋กœ ์ธํ•ด ์ด์ „ ์งˆ๋ฌธ์ด ์ž ์‹œ ๋ณด์ด๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ

---------

Co-authored-by: chaerim kim <89721027+chaaerim@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Feature ์œ ํ˜•: ๊ธฐ๋Šฅ ์ถ”๊ฐ€
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants