Skip to content

2024EwhaGraduationProject/clova-frontend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 

Repository files navigation

1๏ธโƒฃ ํด๋” ๊ตฌ์กฐ

ํด๋” ๊ตฌ์กฐ ์„ค๋ช…
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-12-14 แ„‹แ…ฉแ„’แ…ฎ 4 34 54 api : ์„œ๋ฒ„ ํ†ต์‹ 

assets : ์ด๋ฏธ์ง€, ์•„์ด์ฝ˜

core : ๋”๋ฏธ๋ฐ์ดํ„ฐ

hooks : ์ปค์Šคํ…€ ํ›…

pages : ํ™”๋ฉด ํŽ˜์ด์ง€
- ๊ธฐ๋Šฅ์— ๋”ฐ๋ผ 10๊ฐ€์ง€ ํ™”๋ฉด์œผ๋กœ ๊ตฌ์„ฑ

styles : ํฌ๋งท, ๊ณตํ†ต ์Šคํƒ€์ผ

types : ๋ฐ์ดํ„ฐ ํƒ€์ž…

utils : ๊ณตํ†ต ํ•จ์ˆ˜

2๏ธโƒฃ ์ฝ”๋“œ ์„ค๋ช…

1) api ์—ฐ๊ฒฐ

  1. axios
  • ์™œ fetch๊ฐ€ ์•„๋‹Œ axios๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๊ฐ€? ์‚ฌ์‹ค ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—๋Š” fetch api๊ฐ€ ์กด์žฌํ•˜์ง€๋งŒ, ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•˜๊ธฐ์— ๊ฐœ๋ฐœ์ž๋“ค์€ ์„œ๋ฒ„ ํ†ต์‹ ์— ๋ณด๋‹ค ํŽธ๋ฆฌํ•œ axios๋ฅผ ์„ ํ˜ธํ•œ๋‹ค๊ณ ..!
Axios Fetch
์„ค์น˜ ํ•„์š” O ์„ค์น˜ ํ•„์š” X
CSRF ๋ณดํ˜ธ ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค ๋ณ„๋„ ๊ธฐ๋Šฅ์ด ์—†๋‹ค
์ž๋™์œผ๋กœ JSON ๋ฐ์ดํ„ฐ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค json() ๋ฉ”์„œ๋“œ๋ฅผ ๋”ฐ๋กœ ์‚ฌ์šฉํ•ด์„œ JSON ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ” ์ฃผ์–ด์•ผ ํ•œ๋‹ค
์š”์ฒญ ์ทจ์†Œ ๋ฐ ํƒ€์ž„์•„์›ƒ์„ ๊ฑธ ์ˆ˜ ์žˆ๋‹ค. -
HTTP ์š”์ฒญ์„ ๊ฐ€๋กœ์ฑŒ ์ˆ˜ ์žˆ๋‹ค. -
์ƒํƒœ์ฝ”๋“œ๊ฐ€ ์—๋Ÿฌ ์ฝ”๋“œ๋ฅผ ๋‚ด๋ฑ‰์œผ๋ฉด reject ํ•œ๋‹ค. ์—๋Ÿฌ ์‘๋‹ต์„ ๋ฐ›๋”๋ผ๋„ resolve ํ•˜๊ณ  ๋„คํŠธ์›Œํฌ ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์—๋งŒ ๊ฑฐ๋ถ€ํ•œ๋‹ค. (์—๋Ÿฌ ๋ฑ‰์–ด์ฃผ์ง€ X)

  1. async/await
  • ์™œ promise๊ฐ€ ์•„๋‹Œ async, await๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๊ฐ€? โš ๏ธ Promise & then ์˜ ๋ฌธ์ œ์ 

    • ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์ง€๊ณ , ๋””๋ฒ„๊น…์ด ๋ถˆํŽธํ•˜๋‹ค (๊ธธ์–ด์ง€๋Š” ์ฒด์ด๋‹)
    • ์˜ˆ์™ธ์ฒ˜๋ฆฌ (tryโ€ฆcatch ์™€ .then / .catch์˜ ํ˜ผ์šฉ์ด ํ—ท๊ฐˆ๋ฆผ)

    ๐Ÿ‘‰ ๊ทธ๋ž˜์„œ ๋“ฑ์žฅํ•œ async/await

