[MGS 3기 - 33일차] Redux를 활용해 로그인 구현해보기

박철연·2022년 5월 26일
0

MGS STFE 3기

목록 보기
30/35

오늘 교육 과정 중에는 React 발표회가 예정되어 있었습니다. 발표 중심의 저번 주와는 다르게, 매니저님께서 실습 과제를 제시하고 이를 구현하는 식이었습니다. Redux를 활용하여 로그인 페이지를 구현하는 작업을 진행하고 기록으로 남겨보았습니다.

개요

과제의 방향성

이번 과제의 의도는 아래와 같았습니다.

  • 상태(state)를 통해 input 요소 관리하기
  • useEffect 훅으로 state 관리하기
  • Redux로 state 관리하기
  • state를 통해 컴포넌트 조작하기

감사하게도 사전에 fork한 프로젝트에는 이미 각종 라이브러리나, import 문법이 갖추어져 있었습니다.

또한 해당 과제를 수행하기 위한 폴더 구조도 마련되어 있어 React 코드에 집중할 수 있는 형식이었습니다.

로그인 명세

이번 실습 과제는 다음과 같은 기본 로그인 form이 구현되어야 합니다. 자세한 기능 구현 포인트는 다음과 같습니다.

  1. 각각의 id/pw의 input 값을 state로 관리하고 조작
  2. 로그인 버튼 클릭 시 id나 pw 둘 중 하나라도 값이 비어있다면, alert창을 통해 submit event를 종료
  3. axios를 통신하는 동안 button을 다시 클릭 불가
  4. axios 통신 결과에 따라 user state (redux)를 변경하거나,
    Error Msg를 지정
  5. Error Msg는 있을 때에만 출력되며, 1.5초 뒤 사라짐. Error Msg가 사라지면 button을 다시 클릭 가능

MyPage 명세

  1. 로그인한 유저에 따라서 다른 이름을 출력
  2. 로그아웃 버튼을 클릭하면 user state (redux)를 초기값으로 되돌리고 로그아웃 동작을 실행

API 명세

  • EndPoint : (~~~url)
    반드시 body(obj)를 같이 보내줘야 함.
    body.id : 유저 id
    body.password : 유저 pw
  • 로그인 실패 시
    code : 400 = body 값이 비어 있을 때
    code : 401 = 존재하지 않는 id일 때
    code : 402 = 비밀번호가 틀렸을 때
  • 로그인 성공 시
    code : 200
    userInfo = object, user의 data가 넘어 옴

과제 수행 과정

Login 컴포넌트

로그인 컴포넌트는 얼마 전 있었던 진상현 강사님의 로그인 유효성 검사와 매우 흡사했습니다.

먼저 input 값의 value를 onchange 함수를 만들어 미리 선언해둔 state들에 담았습니다.

그런 다음, 입력값이 비어 있는 경우에는 다음과 같은 코드로 유효성 검사를 한 뒤, msg state를 조작해 충족되지 못한 부분을 사용자에게 전달토록 했습니다. (if 문의 앞 부분은 뒤에서 설명할 예정입니다.)

보시는 것과 같이, 유효성 검사를 충족하지 못한 조건에 대해서는 어떤 이유인지 msg state에 담아서 화면에 띄우도록 했습니다.

명세서 상으로는 이러한 에러 메시지를 띄우되, 1.5초 후에 다시 사라지게끔 구현해야 했습니다.

이를 위해서 setTimeout 함수를 사용했습니다. 당연히 msg를 사라지게 하기 위해 setMsg 함수에 빈 값을 넣어주었습니다.

다만 실시간 강의와 달랐던 부분은, 강의에서의 로그인 유효성 검사는 아이디와 비밀번호의 길이(length)를 기반으로 진행했다는 점입니다.

이번 과제에서는 입력값의 길이가 아니라, axios로 서버와 통신하여 실제로 입력값에 해당되는 아이디와 비밀번호가 있는지 찾는 것이었습니다.

따라서 사전에 axios 코드를 위한 body를 작성하였고, 데이터도 정상적으로 fetch해왔습니다. (중간 중간 확인을 위한 console.log 코드를 포함시켰습니다)

API 명세에 따르면 로그인에 성공했을 경우, 응답 데이터의 code 값은 200이므로, 해당 내용을 조건문에 포함시켜 code가 200일 경우 dispatch 함수에 담아 loginUser 리듀서 함수가 실행되도록 작성했습니다.

