[스파르타코딩] 웹개발 종합반 - 5주차

김영민·2021년 9월 17일

Project [무비스타]

index.html 완성코드

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
        <title>마이 페이보릿 무비스타 | 프론트-백엔드 연결 마지막 예제!</title>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css"/>
        <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
        <style>
            .center {
                text-align: center;
            }

            .star-list {
                width: 500px;
                margin: 20px auto 0 auto;
            }

            .star-name {
                display: inline-block;
            }

            .star-name:hover {
                text-decoration: underline;
            }

            .card {
                margin-bottom: 15px;
            }
        </style>
        <script>
            $(document).ready(function () {
                showStar();
            });

            function showStar() {
                $.ajax({
                    type: 'GET',
                    url: '/api/list?sample_give=샘플데이터',
                    data: {},
                    success: function (response) {
                        let mystars = response['movie_stars']
                        for (let i = 0; i < mystars.length; i++) {
                            let name = mystars[i]['name']
                            let img_url = mystars[i]['img_url']
                            let recent = mystars[i]['recent']
                            let url = mystars[i]['url']
                            let like = mystars[i]['like']

                            let temp_html = `<div class="card">
                                                <div class="card-content">
                                                    <div class="media">
                                                        <div class="media-left">
                                                            <figure class="image is-48x48">
                                                                <img
                                                                        src="${img_url}"
                                                                        alt="Placeholder image"
                                                                />
                                                            </figure>
                                                        </div>
                                                        <div class="media-content">
                                                            <a href="${url}" target="_blank" class="star-name title is-4">${name} (좋아요: ${like})</a>
                                                            <p class="subtitle is-6">${recent}</p>
                                                        </div>
                                                    </div>
                                                </div>
                                                <footer class="card-footer">
                                                    <a href="#"token interpolation">${name}')" class="card-footer-item has-text-info">
                                                        위로!
                                                        <span class="icon">
                                              <i class="fas fa-thumbs-up"></i>
                                            </span>
                                                    </a>
                                                    <a href="#"token interpolation">${name}')" class="card-footer-item has-text-danger">
                                                        삭제
                                                        <span class="icon">
                                              <i class="fas fa-ban"></i>
                                            </span>
                                                    </a>
                                                </footer>
                                            </div>`
                            $('#star-box').append(temp_html)
                        }
                    }
                });
            }

            function likeStar(name) {
                $.ajax({
                    type: 'POST',
                    url: '/api/like',
                    data: {name_give:name},
                    success: function (response) {
                        alert(response['msg']);
                        window.location.reload()
                    }
                });
            }

            function deleteStar(name) {
                $.ajax({
                    type: 'POST',
                    url: '/api/delete',
                    data: {name_give:name},
                    success: function (response) {
                        alert(response['msg']);
                        window.location.reload()
                    }
                });
            }

        </script>
    </head>
    <body>
        <section class="hero is-warning">
            <div class="hero-body">
                <div class="container center">
                    <h1 class="title">
                        마이 페이보릿 무비스타😆
                    </h1>
                    <h2 class="subtitle">
                        순위를 매겨봅시다
                    </h2>
                </div>
            </div>
        </section>
        <div class="star-list" id="star-box">
        </div>
    </body>
</html>

app.py 완성코드

from pymongo import MongoClient

from flask import Flask, render_template, jsonify, request

app = Flask(__name__)

client = MongoClient('localhost', 27017)
db = client.dbsparta

# HTML 화면 보여주기
@app.route('/')
def home():
    return render_template('index.html')

# API 역할을 하는 부분
@app.route('/api/list', methods=['GET'])
def show_stars():
    movie_star = list(db.mystar.find({}, {'_id': False}).sort('like', -1))
    return jsonify({'movie_stars': movie_star})

@app.route('/api/like', methods=['POST'])
def like_star():
    name_receive = request.form['name_give']

    target_star = db.mystar.find_one({'name': name_receive})
    current_like = target_star['like']

    new_like = current_like + 1

    db.mystar.update_one({'name': name_receive}, {'$set': {'like': new_like}})

    return jsonify({'msg': '좋아요 완료!'})

@app.route('/api/delete', methods=['POST'])
def delete_star():
    name_receive = request.form['name_give']
    db.mystar.delete_one({'name': name_receive})
    return jsonify({'msg': '삭제 완료!'})

if __name__ == '__main__':
    app.run('0.0.0.0', port=5000, debug=True)

IP주소와 포트

  • 사실 우리가 접속하는 컴퓨터는 숫자로 되어있는 주소(IP 주소)가 붙어있어요. 우리가 아는 URL 은 우리가 알아보기 쉽게 하는 등의 이유로 IP 주소를 알파벳으로 바꾼 거에요. 이렇게 변환해주는 시스템을 DNS 라고 합니다.

  • IP 주소(줄여서 IP라고 부릅니다)

    : 컴퓨터가 통신할 수 있도록 컴퓨터마다 가지는 고유한 주소라고 생각하면 됩니다. 정확히는 네트워크가 가능한 모든 기기가 통신할 수 있도록 가지고 있는 특수한 번호입니다. 서버는 하나의 주소를 가지고 있습니다.

  • 포트(port)

    : 하나의 IP에 여러 포트가 있습니다. 하나의 포트에 하나의 프로그램을 실행시킬 수 있습니다.

