로그인 개념과 어플리케이션 구조 알아보기

2023. 3. 7. 19:10프론트엔드

날짜: 2023년 3월 6일
태그: 교육, 원티드 프리온보딩

로그인 개념과 어플리케이션 구조 알아보기

 

로그인의 기본적인 개념과 왜 로그인을 하는지

로그인이란게 대체 뭘까?

컴퓨터 보안에서 로그인(영어: login, 문화어: 등록가입)과 로그아웃(영어: logout)은 접근 허가 증명을 얻기 위해 사용자 인증으로 개인이 컴퓨터 시스템에 접근하는 작업을 말한다. 컴퓨터 보안에서 중요한 역할을 담당한다. 사용자 자격 증명은 일반적으로 사용자이름과 그에 일치하는 비밀번호 형태를 이루며[1] 이를 기반으로 사용자는 액세스 하기 위해 시스템에 로그인할 수 있으며 더 이상 필요하지 않을 때 로그아웃할 수 있다. ( 출처 : 위키 백과 )

 

정의를 살펴 보면 다음과 같은 단어들이 있다.

  • 접근 허가 증명
  • 사용자 인증
  • 시스템 접근
  • 로그아웃

정리하면 시스템에서 사용자 인증을 하고 시스템 접근 허가를 증명한 후에 시스템에 접근 하기위해 필요한 기능이다.

애플리케이션 구조에서 로그인의 역할

github 페이지

 

⚠️ 웹에서의 로그인이도 비슷한 의미 이다.

웹 앱 (시스템)에 접근하기 위해 나에게 부여된 아이디, 비밀번호를 통해서 회원 페이지의 접근 권한을 얻고 비회원은 접근할 수 없는 페이지에에 접근할 수 있을 것이다.

 

⚠️ 서비스의 관점에서 보면?

예시: 배달의 민족

웹 서비스의 여러가지 서비스들이 있을 것이다. 그리고 그것을 이용하려면 서비스에서 내가 누군지, 이용하는 사람이 누군지 알아야 할것이다. 신원확인이 정확히 제대로 되지 않으면 서비스 입장에서 막대한 손해가 갈것이다. ( http 통신 tcp 프로토콜은 stateless 프로토콜이라 누가 보냈는지 모른다. )

  • 쿠폰을 지급해야 하는데.. 누구 한테..?
  • 이 사람이 배달을 시켰었나..?
  • 지역이 여기가 맞았나..? 배달 주소가 어디지??

✔️ 따라서 로그인은 유저가 시스템에 접근하기 위해서 신원확인을 하는 절차라고 정리할 수 있겠다.

로그인기능 만들기

로그인 기능을 넣기 위해 페이지 구조를 생각해보면 다음 그림과 같다.

  • 메인 페이지 : 메인페이지는 회원이 접근할 수 있는 페이지와 비 회원이 접근할 수 있는 페이지가 나눠져 있을 것이다. 경우에 따라선 회원전용 페이지만 있을 수도 있겠다.
  • 로그인 페이지 : 로그인을 하기 위해서는 로그인 페이지가 있어야 한다.
  • 회원가입 페이지 : 로그인을 할 id 를 만들기위해서 나의 정보를 담은 회원 정보가 있어야한다.
  • 오류 페이지 : 비회원이 회원접근 페이지를 갔을 때를 대비한 오류 페이지가 필요하다.
  • 로그아웃 : 이제는 로그아웃 페이지가 잘 없는것 같다. 바로바로 메인 페이지로 렌더링 될것이다.

로그인 화면과 로직

🤔 로그인 로직은 어떻게 짜야 할까?

네이버 로그인 창

  • 일단 로그인 화면을 생각해보면 필요한 정보는 아이디, 비밀번호, 제출버튼 이다.
  • Form에서 ID와 PW를 추출해서 서버로 전송할 것이다.
  • 서버에서는 회원 목록을 조회 하면서 ID와 PW를 대조하고, 회원이 존재하면 “성공” 응답과 시스템에 맞는 데이터를 전송해줄 것이다.
  • 회원 목록에 존재하지 않거나 틀리면 “실패” 응답과 로그인 화면에 적절한 메시지를 띄워줄 것이다.

 

💻 프론트엔드 관점에서는 로그인 시 어떤 동작을 취해야 할까?

  1. Form에서 ID와 PW를 추출해서 서버로 전송하는 것
  2. 서버 결과를 받아서 유저와 적절한 상호작용을 하는 것
  3. 페이지 접근 권한을 바꿔줄 것