로그인 관리

src 폴더 안에는 components 폴더와 더불어 reducer 폴더도 만들어 Redux 관련 코드들을 모아두었습니다.

먼저 store.js 파일은 대략적으로 다음과 같습니다.

import 부분에서 보이는 것과 같이, 실제 store에 들어갈 state의 내용은 userSlice라는 파일을 따로 만들어서 store에 들여왔습니다.

다음이 userSlice 파일의 내용입니다.

createSlice로 userSlice 변수를 만든 뒤, 초기 상태값을 지정해주었습니다.

아래 reducer 함수 부분에는 두 가지 함수를 사용했습니다. 당연히 로그인을 하는 함수와 로그아웃을 하는 함수입니다.

로그인 컴포넌트에서 로그인 유효성 검사를 설명할 때 언급한 loginUser 함수입니다.

강사님이나 다른 수강생분들은 state 값에 체이닝을 하거나 스프레드 문법을 사용해서 state 값 변경을 시도하셨습니다.

저는 새로운 변수를 만들어 값을 바꾸고, 최종적으로 해당 변수를 return하는 식으로 state 변경을 하는 패턴을 본 적이 있어 한번 따라해 보았습니다.

그 결과 정상적으로 잘 작동하는 것을 확인하였습니다. 다만, isLogin 부분을 true로 바꿔주는 코드가 중간에 삽입되다 보니, 코드를 처음 보는 분들께는 의미가 잘 전달되지 않을 수도 있다는 생각을 했습니다.

다음은 로그아웃을 위한 clearUser 리듀서 함수입니다.

주석에 작성한 것과 같이, 최초의 state 값을 직접적으로 불러올 방법이 없나 고민해보았습니다.

그러나 마땅한 방법은 찾지 못했고, clearUser 함수가 실행되는 것은 loginUser 함수에 의해 state가 이미 변경된 시점이기 때문에, 그냥 리셋을 위한 state 값을 하드 코딩 해보았습니다.

피드백 / 개선 방향

loading state 미사용

기본 과제에는 useState를 사용해 loading이라는 상태가 이미 추가되어 있습니다.

처음에 저는 이 state를 어디 쓸 지 고민하다가, 결국 사용하지 않고 제 나름대로 기능을 구현해보았습니다.

제가 핀트를 잘못 잡았던 것이, 단순히 로그인 여부를 확인하는 상태(이 과제에서는 store 내 user state의 isLogin이라고 할 수 있습니다)만 있으면 로그인 버튼의 기능도 온전히 구현될 거라고 생각했다는 것입니다.

현재 제가 작성한 LoginComponent.jsx 파일에서는 useSelector를 쓰고 있지 않은데, 위와 같은 아이디어로 접근했다면 useSelector를 통해 store 안의 상태를 불러와야 했습니다.

하지만, 그보다 더 좋은 방법이 바로 미리 마련된 loading 상태를 쓰는 것이라고 결론내렸습니다.

당연히 컴포넌트 파일 안에서 useState로 작성되었기 때문에, 따로 import를 할 필요도 없고 axios 통신과 button간의 연결도 더 수월할 것입니다.

useEffect 미사용

최초 코드에는 useEffect 내부에 의존성으로 msg가 추가되어 있었습니다.

그래서 작업 초기에는 useEffect를 사용하여 에러 메시지를 핸들링하는 코드를 작성하면 된다고 생각했습니다.

그러나 msg의 내용이 실제 화면 렌더링에 영향을 미치고 있는 구조이기 때문에, 저는 이를 side effect로서 useEffect에 포함시키기 힘들다고 판단했습니다.

뿐만 아니라, useEffect 내에 loading을 의존성으로 추가해야 하는 상황이 발생할 수도 있었습니다. (물론 이 경우는 제가 loading을 쓰지 않기로 결정했기 때문에 실제로 일어나지는 않았습니다.)

그러한 이유로 useEffect를 사용하지 않기로 했으나, msg를 핸들링하는 프로세스가 모두 화면 렌더링에 영향을 주는 것은 아니었습니다.

추후에 코드를 개선하는 과정에서는 side effect의 개념을 다시 정리하고, msg 핸들링에서 렌더링과 side effect를 구분해서 useEffect 훅을 적절하게 사용해야 할 것으로 보입니다.

profile
Frontend Developer

0개의 댓글