Coder Social home page Coder Social logo

pretest's Introduction

๐Ÿ“‹ ์‚ฌ์ „๊ณผ์ œ

  1. ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ๊ตฌํ˜„
  2. Todo App API ๋ช…์„ธ์„œ ์ž‘์„ฑ
  3. ๊ฒฐ๊ณผ๋ฌผ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

1. ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ ๊ตฌํ˜„

1. ๋กœ๊ทธ์ธ ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ

  • ์•„๋ž˜ ์š”๊ฑด์— ๋งž์ถฐ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ framework(react, vue ๋“ฑ) ์‚ฌ์šฉํ•˜์—ฌ ์ž์œ ๋กญ๊ฒŒ ๊ตฌํ˜„ํ•ด์ฃผ์„ธ์š”
  • README.md ์ž‘์„ฑํ•ด์ฃผ์„ธ์š” (๊ณผ์ œ ๊ด€๋ จ ๋‚ด์šฉ)
  • ๊ฐœ๋ฐœ๋œ ์ฝ”๋“œ๋Š” ์••์ถ•ํ•˜์—ฌ ๋ฉ”์ผ๋กœ ์ „๋‹ฌ ํ˜น์€ github๋“ฑ ๋งํฌ๋ฅผ ์ „๋‹ฌํ•ด์ฃผ์„ธ์š”

2. ๊ณผ์ œ ์š”๊ตฌ์กฐ๊ฑด

  • ์ตœ์†Œ input 2๊ฐœ, button 1๊ฐœ๋กœ๊ทธ์ธ์‹œ (ID, PW ์ž…๋ ฅ ํ›„)
  • Local Storage(ํ˜น์€ cookie) ๋กœ๊ทธ์ธ ์ •๋ณด ์ €์žฅ (๋‹ค์‹œ ์ ‘์†ํ–ˆ์„์‹œ ์ •๋ณด ์œ ์ง€)
  • ๋ฉ”์ธ ํŽ˜์ด์ง€ ์ด๋™

์œ ํšจ์„ฑ ๊ฒ€์‚ฌ

  • ID : ๋ฉ”์ผํ˜•์‹
  • PWD : ์†Œ๋ฌธ์ž, ๋Œ€๋ฌธ์ž, ์ˆซ์ž ์กฐํ•ฉ (์ตœ์†Œ 1๊ฐœ์”ฉ) ์‹œ์ž‘๋ฌธ์ž๋Š” ์•ŒํŒŒ๋ฒณ

3. ๊ตฌํ˜„

1. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

๐Ÿ“ฆsrc
 โ”ฃ ๐Ÿ“‚components // 1. ์ปดํฌ๋„ŒํŠธ ํด๋”
 โ”ƒ โ”ฃ ๐Ÿ“œAuthRoute.tsx //
 โ”ƒ โ”ฃ ๐Ÿ“œHeader.tsx // ํ—ค๋”
 โ”ƒ โ”— ๐Ÿ“œProtectedRoute.tsx // ์›์น˜ ์•Š์€ ๋„๋ฉ”์ธ ๋ง‰๊ธฐ
 โ”ฃ ๐Ÿ“‚context
 โ”ƒ โ”— ๐Ÿ“œAuthContext.tsx // ์ „์—ญ์ƒํƒœ๊ด€๋ฆฌ (์œ ์ €์ •๋ณด,๋กœ๊ทธ์•„์›ƒ)
 โ”ฃ ๐Ÿ“‚hooks
 โ”ƒ โ”— ๐Ÿ“œuseForm.ts // Form ์ƒํƒœ๊ด€๋ฆฌ ์ปค์Šคํ…€ ํ›…
 โ”ฃ ๐Ÿ“‚pages
 โ”ƒ โ”ฃ ๐Ÿ“œHome.tsx // ๋ฉ”์ธ ํŽ˜์ด์ง€
 โ”ƒ โ”— ๐Ÿ“œSignIn.tsx // ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€
 โ”ฃ ๐Ÿ“‚utils
 โ”ƒ โ”— ๐Ÿ“œvalidate.ts // ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
 โ”ฃ ๐Ÿ“œApp.tsx // ๋ผ์šฐํ„ฐ, Context Providers, Theme Provider
 โ”ฃ ๐Ÿ“œindex.tsx
 โ”ฃ ๐Ÿ“œreact-app-env.d.ts
 โ”— ๐Ÿ“œreportWebVitals.ts