AWS (Amazon Web Service) 서버

AWS EC2

SSH(Secure Shell Protocol)

  • 다른 컴퓨터에 접속할 때 쓰는 프로그램입니다. 다른 것들 보다 보안이 상대적으로 뛰어납니다.
  • 접속할 컴퓨터가 22번 포트가 열려있어야 접속 가능합니다. AWS EC2의 경우, 이미 22번 포트가 열려있습니다.

Mac OS: Mac은 ssh가 있어서, 명령어로 바로 접근 가능

  • 터미널을 열기 (spotlight에 terminal 입력)

  • 방금 받은 내 Keypair의 접근 권한을 바꿔주기

    sudo chmod 400 받은키페어를끌어다놓기 
  • SSH로 접속하기

    ssh -i 받은키페어를끌어다놓기 ubuntu@AWS에적힌내아이피

    예) 아래와 비슷한 생김새!

    ssh -i /path/my-key-pair.pem ubuntu@13.125.250.20

간단한 리눅스 명령어 연습

  • 리눅스는 윈도우 같지 않아서, '쉘 명령어'를 통해 OS를 조작한다. (일종의 마우스 역할)

[가장 많이 쓰는 몇 가지 명령어]

  • 팁! 리눅스 커널에서 윗화살표를 누르면 바로 전에 썼던 명령어가 나옵니다.
ls: 내 위치의 모든 파일을 보여준다.

pwd: 내 위치(폴더의 경로)를 알려준다.

mkdir: 내 위치 아래에 폴더를 하나 만든다.

cd [갈 곳]: 나를 [갈 곳] 폴더로 이동시킨다.

cd .. : 나를 상위 폴더로 이동시킨다.

cp -r [복사할 것] [붙여넣기 할 것]: 복사 붙여넣기

rm -rf [지울 것]: 지우기

sudo [실행 할 명령어]: 명령어를 관리자 권한으로 실행한다.
sudo su: 관리가 권한으로 들어간다. (나올때는 exit으로 나옴)

서버 세팅하기

서버 환경 통일하기

우리는 지금 막! 컴퓨터를 구매한 상태예요. 여기에 이런저런 세팅들(업그레이드, DB설치, 명령어 통일 등)을 해줘야 본격적으로 이용할 때 편리하답니다!

  • EC2 한방에 세팅하기

파일질라로 업로드하고, git bash(또는 터미널)에서 아래 코드를 차례대로 입력해주세요.

3분 정도 기다리면 모든 세팅이 완료됩니다.

sudo chmod 755 initial_ec2.sh
./initial_ec2.sh

mongoDB

mongoDB 설치코드

wget -qO - https://www.mongodb.org/static/pgp/server-4.2.asc | sudo apt-key add -

echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.2.list

sudo apt-get update

sudo apt-get install -y mongodb-org

mongoDB 실행하기

# 실행. 아무 반응이 없으면, 잘 실행된 것!
# 리눅스는 보통 잘 되면 아무것도 안나와요!^^;
sudo service mongod start

mongoDB 접속 계정 생성하기

# admin으로 계정 바꾸기
use admin;

# 계정 생성하기
db.createUser({user: "test", pwd: "test", roles:["root"]});

mongoDB 외부에 열어주기

sudo vi /etc/mongod.conf

# sudo: 관리자(SuperUser) 권한으로 다음을 실행
# => "관리자 권한으로 /etc 폴더 아래 mongod.conf 파일을 Vim으로 켜줘!"라는 뜻입니다

Robo3T를 이용해서, "내 컴퓨터에서"→"서버에 있는 mongoDB"에 접속하기

  • 좌측 상단 내 아이콘을 클릭합니다.

  • Create 클릭!

  • 접속 정보를 세팅합니다.

  • 상단 Authentication 탭을 클릭합니다.

    1. Perform authentication 체크박스를 클릭합니다.
    2. 생성한 계정의 아이디와 비밀번호를 입력하고, 'save'를 클릭합니다.

flask 서버를 실행해보기

pip로 패키지를 설치하기

pip install flask

flask 서버를 실행하기

  • 아래 명령어로 flask 서버를 실행합니다.

    python app.py
  • 서버 실행이 되면, 크롬에서 접속을 해봅니다.

    크롬 브라우저 창에 아래와 같이 입력합니다.
    
    http://[내 EC2 IP]:5000/

AWS 포트 열어주기