async function ํ•จ์ˆ˜๋ช…( ){
  await ๋น„๋™๊ธฐํ•จ์ˆ˜();
}

  1. customAxios
  • axios๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค baseURL์„ ์ž‘์„ฑํ•˜๋Š” ๋“ฑ ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ชจ๋“ˆํ™”ํ•˜์—ฌ ์‚ฌ์šฉ
import axios from "axios";

export const customAxios = axios.create({
  baseURL: `${import.meta.env.VITE_APP_BASE_URL}`,
  headers: {
    "Content-Type": "application/json",
    "Access-Control-Allow-Origin": "*",
  },
});

  1. ์ธํ„ฐ์…‰ํ„ฐ
  • ๋กœ๊ทธ์ธ์„ํ•˜๋ฉด ํ—ค๋”์— ํ† ํฐ์„ ๋„ฃ์–ด์ฃผ๋Š” ์ž‘์—… ๐Ÿ‘‰ authorization header
    • access ํ† ํฐ์— ๋”ฐ๋ผ ์‚ฌ์šฉ์ž๋ฅผ ์‹๋ณ„ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ† ํฐ์„ ํ™•์ธํ•˜๋Š” ์ ˆ์ฐจ๊ฐ€ ํ•„์ˆ˜์˜€์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์š”์ฒญ์„ ์ธํ„ฐ์…‰ํŠธํ•ด์„œ access token์˜ ์ •๋ณด๋ฅผ ํ—ค๋”์— ๋„ฃ์–ด์ฃผ๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.
    • ํ† ํฐ์€ Cookie์— ๋„ฃ์–ด์„œ ๊ด€๋ฆฌํ–ˆ๊ณ  access token์ด ์žˆ์œผ๋ฉด ํ—ค๋”์˜ Authorization์— Bearer ${token} ํ˜•ํƒœ๋กœ ํ† ํฐ ๊ฐ’์„ ๋„ฃ์–ด์„œ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
    • useLayoutEffect ํ›…์„ ์ด์šฉํ•ด์„œ ๋ Œ๋”๋ง ์ „์— ํ›… ์‹คํ–‰
const useSetInterceptors = () => {
  useLayoutEffect(() => {
    api.interceptors.request.use((config) => {
      const accessToken = getToken();
      if (accessToken) {
        config.headers["Authorization"] = `Bearer ${accessToken}`;
      }
      return config;
    });
  });
};

export default useSetInterceptors;
  1. react-query์™€ custom-hook

๐Ÿ”ป GET - useQuery ์‚ฌ์šฉ

์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ unique key๋ฅผ ํฌํ•จํ•œ ๋ฐฐ์—ด์ด ๋“ค์–ด๊ฐ„๋‹ค. ์ดํ›„ ๋™์ผํ•œ ์ฟผ๋ฆฌ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋œ๋‹ค. ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋“ค์–ด๊ฐ€๋Š” ๋ฐฐ์—ด์˜ ์ฒซ ์š”์†Œ๋Š” unique key๋กœ ์‚ฌ์šฉ๋˜๊ณ , ๋‘ ๋ฒˆ์งธ ์š”์†Œ๋ถ€ํ„ฐ๋Š” query ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๊ฐ’๋“ค์ด ์ „๋‹ฌ๋œ๋‹ค. ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์‹ค์ œ ํ˜ธ์ถœํ•˜๊ณ ์ž ํ•˜๋Š” ๋น„๋™๊ธฐ ํ•จ์ˆ˜๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค. ์ด๋•Œ ํ•จ์ˆ˜๋Š” Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ˜•ํƒœ์—ฌ์•ผ ํ•œ๋‹ค. ์ตœ์ข… ๋ฐ˜ํ™˜ ๊ฐ’์€ API์˜ ์„ฑ๊ณต, ์‹คํŒจ ์—ฌ๋ถ€, ๋ฐ˜ํ™˜๊ฐ’์„ ํฌํ•จํ•œ ๊ฐ์ฒด์ด๋‹ค.

export function useGetAll() {
  const { data, error, refetch } = useQuery("getAll", getAll, {
    refetchInterval: 3000, // 3์ดˆ๋งˆ๋‹ค ๋ฐ์ดํ„ฐ๋ฅผ refetch
    onError: () => {
      console.log("๋ฌผํ’ˆ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ ์—๋Ÿฌ", error);
    },
  });
  return { data, error, refetch };
}

๐Ÿ”ป POST - useMutation ์‚ฌ์šฉ