2. Form ์ƒํƒœ๊ด€๋ฆฌ

  • hooksํด๋”์—์„œ useFormController์˜ ์ปค์Šคํ…€ ํ›…์„ ํ†ตํ•ด Form์˜ email, password, displayName ๋“ฑ์˜ value๋“ค๊ณผ loading, error์— ๋Œ€ํ•œ ์ƒํƒœ๊ด€๋ฆฌ๋ฅผ ํ•˜๋Š” ํ›…์ž…๋‹ˆ๋‹ค.
  • ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ initialValues๋Š” ์ดˆ๊นƒ๊ฐ’, onSubmit๋Š” submitํ•  ๊ฒฝ์šฐ์˜ ์ฝœ๋ฐฑ ํ•จ์ˆ˜, validate๋Š” ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์œ„ํ•œ ํ•จ์ˆ˜๋ฅผ ์ฝœ๋ฐฑํ•จ์ˆ˜๋กœ ๊ตฌ์„ฑ์ด ๋ฉ๋‹ˆ๋‹ค.
  • ์ด ํ”„๋กœ์ ํŠธ์—์„œ validate ์ฝœ๋ฐฑํ•จ์ˆ˜๋กœ utils/validate.ts์—์„œ signInValidationํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

*์ •๊ทœํ‘œํ˜„์‹

// ์š”๊ตฌ์‚ฌํ•ญ ๊ธฐ์ค€ Input

// ์ด๋ฉ”์ผ ํ˜•์‹ - ์ด๋ฉ”์ผ ํ˜•์‹ ex) [email protected]
const EMAIL_REGEX =
  /^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$/i;

// ๋น„๋ฐ€๋ฒˆํ˜ธ ํ˜•์‹ - ์†Œ๋ฌธ์ž, ๋Œ€๋ฌธ์ž, ์ˆซ์ž๋กœ ๊ตฌ์„ฑ, ๋งจ ์•ž์€ ๋ฌธ์ž ex) Test1
const PWD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]+$/;

// ์ถ”๊ฐ€ input

// ์ด๋ฆ„ ํ˜•์‹ - ํ•œ๊ธ€๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ, ์ตœ์†Œ 1๊ธ€์ž ์—์„œ๋ถ€ํ„ฐ ์ตœ๋Œ€ 8๊ธ€์ž ex) ํ™๊ธธ๋™
const DISPLAY_NAME_REGEX = /^[๊ฐ€-ํžฃ]{1,8}$/;
  • ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ํ•จ์ˆ˜
const signInValidation = ({
  displayName,
  email,
  password,
}: SignUpValidationProps) => {
  const errors: SignUpValidationProps = {};

  if (!displayName) {
    errors.displayName = "์ด๋ฆ„์ด ์ž…๋ ฅ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.";
  } else if (!DISPLAY_NAME_REGEX.test(displayName)) {
    errors.displayName =
      "์ด๋ฆ„์€ ํ•œ๊ธ€๋กœ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š” ์ตœ์†Œ 1๊ธ€์ž ์ตœ๋Œ€ 8๊ธ€์ž๋กœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.";
  }

  if (!email) {
    errors.email = "์ด๋ฉ”์ผ์ด ์ž…๋ ฅ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.";
  } else if (!EMAIL_REGEX.test(email)) {
    errors.email = "์ด๋ฉ”์ผ ํ˜•์‹์œผ๋กœ ์ž‘์„ฑ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค..";
  }

  if (!password) {
    errors.password = "๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.";
  } else if (!PWD_REGEX.test(password)) {
    errors.password =
      "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์†Œ๋ฌธ์ž,๋Œ€๋ฌธ์ž,์ˆซ์ž๋กœ ์‚ฌ์šฉํ•œ ์กฐํ•ฉ์ด๋ฉฐ, ์‹œ์ž‘๋ฌธ์ž๋Š” ๋ฌธ์ž๋กœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.";
  }

  return errors;
};

email, password, displayName์„ ๋„ฃ์–ด์ฃผ๋ฉด errors์ธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋‹ด์€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

*ex. ์—๋Ÿฌ๋ฉ”์‹œ์ง€ ์˜ˆ์‹œ

