220429_내일배움캠프_TIL

Today Jeeho Learned·2022년 4월 29일
0

TIL

목록 보기
12/249

- 핵심적으로 배울 것

  1. Flask의 더 많은 기능배우기
  2. API에 보안 키를 전달하기
  3. 멀티페이지 사이트 만들기 (이것이 페이징처리인가?)

두 페이지로 되어있는 나만의 단어장을 만들어 볼것이다.
그전에 필요한 개념들을 알아가보자

1. 정적인 페이지 vs 동적인 페이지

  • 서버에 저장되어있는 형태를 그대로 넘겨주는 것을 정적인 웹페이지

  • 로그인한 사용자의 닉네임을 보여준다던지, 추가 가공을 통해 모습이 변하는것은 동적인 웹 페이지

  • 정적인 웹페이지는 추가적인 통신&계산이 필요 없기 때문에 속도가 빠르고, 서버에 부담이 적은 반면에 추가/수정/삭제 등 내용 변경이필요할때 HTML 자체를 수정해야하기 때문에 번거롭다.

  • 동적인 웹페이지는 한 페에지에서 상황,시간,사용자의초정에 따라서 다른 모습을 보여 줄 수있는 장점이 있지만, 상대적으로 보안에 취약하고 모습이 계속 변하기때문에 검색 엔진 최적화가 어렵다.

동적 웹페이지를 많이쓰는데, 이런 동적웹페이지의 종류를 알아보자

-1. CSR방법이란?
HTML을 보낼때 JS까지 같이 포함해서 데이터를 보내게 되는데, 클라이언트쪽에서 HTML을 완성하는 방법

-2. SSR방법이란
HTML을 만들때 서버쪽에서 데이터를 끼워넣어 완성된 형태의 HTML을 보내주는 방법

-3. 복합적인 ajax방법
요청이 들어오면 html에 자바스크립트를 심어서 보내주고, 페이지가 뜨고나면 자바스크립트 코드가 다시 ajax로 서버로 요청을보내 데이터를 가져오는 서버에 요청을 두번 보내는 복합적인 방법

그동안 복합적인 방법을 많이 사용했으니, 이번에는 SSR을 공부해보자!
Flask에서 SSR을 공부하기 위해서는 Jinja2라는 템플릿 언어를 사용해야한다.

  • jinja2
    템플릿이 되는 html문서에다 데이터가 들어갈 곳을 표시해주시는 문법을 정의해 놓은 것이다.

  • api 키
    open api라도 너무 많은 요청을 보내는 등의 악용을 방지하기 위해서 api 키를 배부받아 요청시에 같이 보내줘야하는 경우가 있다.

이 api키를 서버에서 api로 요청을 보낼때, 클라이언트에서 api로 요청을 보낼때 어떻게 보내주는지 알아보자

02. 플라스크로 멀티페이지 사이트 만들기

  • 프로젝트 생성후, 필요한 파일들을 생성하고, 패키지를 설치해준다.

  • 페이지를 2개만들기때문에 index.html 과 detail.html을 만들어준다.

  • 메인페이지에서 상세페이지로 가기위한 하이퍼링크를 만들어주었다.

<body>
    <h1>메인페이지</h1>
    <a href="/detail">상세페이지로 가기</a>

</body>

href다음에 상세페이지인 localhost:5000/detail을 넣어줘야 하나 생각했지만 같은 페이지 이기때문에 /detail만 입력해주면 된다.

누르면 상세페이지로 이동된다.

-반대로 상세페이지에서 메인페이지로 돌아가는 버튼을 만들어주었다.

    <script>
        function to_main(){
            window.location.href="/"
        }
    </script>
</head>
<body>
    <h1>상세페이지</h1>
    <button onclick="to_main()">메인으로 돌아가기</button>
</body>

버튼에 onclickdp 함수를 하나 만들어주고 함수안에 window.location href="/"를 넣어준다 아까는 detail 이었는데 이번에는 그냥 메인페이지이기때문에 /만 넣어줘도 잘 작동한다.

window.location.reload()가 생각난다 얘는 새로고침이었지!

<button onclick="window.location.href='/'">메인으로 돌아가기</button>

한줄짜리 함수라서 그냥 onclick에 넣어줘도 된다. 그런데 주의할것은 "가 4개가 들어가서 오류가 생기기때문에 onclikc 안에있는 " "에서는 작은따음표로 설정해주자

  • Jinja를 사용해서 페이지에 값을 끼워 넣어보자

먼저 app.py의 main에서 myname이란 변수에 값을 넣어주고, render할때 같이 넣어준다
그러면 index.html에서는 {{ ~~~ }} 이중 중괄호를 사용하는 jinja가 이 해당하는 값을 보여준다.

03. 플라스크로 멀티페이지 사이트 만들기 - 응용