๋ฐ˜ํ™˜๊ฐ’์€ useQuery์™€ ๋™์ผํ•˜์ง€๋งŒ, ์ฒ˜์Œ ์‚ฌ์šฉ ์‹œ์— post ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ค€๋‹ค. ์ด๋•Œ useMutation์˜ ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋น„๋™๊ธฐ ํ•จ์ˆ˜๊ฐ€ ๋“ค์–ด๊ฐ€๊ณ , ๋‘ ๋ฒˆ์งธ ์ธ์ž๋กœ ์ƒํ™ฉ ๋ณ„ ๋ถ„๊ธฐ ์„ค์ •์ด ๋“ค์–ด๊ฐ„๋‹ค๋Š” ์ ์ด ์ฐจ์ด์ด๋‹ค.

์‹ค์ œ ์‚ฌ์šฉ ์‹œ์—๋Š” mutation.mutate ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ API ํ˜ธ์ถœ ์‹œ์— ์ „๋‹ฌํ•ด์ฃผ์–ด์•ผํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค const { mutate: postVoteMutate } = usePostVote();

export function usePostImage() {
  return useMutation(postImage, {
    onSuccess: (data) => {
      console.log("์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์„ฑ๊ณต", data);
    },
    onError: (error) => {
      console.log("์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์‹คํŒจ", error);
    },
  });
}

๐Ÿ‘‰ ์™œ React Query๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๊ฐ€?

  1. React Query๋Š” React Application์—์„œ ์„œ๋ฒ„ ์ƒํƒœ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ์บ์‹ฑํ•˜๋ฉฐ, ์ง€์†์ ์œผ๋กœ ๋™๊ธฐํ™”ํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•˜๋Š” ์ž‘์—…์„ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
  2. ๋ณต์žกํ•˜๊ณ  ์žฅํ™ฉํ•œ ์ฝ”๋“œ๊ฐ€ ํ•„์š”ํ•œ ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋ฐฉ์‹๊ณผ ๋‹ฌ๋ฆฌ React Component ๋‚ด๋ถ€์—์„œ ๊ฐ„๋‹จํ•˜๊ณ  ์ง๊ด€์ ์œผ๋กœ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ๋” ๋‚˜์•„๊ฐ€ React Query์—์„œ ์ œ๊ณตํ•˜๋Š” ์บ์‹ฑ, Window Focus Refetching ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜์—ฌ API ์š”์ฒญ๊ณผ ๊ด€๋ จ๋œ ๋ฒˆ์žกํ•œ ์ž‘์—… ์—†์ด โ€œํ•ต์‹ฌ ๋กœ์งโ€์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  4. React-Query๋Š” ์บ์‹ฑ์„ ํ†ตํ•ด ๋™์ผํ•œ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋ฐ˜๋ณต์ ์ธ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ํ˜ธ์ถœ์„ ๋ฐฉ์ง€ํ•˜๊ณ , ์ด๋Š” ๋ถˆํ•„์š”ํ•œ API ์ฝœ์„ ์ค„์—ฌ ์„œ๋ฒ„์— ๋Œ€ํ•œ ๋ถ€ํ•˜๋ฅผ ์ค„์ด๋Š” ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
  5. ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ Server ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์žˆ๋Š”๋ฐ, ์ด๋•Œ onSuccess์™€ onError ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด fetch ์„ฑ๊ณต๊ณผ ์‹คํŒจ์— ๋Œ€ํ•œ ๋ถ„๊ธฐ๋ฅผ ์•„์ฃผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ด๋Š” Server ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ณผ์ •์—์„œ ๊ตฌํ˜„ํ•ด์•ผํ•  ์ถ”๊ฐ€์ ์ธ ์„ค์ •๋“ค์„ ์ง„ํ–‰ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  6. ๐Ÿ“ ์ฆ‰, Client ๋ฐ์ดํ„ฐ๋Š” ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๊ด€๋ฆฌํ•˜๊ณ , Server ๋ฐ์ดํ„ฐ๋Š” React-Query๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋˜๊ณ  ์ด๋ฅผ ํ†ตํ•ด ์šฐ๋ฆฌ๋Š” Client ๋ฐ์ดํ„ฐ์™€ Server ๋ฐ์ดํ„ฐ๋ฅผ ์˜จ์ „ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์žฅ์ 
