본문 바로가기
DEV/Web 개발

Web 개발 :: Django rest framework, front-end_TIL#42

by 올커 2022. 11. 2.

■ JITHub 개발일지 42일차

□  TIL(Today I Learned) ::

파이썬, Django rest framework, front-end

 - 파이썬 drf를 활용해서 기본적인 user 환경을 만들어보고, frontend index화면을 javascript를 활용하여 연결해보았다.

 - 로그인 화면에서 from 태그를 이용하여 사용자로부터 내용을 입력받고, 특정 명령을 줄 때에는 button을 활용하였다. 이 때, onclick 옵션을 통해 javascript에서 정의해준 function을 불러오게 하였다. 

...
<body>
    <h1>로그인 페이지</h1>
    <form>
        <input type="email" name="email" id="email" placeholder="email">
        <input type="password" name="password" id="password" placeholder="password">
        <button type="button" onclick="handleLogin()">제출</button>
    </form>

    <button type="button" onclick="handleMock()">모크 api</button>
    <button type="button" onclick="handleLogout()">로그아웃</button>
</body>

 - 자바스크립트에서 페이지를 잘 불러왔는지 확인할 때에는 아래와 같이 window.onload를 사용했다. 이 때 arrow function을 사용하는데 아직 익숙하지 않다.

window.onload = () => {
    console.log("로딩완료")
}

 - 회원가입 기능은 아래와 같이 작성했다.

 - 비동기 처리를 위해 async/await를 사용했다. (※ 참고 링크)

 - form에서 작성된 data를 가져오기 위해서 document.getElementById를 사용한다. getElementById는 하나의 값만 가져올 수 있다. 여러개의 값은 getElementsByName(getElementsByTagName, getElementsByClassName 등) 등을 사용해야 한다. 또, 해당 값으로 읽어오기 위해서 .value를 뒤에 붙여주어야 해당값으로 읽어오게 된다. 

 

 - await를 통해 결과값을 받을 때까지 기다려준 후 다음라인으로 넘어간다. 이 때 주소는 .../users/signup/ 으로 해준다.

 - headers에는 content-type, method는 POST, body는 JSON.Stringify를 통해 직렬화 시켜주고, email과 password를 넣어 보내주는 것으로 signup기능을 구성했다.

async function handleSignup(){
    const email = document.getElementById("email").value
    const password = document.getElementById("password").value
    console.log(email, password)

    const response = await fetch('http://127.0.0.1:8000/users/signup/', {
        headers:{
            'content-type':'application/json',
        },
        method:'POST',
        body:JSON.stringify({
            "email":email,
            "password":password
        })
    })

    console.log(response)
}

 - 로그인 기능은 유사하지만 좀 다르다.

async function handleLogin(){
    const email = document.getElementById("email").value
    const password = document.getElementById("password").value
    console.log(email, password)

    const response = await fetch('http://127.0.0.1:8000/users/api/token/', {
        headers:{
            'content-type':'application/json',
        },
        method:'POST',
        body:JSON.stringify({
            "email":email,
            "password":password
        })
    })

    const response_json = await response.json()

    console.log(response_json)

    localStorage.setItem("access", response_json.access);
    localStorage.setItem("refresh", response_json.refresh);

    const base64Url = response_json.access.split('.')[1];
    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));

    localStorage.setItem("payload", jsonPayload);

}

 - 로그인이 완료되면response에 access 토큰과 refresh 토큰이 생긴다. 위의 코드 중 아래의 표현에서는 json형태로 바꾸어 response_json에 넣어준다. 

const response_json = await response.json()

 - 그리고 response_json에서 access 토큰, refresh 토큰을 각각 꺼내어 localStorage.setItem을 사용하여 localStorage에 access 토큰과 refresh 토큰을 넣어준다. (*localStorage에서 값을 가져올 경우에는 getItem을 사용한다.)

localStorage.setItem("access", response_json.access);
localStorage.setItem("refresh", response_json.refresh);

 - 마지막으로 paload를 전달하기 위해 아래의 코드를 추가해주었다. (이 때에는 코드가 복잡해서 그냥 붙여넣었다.)

response_json의 access 토큰에서 .을 기준으로 두번째 항을 base64Url에 넣고, 두 번째 줄에서는 base64에 base64Url을 넣고 문자를 치환해준다. 그 아래줄에서는 코드를 해석한 결과를 jsonPayload에 넣어준다.

const base64Url = response_json.access.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
    return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));

localStorage.setItem("payload", jsonPayload);

 - Mock 기능은 간단하게 아래처럼 구현했다. 

# users/views.py

class mockView(APIView):
    permission_classes = [permissions.IsAuthenticated]
    def get(self, request):
        user = request.user
        user.is_admin = True
        user.save()
        return Response("get 요청")
async function handleMock(){
    const response = await fetch('http://127.0.0.1:8000/users/mock/', {
        headers:{
            "Authorization":"Bearer " + localStorage.getItem("access")
        },
        method:'GET',
    })

    console.log(response)
}

 - logout 기능의 경우 localstorage.removeItem을 사용할 수도 있지만 이 경우에는 삭제할 항목들을 각각 넣어주어야 한다. 더 좋은 방법이 있을 것 같아 구글링해보니, localStorage에 있는 모든 내용을 삭제하려면 간단하게 clear()를 사용할 수도 있었다. localStorage에 있는 모든 내용을 삭제했을 때 문제가 되는 것이 있을지, 확인은 필요해보인다.

async function handleLogout(){
    localStorage.clear();
    // localStorage.removeItem("access", "refresh", "payload");
}

 

반응형

댓글