복습할겸 ajax를 사용하여 서울시 미세먼지수치를 나타내는 open api를 사용해서 60이상의 수치가 있는 구만 나타내보자

<script>
        $(document).ready(function () {
            get_list()
        })

        function get_list() {
            $.ajax({
                type: "GET",
                url: "http://openapi.seoul.go.kr:8088/6d4d776b466c656533356a4b4b5872/json/RealtimeCityAir/1/99",
                data: {},
                success: function (response) {
                    let rows = response["RealtimeCityAir"]["row"];
                    console.log(rows)
                }
            })
        }
    </script>

잊지말자 먼저 ajax를 사용하려면 jquery를 import해와야한다!
위에 코드를 해석하면 페이지가 로딩이 되면 get_list함수를 실행하는데
get_list 함수를 보면 ajax요청을 서울시 오픈api로 보내는데 , 보내는 것이 성공하면 응답으로 보내주는 json데이터에서 realtimcityair안에 row라는 값을을 rows로 넣어주고! 콘솔창에 출력해줘! 라는 것이다.

왜썼느냐? 내가 머리속에 정리하기 위해서 ㅎㅎㅎㅎㅎㅎㅎ

    <script>
        $(document).ready(function () {
            get_list()
        })

        function get_list() {
            $.ajax({
                type: "GET",
                url: "http://openapi.seoul.go.kr:8088/6d4d776b466c656533356a4b4b5872/json/RealtimeCityAir/1/99",
                data: {},
                success: function (response) {
                    let rows = response["RealtimeCityAir"]["row"];
                    console.log(rows)
                    for (let i=0; i<rows.length; i++){
                        let gu_name = rows[i]["MSRSTE_NM"]
                        let gu_mise = rows[i]["IDEX_MVL"]
                        console.log(gu_name,gu_mise)
                        let html_temp =`<li>${gu_name}: ${gu_mise}</li>`
                        $("#gu-list").append(html_temp)
                    }
                }
            })
        }
    </script>
</head>
<body>
    <h1>상세페이지</h1>
    <button onclick="window.location.href='/'">메인으로 돌아가기</button>
    <ul id="gu-list"><
    <li>중구:20</li>
    </ul>
</body>

아직 눈이랑 손에 안익은 것 같다.
li는 순서없는 리스트만들어주는 것이다.
기억하쟈 ("#gu-list") 이것처럼 id가 있는 곳에 넣어줄때는 #꼭 붙이고 append해주기

+추가로

li에 중구를 임의로20으로 설정해놨는데, ul태그안에 있기 때문에 출력하면 같이 나온다.
중구 20을 지워도 되지만 출력하기전에

$("#gu-list").empty()

를 사용해서 비워주도 된다.

                    for (let i = 0; i < rows.length; i++) {
                        let gu_name = rows[i]["MSRSTE_NM"]
                        let gu_mise = rows[i]["IDEX_MVL"]
                        console.log(gu_name, gu_mise)
                        if (gu_mise > 60) {
                            let html_temp = `<li>${gu_name}: ${gu_mise}</li>`
                            $("#gu-list").append(html_temp)
                        }
                    }

수치가 60이상인 구만출력하기 위해서 if조건문을 하나 추가해주면 된다.

이제 이것을 jinja2를 사용해서 해보자

detail.html에서 로딩후 바로 실행했던 get_list() 함수를 주석처리해주고

app.py에서 밑에 코드를 붙여준다.

@app.route('/detail')
def detail():
    r = requests.get('http://openapi.seoul.go.kr:8088/6d4d776b466c656533356a4b4b5872/json/RealtimeCityAir/1/99')
    response = r.json()
    # request에서 뒤에있는 주소로 get요청을 보낸다, 그런 결과를 r에 담고 이런 r을 response에 json형태로 저장해라
    rows = response['RealtimeCityAir']['row']
    #openapi의 형태를 확인하긴 해야함
    return render_template("detail.html", rows=rows)
    # 같아도 되는데 내가 기억하기 편한 사용하기

주석을 달아놓은 그대로 이해하면 될 것 같다. 그리고 다시 index.html로 돌아가서

<body>
    <h1>상세페이지</h1>
    <button onclick="window.location.href='/'">메인으로 돌아가기</button>
    <ul id="gu-list">
        <li>{{ rows[0]["MSRSTE_NM"]}}: {{ rows[0]["IDEX_MVL"]|int }}</li>
    </ul>
</body>

이렇게 쓰면 row의0번째 구에 대한 이름과 수치값만을 출력할수있다
그리고 수치값이 실수형으로 나오기 마련인데 | 라는 파이프를 함께쓰고 뒤에 정수형인 int를 붙여주면 정수형 수치만 출력된다.

그런데!! 너무 길다 변수로 담아서 넣어주자 !

<body>
    <h1>상세페이지</h1>
    <button onclick="window.location.href='/'">메인으로 돌아가기</button>
    <ul id="gu-list">
        {% set gu_name = rows[0]["MSRSTE_NM"] %}
        {% set gu_mise = rows[0]["IDEX_MVL"] %}
        <li>{{ gu_name }}: {{ gu_mise|int }}</li>
    </ul>
</body>

{% %}형태임을 기억하자!

    <ul id="gu-list">
        {% for row in rows %}
            {% set gu_name = row["MSRSTE_NM"] %}
            {% set gu_mise = row["IDEX_MVL"] %}
            {% if gu_mise>=60 %}
            <li>{{ gu_name }}: {{ gu_mise|int }}</li>
            {% endif %}
        {% endfor %}
    </ul>

추가로 반복문과 조건문을 써서 정보를 출력하는데
기존과는 조금 다른 형태다. 어디서 끝나는지를 넣어줘야한다.

이번에는 url주소에서 데이터를 받아서 jinja2로 넘겨주는 것을해보자

엔터자체가 서버입장에서는 get요청을 받는 것이다.
url에 데이터를 입력해서 가져오는 방식을 해보자

@app.route('/detail/<keyword>')
def detail(keyword):
    return render_template("detail.html", word=keyword)

원래는 /detail?~~~ 처럼 물음표뒤에 붙는 값을 따로 저장해서 해줬는데
route부분에 / < keyword > 넣어주면 url에서 detail/(입력값) 에서 입력값에 원하는 글자를 입력하면 입력하는 값이 word에 들어가고 바로 출력이 된다.

04.사전(dictionary) API 사용하기

owlbot이라는 사전 api를 가져올것이다!
이메일로 토큰을 받았다.

@app.route('/detail/<keyword>')
def detail(keyword):
    r = requests.get(f"https://owlbot.info/api/v4/dictionary/{keyword}", headers={"Authorization": "Token [토큰]"})
    result = r.json()
    print(result)
    return render_template("detail.html", word=keyword)

detail/~~~ url에서 입력했을때 입력한 값에 대한 사전적인 정보를 알려주는 코드다.
f스트링을 사용해서 keyword값을 넣어줬고 이를 통해 url에 hi를 입력하면
hi에 해당사전 사전적인 용어가 출력된다.

  • 자바스크립트로 api키를 넣어서 요청하는 것
    크롬창에서 개발자 도구의 콘솔창에서 ajax 코드를 입력해도 잘 작동한다.
$.ajax({
    type: "GET",
    url: "https://owlbot.info/api/v4/dictionary/owl",
    beforeSend: function (xhr) {
        xhr.setRequestHeader("Authorization", "Token [내토큰]");
    },
    data: {},
    error: function (xhr, status, error) {
        alert("에러 발생!");
    },
    success: function (response) {
        console.log(response)
    }
})

기본보다 조금더 길어졌는데, get요청으로 url은 owl에 대한

beforeSend: function (xhr) {
        xhr.setRequestHeader("Authorization", "Token [내토큰]");

보내기전에 내 토큰정보를 보내라! 라는 의미로 이메일로 받은 토큰정보를 보내면 된다.
그리고 먼저 에러가 발생했을때 먼저 alert를 뛰우라는 메세지다.

owl말고 내가 원하는 값을 써도 좋은데
내가 입력한 값을 넣으려면

let word ="내가입력한 값"으로 선언해주고 주소 앞뒤를 백틱으로 감싸주고
url: https://owlbot.info/api/v4/dictionary/${word},를 대신 넣어주면 내가 입력한 값이 출력된다.

05.나만의 단어장 api설계하기

사용자 입장에서 기능들을 살펴보면서 api를 설계해보자

두페이지밖에 안되는데 구현할 것들이 많다.ㅜㅜ

  • 메인 페이지

    1. 단어 검색
      단어가 단어장에 이미 있는 단어인지 검색 → 있으면 하이라이트, 없으면 상세 페이지로 이동
    2. 단어장에 있는 단어를 클릭했을 때 상세 페이지로 이동
  • 상세 페이지

    1. 단어 저장 또는 삭제
      • 단어가 이미 존재하면 삭제 버튼, 아니면 저장 버튼 노출
      • 저장 버튼을 누르면 DB에 저장하고 삭제 버튼으로 바뀜
      • 삭제 버튼을 누르면 DB에서 삭제하고 메인 페이지로 이동
    2. 예문 저장과 삭제
      • 저장된 단어의 경우 예문 칸이 보여지게 하기
      • 예문을 저장하면 목록 맨 아래에 추가
      • 예문에 단어가 포함되지 않으면 얼럿 띄우기
      • 예문을 선택해서 삭제할 수 있음

profile
기록해야 (살아)남는다 !

0개의 댓글