{
    "displayName": "์ด๋ฆ„์€ ํ•œ๊ธ€๋กœ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š” ์ตœ์†Œ 1๊ธ€์ž ์ตœ๋Œ€ 8๊ธ€์ž๋กœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.",
    "email": "์ด๋ฉ”์ผ ํ˜•์‹์œผ๋กœ ์ž‘์„ฑ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค..",
    "password": "๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ์†Œ๋ฌธ์ž,๋Œ€๋ฌธ์ž,์ˆซ์ž๋กœ ์‚ฌ์šฉํ•œ ์กฐํ•ฉ์ด๋ฉฐ, ์‹œ์ž‘๋ฌธ์ž๋Š” ๋ฌธ์ž๋กœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค."
}

form์—๋Ÿฌ์ƒํƒœ

  • MUI์ธ ui ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ <TextField> ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ, error์™€ helperTet์— props๋ฅผ ์ฃผ์–ด ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜๋กœ๊ณ  ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
return (
  <>
    <TextField
      sx={textStyle}
      fullWidth
      placeholder="์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."
      type="text"
      name="email"
      value={email}
      onChange={handleChange}
      error={!!errors.email}
      helperText={errors.email}
    />
  </>
);
  • ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€ ์ €์žฅ ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€ ์ €์žฅ form ์ƒํƒœ๊ด€๋ฆฌ ํ›…์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ onSubmit ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์œ„ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. pretest๋ผ๋Š” key์— display,name, password์˜ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•˜๊ณ  navigate('/')๋ฅผ ํ†ตํ•ด์„œ ๋ฉ”์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค., ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€ ์ €์žฅ

๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€ ์ €์žฅ

3. ๋กœ๊ทธ์ธ ์ƒํƒœ ์œ ์ง€

  • AuthRoute ์ปดํฌ๋„ŒํŠธ์˜ ๊ธฐ๋Šฅ์€ ๋กœ๊ทธ์ธ ์ƒํƒœ๊ฐ€ ๋˜์—ˆ์„ ๋•Œ, ๋ฉ”์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๊ฒŒ ํ•˜๊ณ , ๋กœ๊ทธ์ธ ์ƒํƒœ๊ฐ€ ์œ ์ง€๋˜๋Š” ๋™์•ˆ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
  • ProtectedRoute ์ปดํฌ๋„ŒํŠธ์˜ ๊ธฐ๋Šฅ์€ ์›์น˜ ์•Š๋Š” ๋„๋ฉ”์ธ์„ ๋ง‰์Šต๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ์ƒํƒœ ์œ ์ง€

  • useEffect์˜ dependency ๋ฐฐ์—ด์— navigate๋ฅผ ์ฃผ์–ด, url์˜ ๋ณ€๊ฒฝ์„ ์‹œ๋„ํ•  ๋•Œ, ํŽ˜์ด์ง€๊ฐ€ mount๋  ๋–„, checkUserํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜์—ฌ, ๋กœ์ปฌ์Šคํ† ๋ฆฌ์ง€์— ์œ ์ € ์ •๋ณด๊ฐ€ ์ €์žฅ์ด ๋˜์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด, ๋‹ค์‹œ login ๋ผ์šฐํ„ฐ๋กœ ์ด๋™์„ ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

4. ๊ทธ ๋ฐ–์˜ ๊ธฐ๋Šฅ

  • context ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ ์ €์˜ ์ •๋ณด์™€ ๋กœ๊ทธ์•„์›ƒ ํ•จ์ˆ˜ ๋“ฑ๋ฅผ ์ „์—ญ์ƒํƒœ๋กœ ๊ด€๋ฆฌํ•˜์—ฌ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ตฌํ˜„ (context/AuthContext)
const AuthProvider = ({ children }: { children: React.ReactNode }) => {
  const navigate = useNavigate();
  const [userInfo, setUserInfo] = React.useState<UserInfo | unknown>({});

  // ๋กœ๊ทธ์•„์›ƒ์‹œ์—, ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ์ด๋™
  const logOut = async () => {
    await localStorage.removeItem("pretest");
    setUserInfo({});
    navigate("/signin");
  };

  React.useEffect(() => {
    const userInfo = localStorage.getItem("pretest");
    if (!userInfo) return;
    const parsedUserInfo = JSON.parse(userInfo);
    setUserInfo(parsedUserInfo);
  }, [navigate]);

  return (
    <AuthContext.Provider
      value={{
        userInfo,
        logOut,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};
export { AuthContext, AuthProvider };

๋กœ๊ทธ์ธ ์ƒํƒœ ์œ ์ง€

2. ToDo App API ๋ช…์„ธ์„œ ์ž‘์„ฑ

pretest's People

Contributors

taetaeo avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.