➕ 앞으로의 통신에 유저의 신원확인을 위한 무언가를 같이 전송 해줄것. ( 방식에 따라 다르다.)

ex ) Token … cookies , local storage, session storage

 

 

Login Moking을 통해서 간단하게 알아보는 로그인 로직

1. LoginWithMockAPI : Login의 총 로직을 수행하는 MockAPI이다. 
아래 기능들이 수행 된다.
2. loginSubmitHandler : LoginForm에서 ID와 PW를 추출해서 가져오는 핸들러이다.
3. Login :  LoginForm에서 추출한 ID와 PW를 서버로 전송해서 확인하는 함수 
user의 토큰을 반환한다. 
4. getUserInfo : user Token을 통해 서버에서 회원 정보를 가져오는 함수이다. 
유저 정보를 반환 한다.
5. state 변경 : userInfo를 통해서 가져온 user로 state를 변경해서 
컴포넌트를 바꾼다.
6. return : 컴포넌트를 렌더링 한다.

실제 서비스의 로그인

실제 서비스 구성하기

  • 실제 서비스를 구성하는 페이지(접근권한)을 분리를 해야 한다.
  1. 로그인이 필요한 페이지
  2. 로그인이 불필요한 페이지

😒 그러면 페이지별로 어떻게 확인 할까?

react 프로젝트 기반으로 생각해보자.

1. 페이지 별로 로그인 권한이 필요한지 확인

const MainContent = () => {

    //로그인 여부 확인 custom hooks
    const [isloggedIn, setLogin] = useIsLoggedIn();

    if(isLoggedIn){
            //로그인 시 렌더링
            return ...
    }else {
            //비로그인 시 렌더링
            return ...
    }
}
  • 제일 간단한 방법으로 로그인 권한이 필요한지 확인 하고 렌더링 한다.
  • 간단하게 해결할 수는…. 있겠지만 페이지가 늘어날수록 기하급수적으로 중복 코드를 작성해야 할것..

2. 페이지별로 렌더링 되기 전에 레이아웃 컴포넌트(컴포넌트 합성)로 권한을 확인한다.

AuthCheck.js

const AuthCheck = ({children}) => {

    const isloggedIn = useIsLoggedIn();

    if(isLoggedIn){
            //로그인 시 렌더링
            return (<>{children}</>);
    }else {
            //비로그인 시 렌더링
            return <h1>"Login is need"</h1>;
    }
}

RootRouter.js

const RootRouter = createBrowserRouter([
  {
    path: "/",
    element: <Auth><HomePage subRootList={subRoot} /></Auth>,
    children: subRoot,
  },
  {
    path: "/login",
    element: <LoginPage />,
    action: loginAction,
  },
]);
  • 컴포넌트 합성을 이용해서 체크하는 방법이다.
  • 코드를 분리하고 원하는 페이지마다, 컴포넌트 합성을 시켜줘서 체크 할 수 있을 것이다.
  • 하지만 페이지가 점점 늘어 날 수록 중복될 수 있고 유지보수가 힘들어질 것이다.

 

3. 레이아웃 컴포넌트를 똑똑한 방식으로 다시 쓰기 feat. Array.map

  • 로그인을 확인하는 코드 & 로직을 모듈화 해야한다. ( 반복되는건 못참지 )

const RoutePath = [
  {
    path: "/",
    element: <HomePage subRootList={subRoot} />,
        needAuth: false,
  },
  {
    path: "/login",
    element: <LoginPage />,
        needAuth: false,
  },
  {
    path: "/main",
    element: <MainPage />,
        needAuth: true,
  },
  {
    path: "/Content",
    element: <ContentPage />,
        needAuth: true,
  },
];

const RootRouter = createBrowserRouter(RoutePath.map(route => {
    let element = route.element;
    if(route.needAuth){
        element = <Auth>{route.element}</Auth>;
    };
    return {
        element,
        path : route.pass,
        //children 이 있으면 추가 구현
    }
}));
  • RoutePath에 needAuth 속성을 둬서 map을 이용해 조건부로 로그인 인증이 필요한 페이지를 나눠준다.
  • 위와 같은 방법(레이아웃 패턴) 으로 코드를 분리하면 다음과 같은 장점이 있다.
    1. 새로운 페이지를 넣을때 RootPath만 수정하면 되므로 수정코드 유지 보수가 쉬워지고, 가독성이 좋아진다.
    2. 일일히 사람이 넣으면 필연적으로실수가 일어날 수 있는데 (Human Error)이를 줄일수 있다.
    3. Array.reduce를 이용해 원하는 요소만 뽑아내서 재사용이 가능하다.