AWS에서 5000포트 열어주기

  • EC2 서버(=가상의 내 컴퓨터)에서 포트를 따로 설정하는 것 외에도,
    AWS EC2에서도 자체적으로 포트를 열고/닫을 수 있게 관리를 하고 있습니다.

    → 그래서 AWS EC2 Security Group에서 인바운드 요청 포트를 열어줘야 합니다.
  • 일단, EC2 관리 콘솔로 들어갑니다. 그리고 보안그룹(영문: Security Group)을 눌러 들어갑니다. 여기선 launch-wizard-1 이라고 쓰여 있네요

  • 해당 보안그룹을 클릭합니다.

  • Edit inbound rules를 선택합니다.

  • 세 가지 포트를 추가해봅니다.

    → 80포트: HTTP 접속을 위한 기본포트

    → 5000포트: flask 기본포트

    → 27017포트: 외부에서 mongoDB 접속을 하기위한 포트

완성본 업로드해보기

원페이지쇼핑몰 완성본을 filezilla로 EC2에 업로드

  • 그 전에! MongoDB 접속 세팅을 바꿔주세요!

    AWS의 MongoDB에 아이디와 비밀번호를 추가했으니, 우리의 pymongo에도 아이디와 비밀번호를 입력해주어야 합니다! 그래야 pymongo가 올바르게 DB에 접근할 수 있습니다.

    app.py 파일을 열어서,
    아래 처럼 가운데 한 줄을 바꿔주세요!

    pymongo 계정 접속

      ```python
      client = MongoClient('mongodb://test:test@localhost', 27017)
      ```

    아래와 같은 뜻이에요!

    client = MongoClient('mongodb://아이디:비밀번호@localhost', 27017)
  • 파일질라에서 homework 폴더 째로 드래그 드롭으로 EC2 인스턴스의 home/ubuntu 폴더에 업로드합니다.

완성본 실행

  • 실행하려고 시도하기

    # home 디렉토리로 이동
    cd ~
    
    # 해당 폴더로 이동해서 아래 코드를 실행합니다.
    python app.py
  • 에러가 나죠? 패키지를 설치하지 않았기 때문입니다.

    # 설치하기
    pip install pymongo
  • 다시 실행해봅니다

    python app.py
  • 브라우저에서 접속하기

    http://내AWS아이피:5000/

포트포워딩

포트번호 떼고 접속하기

http://내AWS아이피/

포트번호 없애기

  • 지금은 5000포트에서 웹 서비스가 실행되고 있습니다. 그래서 매번 :5000 이라고 뒤에 붙여줘야 하죠. 뒤에 붙는 포트 번호를 없애려면 어떻게 해야할까요?
  • http 요청에서는 80포트가 기본이기 때문에, 굳이 :80을 붙이지 않아도 자동으로 연결이 됩니다.
  • 포트 번호를 입력하지 않아도 자동으로 접속되기 위해, 우리는 80포트로 오는 요청을 5000 포트로 전달하게 하는 포트포워딩(port forwarding) 을 사용하겠습니다.
  • 리눅스에서 기본으로 제공해주는 포트포워딩을 사용할 것입니다.
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 5000

nohup 설정하기

SSH 접속을 끊어도 서버가 계속 돌게하기

  • 현재 상황

    Git bash 또는 맥의 터미널을 종료하면 (=즉, SSH 접속을 끊으면) 프로세스가 종료되면서, 서버가 돌아가지 않고 있습니다. 그러나 우리가 원격접속을 끊어도, 서버는 계속 동작해야겠죠?

  • 원격 접속을 종료하더라도 서버가 계속 돌아가게 하기

    # 아래의 명령어로 실행하면 된다
    nohup python app.py &
  • 서버 종료하기 - 강제종료하는 방법

    # 아래 명령어로 미리 pid 값(프로세스 번호)을 본다
    ps -ef | grep 'app.py'
    
    # 아래 명령어로 특정 프로세스를 죽인다
    kill -9 [pid값]
  • 다시 켜기

    nohup python app.py &

og태그

  • static 폴더 아래에 이미지 파일을 넣고, 각자 프로젝트 HTML의 ~ 사이에 아래 내용을 작성하면 og 태그를 개인 프로젝트에 사용할 수 있습니다.

    1. "내 사이트의 제목" 입력하기

    2. "보고 있는 페이지의 내용 요약" 입력하기

    3. 적당한 이미지를 만들거나/골라서 static폴더에 ogimage.png로 저장하기!
      (사이즈 800x400인 이미지를 구글에서 검색!)

      og태그 넣기

      ```jsx
      <meta property="og:title" content="내 사이트의 제목" />
      <meta property="og:description" content="보고 있는 페이지의 내용 요약" />
      <meta property="og:image" content="{{ url_for('static', filename='ogimage.png') }}" />
      ```
  • 참고! 이미지를 바꿨는데 이전 ogimage가 그대로 나와요!

그것은 페이스북/카카오톡 등에서 처음 것을 한동안 저장해놓기 때문입니다.

페이스북 og 태그 초기화 하기: https://developers.facebook.com/tools/debug/
카카오톡 og 태그 초기화 하기: https://developers.kakao.com/tool/clear/og

profile
“Stay hungry, Stay foolish.”

0개의 댓글