์žฌ์‚ฌ์šฉ์„ฑ API ํ˜ธ์ถœ๊ณผ ์ฒ˜๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•˜์—ฌ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ
์—๋Ÿฌ ํ•ธ๋“ค๋ง useMutation์˜ onError ์ฝœ๋ฐฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌ
์„ฑ๊ณต ์ฒ˜๋ฆฌ onSuccess ์ฝœ๋ฐฑ์„ ์‚ฌ์šฉํ•ด ์„ฑ๊ณต ์‹œ ํ•„์š”ํ•œ ํ›„์† ์ž‘์—…(์˜ˆ: ํŽ˜์ด์ง€ ์ด๋™)์„ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ
์ƒํƒœ ๊ด€๋ฆฌ React Query๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉด, ์ƒํƒœ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•  ํ•„์š” ์—†์ด ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ

  1. ๋ฆฌ์•กํŠธ์ฟผ๋ฆฌ๋ฅผ ์ ์šฉํ•œ ๋ฐฉ๋ฒ•
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-12-15 แ„‹แ…ฉแ„’แ…ฎ 9 33 02
  • api ํด๋”์— ์žˆ๋Š” ํ•จ์ˆ˜๋Š” API ํ˜ธ์ถœ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • customAxios๋ฅผ ์‚ฌ์šฉํ•ด API ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ์˜ ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-12-15 แ„‹แ…ฉแ„’แ…ฎ 9 32 04
  • hooks ํด๋”์— ์žˆ๋Š” ํ•จ์ˆ˜๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• 
  • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ•˜๋ฉด ์ฟ ํ‚ค์— ํ† ํฐ์„ ์ €์žฅํ•˜๊ณ , ์‹คํŒจ ์‹œ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๋“ฑ ์ปค์Šคํ…€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ปดํฌ๋„ŒํŠธ์—์„œ hooks๋“ค์„ ํ˜ธ์ถœํ•˜์—ฌ ๋‹ค์–‘ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

3๏ธโƒฃ How to install, test

1) ํ”„๋กœ์ ํŠธ๋ฅผ ๋ณธ์ธ์˜ ์ €์žฅ์†Œ๋กœ fork

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-12-14 แ„‹แ…ฉแ„’แ…ฎ 4 19 41

2) forkํ•œ ์ €์žฅ์†Œ๋กœ ์ด๋™ ํ›„ ์ €์žฅ์†Œ ์ฃผ์†Œ ๋ณต์‚ฌ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-12-14 แ„‹แ…ฉแ„’แ…ฎ 4 20 29

3) forkํ•œ ์ €์žฅ์†Œ๋ฅผ ์ž์‹ ์˜ ์ปดํ“จํ„ฐ๋กœ cloneํ•˜๊ณ , ํ•ด๋‹น ํด๋”๋กœ ์ด๋™

git clone ์ €์žฅ์†Œ_์ฃผ์†Œ.git
cd ํด๋”_์ด๋ฆ„

4) ์˜์กด์„ฑ ๋ชจ๋“ˆ ์„ค์น˜ yarn

5) React ์•ฑ ์‹คํ–‰ yarn dev

4๏ธโƒฃ Opensource

์—ญํ•  ์ข…๋ฅ˜
Library React ReactQuery
Programming Language TypeScript
Styling StyledComponent
Data Fetching Axios
Formatting ESLint Prettier Stylelint
Package Manager Yarn
Version Control Git GitHub
Deploy Deploy

๐Ÿ“„ ๋ธŒ๋žœ์น˜ ์ „๋žต

[Issue ๋จผ์ € ์ƒ์„ฑํ•˜๊ณ  ํ•ด๋‹น ์ด์Šˆ ๋ฒˆํ˜ธ ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ]

โ–ถ๏ธ ๋ธŒ๋žœ์น˜๋ช…

  • main: ์ตœ์ข… Merge๋ฅผ ํ•˜๋Š” ๊ณณ (๋ฐฐํฌ ๋ธŒ๋žœ์น˜)
  • develop : ๊ฐœ๋ฐœํ• ๋•Œ Mergeํ•˜๋Š” ๊ณณ
  • ํŽ˜์ด์ง€๋ช… : ๊ธฐ๋Šฅ์„ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ๊ฐ์ž ํŽ˜์ด์ง€๋ณ„๋กœ ์‚ฌ์šฉํ•  ๋ธŒ๋žœ์น˜

โ–ถ๏ธ ๋ธŒ๋žœ์น˜ ์ „๋žต

  • ์ด์Šˆ๋ฒˆํ˜ธ/ํŽ˜์ด์ง€/๊ธฐ๋Šฅ์„ค๋ช…
signup
ใ„ด 46/signup/resize-padding

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages