[Challenge] 로그인 구현 lv.1

KoEunseo·2023년 3월 10일
0

challenge

목록 보기
2/9

사용 스택

react
typescript

LoginType.ts

type LoginSuccessMessage = "SUCCESS";
type LoginFailMessage = "FAIL";
interface LoginRes {
  message: LoginSuccessMessage | LoginFailMessage; // "SUCCESS" | "FAIL"
  token: string;
}

interface UserInfo {
  name: string;
}

interface User {
  username: string;
  password: string;
  userInfo: UserInfo; // string타입
}

MockUserData.ts

const users: User[] = [
  { username: "hello", password: "1234", userInfo: { name: "강코딩" } },
  { username: "world", password: "qwer", userInfo: { name: "나해커" } },
  { username: "bye", password: "!@#$", userInfo: { name: "남궁버그" } },
];

login

login 함수는 비동기함수이다. 올바른 username, password를 입력받았을때 LoginRes를 리턴한다. 목데이터에 없는 username과 password를 리턴하는 경우에는 null을 리턴하게 된다.
여기서 토큰이라고 보낸 건 임의로 작성된 것으로 실제로 이렇게하면 아마 큰일나지 않을까..

const login = async (
  username,
  password
): Promise<LoginRes | null> => {
  const user: User | undefined = users.find((user) => {
    return username === user.username && password === user.password;
  });

  if (user) {
    return {
      message: "SUCCESS",
      token: JSON.stringify({ user: user.userInfo, secret }),
    };
  } else {
    return null;
  }
};

Login.tsx

input event type

event: React.FormEvent<HTMLFormElement>

FormData()

input에서 값을 받아올 때 e.value로 항상 받아왔었는데 FormData라는 것이 있다. 코드가 간결해져서 넘 좋음. 그런데 유효성검사는 즉각적으로는 못하는듯? useRef를 쓸때처럼 사용해주어야 할 것 같다. (focus가 해제됐을때 값을 가져와서 검사하고 메세지를 띄우는 형식)

사용법

1. input에 name을 준다.

formdata를 읽어올때 name을 키로 받아온다.

2. formData 객체를 만든다.

const formData = new FormData();

3. formData.get("name")

input name을 get 메서드로 보내주면 값을 읽어온다.

4. formData.append("name", "value")

값을 추가할 수도 있다.

5. 이외에도 많이있음.

keys, set, getAll, delete,
entries({key:"value"}[] 형태의 iterator 반환),
has(특정 키가 있는지 여부 반환), values...

button vs input type="submit"

button의 디폴트 타입은 submit이다.
둘다 같은 기능을 가지고 있다. 찾아봤을때 딱히 다른 점은 없는 것 같은데,
input과 button이 같은 타입을 공유하고 있는 것으로 보인다.
input으로도 button, reset, submit을 만드는 것이 가능하다.
다만 내 생각에는 input으로 했을때보다 button으로 했을 때 좀더 의미가 와닫을것같다.

const Login = () => {
  const [userInfo, setUserInfo] = useState<UserInfo>();

  const loginSubmit = async (
    event: React.FormEvent<HTMLFormElement>
  ) => {
    event.preventDefault();

    const formData = new FormData(event.currentTarget); //formData 객체 생성

    const loginRes = await login(
      formData.get("username") as string,
      formData.get("password") as string
    ); //as로 타입스라이팅(?)을 하지않으면 에러가 난다. ㅠㅠ 왜인지 알려주실분
    if (!loginRes) return;

  };

  return (
    <div>
      <h1>Login with Mock API</h1>
      <form onSubmit={loginSubmit}>
        <label>
          Username:
          <input type="text" name="username" />
        </label>
        <label>
          Password:
          <input type="password" name="password" />
        </label>
        <button>submit</button> 
      </form>
      <div>
        <h2>User info</h2>
        {JSON.stringify(userInfo)}
      </div>
    </div>
  );
};

코드 진행 순서

  1. Login페이지(컴포넌트)에서 유저가 username, password를 입력
  2. loginSubmit 함수가 실행된다.
  3. login 함수가 실행된다.
    username이 리스트에 있는지, 비번이 맞는지 확인 후
    LoginRes를 리턴. 이 res에는 성공여부를 담은 메시지와 토큰을 포함한다.

UserInfo를 얻어보자

getUserInfo

  1. 유효한 토큰이 있는지 여부를 확인 후 토큰을 파싱한다.
  2. 유저리스트에서 해당 유저의 정보를 찾아 리턴한다.
const getUserInfo = async (token: string): Promise<UserInfo | null> => {
  const token = JSON.parse(token);
  if (!token?.secret || token.secret !== secret) return null;
  const loggedUser: User | undefined = users.find((user: User) => {
    if (user.userInfo.name === token.user.name) return user;
  });
  if (loggedUser) {
    return loggedUser.userInfo;
  } else {
    return null;
  }
};

setUserInfo

getUserInfo를 실행해 usrInfo에 저장한다.

const Login = () => {
  const [userInfo, setUserInfo] = useState<UserInfo>();
  //... 생략
    const userInfo = await getUserInfo(loginRes.token);
    if (!userInfo) return;

    setUserInfo(userInfo);
}

이렇게 간단하게(?) 로그인을 구현해보았다. 사실 이때 첫 한시간을 못들어서... 😭
혼자 강의자료를 보면서 연습해봤다. 그래서 다르거나 틀린 부분이 있을 것 같음.
이번 강사님은 말씀도 너무 잘하시고 답변도 잘해주시고 역시 대기업의 배포(?)가 느껴진다.ㅋㅋㅋㅋㅋ
그리고 너무 유익함!!
무엇보다 타입스크립트를 공부하고 강의를 듣게 되어서 너무나도 다행이었다!
타입스크립트때문에 어려워하는 분들이 많은 것 같음. 코드가 깔끔하고 이해하기 쉽게 되어있어서 정말 도움된다.
그래서 나는 그래도 이해는 쭉쭉 된다.. 이렇게 내가 구현할수있는지와는 별개로ㅎㅎ
열심히 기록하고 연습해서 내껄로 만들어야지. 💪

0개의 댓글