본문 바로가기

Education

[웹개발종합반] week5: AWS / FileZilla

반응형

5주차 수업 목표

  • Flask 프레임워크를 활용해서 API를 만든다.
  • '마이 페이보릿 무비스타'를 완성한다.
  • EC2에 내 프로젝트를 올리고 자랑한다.

 

수업 자료

 

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

매 주차 강의자료 시작에 PDF파일을 올려두었어요!

www.notion.so

 

 


1. 5주차 설치

1.1 Filezilla 설치하기

https://filezilla-project.org/download.php

 

Download FileZilla Client for Windows (64bit x86)

Download FileZilla Client for Windows (64bit x86) The latest stable version of FileZilla Client is 3.54.1 Please select the file appropriate for your platform below. Please select your edition of FileZilla Client FileZilla FileZilla with manual FileZilla P

filezilla-project.org

홈페이지에 접속하여 다운로드 버튼을 누른다.

가장 좌측의 버튼을 누르고 설치한다.

 

1.2 가비아 가입하기 & 도메인 구입하기

가비아 홈페이지에 들어가서 회원가입을 한다.

 

웹을 넘어 클라우드로. 가비아

그룹웨어부터 멀티클라우드까지 하나의 클라우드 허브

www.gabia.com

가비아에서 할인이벤트(500원/1년)를 진행하는 도메인을 구매해서 진행할 예정이다.

 ❗ 여기서, 꼭 무통장입금(가상계좌)으로 결제하기!

로그인 후 메인화면에서 원하는 도메인을 입력한다.

원하는도메인.shop 이 현재 500원 이벤트 중이므로 이 도메인을 선택한다. 그리고 우측의 신청하기 버튼을 누른다.

정보를 모두 입력하고 다음 단계 버튼을 누른다.

여기서 반드시 무통장 입금으로 결제한다. 결제가 완료되면 입금 계좌로 550원을 입금한다. 조금만 기다리면 도메인 구매가 완료되었다는 메일과 메시지가 온다. 이때 마이페이지에서 구매 정보가 뜬다.

 

2. 5주차 오늘 배울 것

미니프로젝트3

친구들도 볼 수 있도록 배포하는 일까지 쭉- 해볼 예정이다!

 

 

3. 무비스타

3.1 프로젝트 세팅

마이 페이보릿 무비스타 미리보기

 

마이 페이보릿 무비스타 | 프론트-백엔드 연결 마지막 예제!

마이 페이보릿 무비스타😆 순위를 매겨봅시다

spartacodingclub.shop

 

프로젝트 세팅하기

  • File - New project - C:\...\projects\moviestar
  • \venv인지 확인 꼭 하기!
  • app.py 생성하고, static, templates 디렉터리 생성하고, templates 내에 index.html 생성하기.
  • Setting - Python Interpreter - flask, pymongo, bs4, requests를 Install package하기

 

3.2 DB 만들기: 데이터 쌓기

프로젝트 준비 - 프로젝트에서 사용할 데이터 넣기(웹 스크래핑)

크롤링해서 영화인들을 긁어와서 DB에 넣는 작업이다.

init_db.py

import requests
from bs4 import BeautifulSoup

from pymongo import MongoClient

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


# DB에 저장할 영화인들의 출처 url을 가져옵니다.
def get_urls():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    data = requests.get('https://movie.naver.com/movie/sdb/rank/rpeople.nhn', headers=headers)

    soup = BeautifulSoup(data.text, 'html.parser')

    trs = soup.select('#old_content > table > tbody > tr')

    urls = []
    for tr in trs:
        a = tr.select_one('td.title > a')
        if a is not None:
            base_url = 'https://movie.naver.com/'
            url = base_url + a['href']
            urls.append(url)

    return urls


# 출처 url로부터 영화인들의 사진, 이름, 최근작 정보를 가져오고 mystar 콜렉션에 저장합니다.
def insert_star(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
    data = requests.get(url, headers=headers)

    soup = BeautifulSoup(data.text, 'html.parser')

    name = soup.select_one('#content > div.article > div.mv_info_area > div.mv_info.character > h3 > a').text
    img_url = soup.select_one('#content > div.article > div.mv_info_area > div.poster > img')['src']
    recent_work = soup.select_one(
        '#content > div.article > div.mv_info_area > div.mv_info.character > dl > dd > a:nth-child(1)').text

    doc = {
        'name': name,
        'img_url': img_url,
        'recent': recent_work,
        'url': url,
        'like': 0
    }

    db.mystar.insert_one(doc)
    print('완료!', name)


# 기존 mystar 콜렉션을 삭제하고, 출처 url들을 가져온 후, 크롤링하여 DB에 저장합니다.
def insert_all():
    db.mystar.drop()  # mystar 콜렉션을 모두 지워줍니다.
    urls = get_urls()
    for url in urls:
        insert_star(url)


### 실행하기
insert_all()

- 실행 시 출력화면

- robo 3T

데이터를 모두 넣었으면 init_db.py를 삭제한다.

 

3.3 뼈대 준비하기

- 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) {
                        alert(response['msg']);
                    }
                });
            }

            function likeStar(name) {
                $.ajax({
                    type: 'POST',
                    url: '/api/like',
                    data: {sample_give:'샘플데이터'},
                    success: function (response) {
                        alert(response['msg']);
                    }
                });
            }

            function deleteStar(name) {
                $.ajax({
                    type: 'POST',
                    url: '/api/delete',
                    data: {sample_give:'샘플데이터'},
                    success: function (response) {
                        alert(response['msg']);
                    }
                });
            }

        </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 class="card">
                <div class="card-content">
                    <div class="media">
                        <div class="media-left">
                            <figure class="image is-48x48">
                                <img
                                        src="https://search.pstatic.net/common/?src=https%3A%2F%2Fssl.pstatic.net%2Fsstatic%2Fpeople%2Fportrait%2F201807%2F20180731143610623-6213324.jpg&type=u120_150&quality=95"
                                        alt="Placeholder image"
                                />
                            </figure>
                        </div>
                        <div class="media-content">
                            <a href="#" target="_blank" class="star-name title is-4">김다미 (좋아요: 3)</a>
                            <p class="subtitle is-6">안녕, 나의 소울메이트(가제)</p>
                        </div>
                    </div>
                </div>
                <footer class="card-footer">
                    <a href="#" onclick="likeStar('김다미')" class="card-footer-item has-text-info">
                        위로!
                        <span class="icon">
              <i class="fas fa-thumbs-up"></i>
            </span>
                    </a>
                    <a href="#" onclick="deleteStar('김다미')" class="card-footer-item has-text-danger">
                        삭제
                        <span class="icon">
              <i class="fas fa-ban"></i>
            </span>
                    </a>
                </footer>
            </div>
        </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():
    sample_receive = request.args.get('sample_give')
    print(sample_receive)
    return jsonify({'msg': 'list 연결되었습니다!'})


@app.route('/api/like', methods=['POST'])
def like_star():
    sample_receive = request.form['sample_give']
    print(sample_receive)
    return jsonify({'msg': 'like 연결되었습니다!'})


@app.route('/api/delete', methods=['POST'])
def delete_star():
    sample_receive = request.form['sample_give']
    print(sample_receive)
    return jsonify({'msg': 'delete 연결되었습니다!'})


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

- 실행 화면

 

3.4 GET 연습: 보여주기

API 만들고 사용하기: 영화인 조회 API (Read ➡ GET)

DB에 쌓인 영화인들을 모두 가져오자. 단, like가 큰 숫자인 역순으로 띄워야 한다.

 

서버

pymongo에 정렬하는 기능을 가지는 메서드가 있다. 이를 활용하여 보자.

 

Python MongoDB Sort

Python MongoDB Sort Sort the Result Use the sort() method to sort the result in ascending or descending order. The sort() method takes one parameter for "fieldname" and one parameter for "direction" (ascending is the default direction). Example Sort the re

www.w3schools.com

sort("name", 1) #ascending
sort("name", -1) #descending

- 전체 코드:app.py

@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})

 

클라이언트

서버로부터 'move_stars'의 데이터를 받고 콘솔을 찍어보자.

- 코드

function showStar() {
	$.ajax({
		type: 'GET',
		url: '/api/list',
		data: {},
		success: function (response) {
			let mystars = response['movie_stars']
			console.log(mystars)
		}
	});
}

- 콘솔 결과

데이터를 잘 받아오고 있음을 확인할 수 있다! 그리고 이제 for 반복문으로 영화인 카드를 생성하여 붙여주어야 한다.

- 코드

        function showStar() {
            $.ajax({
                type: 'GET',
                url: '/api/list',
                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'];

                        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="#" onclick="likeStar('${name}')" class="card-footer-item has-text-info">
                                                위로!
                                                <span class="icon">
                                              <i class="fas fa-thumbs-up"></i>
                                            </span>
                                            </a>
                                            <a href="#" onclick="deleteStar('${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);
                    }
                }
            });
        }

- 화면 결과

마지막으로 like 수도 잘 반영되는지도 확인해보아야 한다. Robo 3T에 들어가서 like수를 변경하자.

리스트의 중간 정도에 있는 영화인을 오른쪽 클릭하고 Edit Document를 통해 like 숫자를 바꾼다.

그리고 페이지를 새로고침하여 좋아요 수가 많은 사람이 가장 최상단에 뜨는지 확인한다.

 

3.5 POST 연습: 좋아요+1

API 만들고 사용하기: 좋아요 API (Update ➡ POST)

좋아요 숫자를 +1하여 높여주는 기능을 구현해보자.

방법

클라이언트에서 이름(name_give)를 받고, 받은 이름을 찾아서 좋아요(like)수를 증가해준다. ➡ Update

 

서버

name_give를 받고, 받은 이름을 찾아서 좋아요 수를 +1한 후 DB를 Update한다.

@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': '좋아요 완료!'})

 

클라이언트

서버에게 name_give로 like수를 변경할 이름 데이터를 보낸다(POST). 그리고 새로고침을 한다.

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

 

완성 화면

'가이 리치' 영화인에게 좋아요 버튼을 눌렀을 때

새로고침 후 좋아요 수가 +1 늘어난 숫자로 반영된다.

 

 

3.6 POST 연습: 삭제하기

API 만들고 사용하기: 카드 삭제 API (Delete ➡ POST)

클라이언트에서 받은 이름(name_give)으로 영화인을 찾고, 해당 영화인을 삭제한다.

 

서버

@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': '삭제 완료!'})

 

클라이언트

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

 

완성 화면

에밀리 블런트를 삭제했을 때

바로 새로고침되어 영화인이 삭제된다.

 

3.7 내 프로젝트를 서버에 올리기

내가 만든 프로젝트를 남들이 볼 수 있도록 서버에 올리는 작업을 해보자. 이를 프로젝트를 배포한다고도 하며, 웹 서비스를 런칭한다고도 한다!

  • 웹 서비스를 런칭하기 위해 클라이언트의 요청에 항상 응답해줄 수 있는 서버에 프로젝트를 실행시켜줄 것이다.
  • 언제나 요청에 응답하려면, 1)컴퓨터가 항상 켜져있고 프로그램이 실행되어 있어야 하고, 2) 모두가 접근할 수 있는 공개 주소인 공개 IP 주소(Public IP Address)로 나의 웹 서비스에 접근할 수 있도록 해야 한다.
  • 서버는 그냥 컴퓨터라고 했었다. 외부 접속이 가능케 설정한 다음에 내 컴퓨터를 서버로 사용할 수 있다.
  • 우리는 AWS라는 클라우드 서비스에서 편하게 서버를 관리하기 위해서 항상 켜놓을 수 있는 컴퓨터인 EC2 사용권을 구입하여 서버로 사용할 것이다.

 

4. 서버

4.1 AWS 서버 구매하기

EC2 콘솔페이지

 

https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-2

 

ap-northeast-2.console.aws.amazon.com

컴퓨터 한대를 인스턴스라고 한다. 우리는 인스턴스 하나를 구매해야 한다.

로그인을 한 후 '인스턴스'를 누른다.

'인스턴스 시작' 버튼을 누른다.

위에서 세 번째인 '우분투 서버'를 선택한다. 리눅스는 라이센스가 필요없는 오픈소스이며 가장 보편적으로 사용되는 서버다.

t2를 선택한 후에 '검토 및 시작'버튼을 누른다.

시작하기 버튼을 누른다.

기존에 키 페어를 생성한 적이 없다면 '새 키 페어 생성'으로 선택한다.

이제 구매한 컴퓨터(인스턴스)를 원격조정하여 프로그램을 깔거나 실행할 것이다. 그때 이 컴퓨터를 원격으로 접속할 수 있는 키를 말한다. 만약 이 키를 잊어버리면 AWS에도 찾아주지 않으므로 알아서 잘 보관하여야 한다!

키 페어 이름을 입력하고 '키 페어 다운로드' 버튼을 누른다. 다운로드를 완료하면 '인스턴스 시작'을 누른다.

다음 화면에서 '인스턴스 보기' 버튼을 누르고 조금 기다리면, '인스턴스 상태'가 '대기 중'에서 '실행 중'으로 변경된다. 이제 컴퓨터가 켜졌다는 의미다.

 

 

AWS는 무료?

AWS는 단 1년 동안 무료로 제공해준다. 따라서 1년 동안 방금 만든 t2.micro 사이즈의 인스턴스 1개를 24시간 내내 계속해서 켜둘 수 있다. 1년이 지나면 자동으로 유료가 되므로 더이상 사용할 필요가 없다면 꼭 마우스 오른쪽 - '인스턴스 종료'를 눌러서 컴퓨터를 반납해주자.

 

 

Git Bash를 켜고 $ ssh -i 를 입력한 후 다운로드 받은 키페어 파일을 터미널로 마우스를 끈다. 그리고 이어서 ubuntu@를 입력하고 아까 페이지에서 '퍼블릭 IPv4 주소'를 확인하자. 이 값은 우리가 받은 컴퓨터의 주소이다.

해당 값을 복사하고 터미널에 마저 입력한다.

$ ssh -i C:\...\spartakeypair.pem ubuntu@ip주소

다음으로 뜨는 물음들은 모두 yes한다. 그리고 마지막으로 ubuntu@ip~값이 떠있다면 AWS에서 생성한 컴퓨터에 성공적으로 원격접속을 하고 있다는 상태가 된다.

 

 

4.2 서버 세팅하기

이제 우리가 AWS에서 구매한 컴퓨터를 세팅해보자. 세팅을 통해서 코딩하기에 편한 환경을 만든다.

 

filezilla를 이용하여 간단한 python 파일 올리기 & 파이썬 파일 실행하기

다운로드 받은 filezilla를 실행하고, 상단에 표시된 버튼을 누른다.

New Site 버튼을 눌러 사이트를 생성하고, Protocol을 SFTP로 선택한다. 호스트에는 이전의 '퍼블릭 IPv4 주소'값을 입력하고, Port는 22를 입력한다. 로그온 유형은 '키 파일' 사용자는 'ubuntu'(반드시 소문자!!!!!!)를 입력하고, 키 파일은 다운로드 받았던 키페어 파일을 입력한다. 그리고 연결 버튼을 누른다.

퍼블릭 IPv4 주소

확인 버튼을 누른다.

그러면 우리가 AWS에 구매한 서버의 폴더 구조를 볼 수 있다! 터미널에서 명령어를 통해 입력하고 보는 대신, FileZilla를 사용하면 눈으로 직접 보고 관리할 수 있다.

 

이제 FileZilla를 이용하여 간단한 python 파일을 올려보자. 먼저 서버에 업로드할 간단한 파일을 다운로드 받는다.

test.py

https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/web101/week5/test.py

그리고 FileZilla에서 왼쪽 화면에 있는 test.py를 오른쪽으로 파일을 마우스로 끌어 옮긴다.

git bash를 통해서 파일이 잘 올라갔는지 확인도 해보자.

파일 확인하기

파일이 잘 올라갔다! git bash에서 파일을 실행시키려면 $ python3 test.py 를 입력한다.

파일 실행하기

python3이라 입력하는 이유는 python 3 버전을 사용하기 때문이다. 이처럼 파이썬 버전을 통일해줘야 하며, 또 mongoDB와 같은 프로그램도 설치해야할 것이다. 내 컴퓨터에서 설치한 것과 마찬가지로 AWS에서 구매한 컴퓨터에서도 프로그램들을 설치해야 한다. 하지만 통상적으론 실제 회사에서 이런 일들은 개발 팀장님 같은 분들이 도맡아서 하신다. 

 

서버 환경 통일하기

EC2 한방에 세팅하기 ➡ 바탕화면에 저장!

이 파일 역시 마찬가지로 왼쪽에 있는 해당 파일을 오른쪽으로 옮긴다.

initial_ec2.sh 파일은 우리가 터미널에 입력할 명령어들을 모두 모아둔 파일이다. 이 파일을 실행하기 이전에 먼저 파일에 권한을 조정한다. 명령하게 되면 파일 속 명령어들이 잘 실행되도록 한다.

$ sudo chmod 755 initial_ec2.sh

입력하면 아무 일도 일어나지 않는다. 여기에서 파일을 실행하자.

./initial_ec2.sh

그러면 줄이 계속 생성되면서 많은 파일들이 설치된다. 이 중에서

  • 시간 세팅하는 명령어,
  • python3을 python으로 사용할 수 있도록하는 명령어도 있고,
  • pip3 명령어를 pip로 사용할 수 있게 하는 명령어,
  • mongoDB 설치하는 명령어,
  • 포트포워딩(80포트로 들어오는 요청을 5000포트로 넘겨주는 명령어) 등이 있다.

 

(+) pip

우리가 파이참에서 패키지를 설치할 때에는 마우스로 클릭하여 설치하였다. git bash에서는 마우스 및 UI가 없기 때문에 명령어를 통해 패키지를 설치하도록 하는 명령어이다.

 

다시 파이썬 파일을 실행해보기

설치가 완료된 후, 설치가 잘 되었는지 확인하기 위해 $ python test.py를 입력해보자.

실행이 잘 된다. python3을 python으로 명령어를 변경하는 이유는 더 직관성이 높기 때문이다.

mongoDB도 잘 설치되었는지도 확인해보자.

잘 설치가 되었다. 이 상태에서 현재 명령어를 내릴 일은 없다. exit를 입력하면 mongoDB 화면에서 벗어날 수 있다.

 

뭔가 꼬인 것 같고 잘 안되는 것 같다 싶을 때는 다음 순서에 따라 실행하자. (이게 젤 간편하고 빠르다!)

  1. 인스턴스 종료
  2. 새로운 인스턴스 생성
  3. 스크립트 파일을 왼쪽 ➡ 오른쪽 넣어 실행시키기

 

4.3 flask 서버 실행해보기

파이참에서 homework 디렉터리 프로젝트를 열자. 그리고 app.py 파일을 생성하고 다음과 같이 flask 기본 코드를 작성한다.

from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return 'This is Home!'

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

FileZilla를 실행시켜서 이전에 옮겼던 .sh파일과 test.py를 삭제하고, app.py 파일을 왼쪽에서 오른쪽으로 옮긴다. 

파일이 컴퓨터로 잘 올라갔는지 확인도 해준다.

그리고 app.py를 실행해보자.

하지만 에러가 발생한다. 왜냐하면 'flask' 모듈을 설치하지 않았기 때문이다. 이전에 우리가 File - Setting - pythong Interpreter를 통해서 Install Package했던 작업을 터미널 환경에서 동일하게 해야 한다. pymongo, flask를 다운받기 위한 코드는 다음과 같다.

$ pip install pymongo flask

pip 라이브러리는 파이썬의 패키지들을 쉽게 다운받을 수 있다. 다운을 받은 후 다시 app.py 파일을 실행해보자.

이제 실행이 잘 된다.

퍼블릭 http://IPv4 주소:5000 주소에 접속해보자. 나의 경우는 http://3.34.191.21:5000/이다.

아직은 접속되지 않는다. 왜냐하면 AWS에서 구매한 컴퓨터이기 때문에 AWS 자체 방화벽이 있기 때문이다. 이 AWS 방화벽을 뚫어야만 접속할 수 있다. 이를 풀어보는 작업을 하자.

 

 

4.4 AWS에서 포트 열어주기

인스턴스를 체크하고, 보안 - 보안그룹 클릭한다.

인바운드 규칙 편집 클릭

포트 범위:22는 현재 22번 포트는 미리 열려있다는 의미이다. 그래서 우리가 접속 가능한 거였다.

따라서 규칙추가 버튼을 눌러 5000번 포트도 추가해주자. 소스는 위치무관으로 선택한다.

80번, 27017번 포트도 추가한다. 80은 HTTP의 기본 포트번호이고, 27017은 pymongo 기본 포트번호이다. 이 역시도 위치무관으로 선택한다.

모두 작성하였다면 하단에 '규칙 완료' 버튼을 누른다. 그리고 다시 페이지에 접속하면 이제 접속이 된다!

터미널에서도 내 컴퓨터 주소로 접속했다고 뜬다.

 

 

4.5 원페이지 쇼핑몰 업로드해보기

Robo3T를 이용해서 '내컴퓨터에서'➡'서버에 있는 mongoDB'에 접속하기

배포하기 이전에, 원페이지 쇼핑몰의 데이터 베이스를 퍼블릭 IPv4 주소로 mongoDB에 넣어야 한다. Robo3T를 실행시키고 create 버튼을 누른다.

name은 마음대로, address에는 퍼블릭 IPv4 주소를 작성한다.

Authenication 탭을 누르고 Perform authenitcation 체크박스를 체크한다. User NamePassword를 'test'입력하고 Test 버튼을 누른다. (💡 여기서 user와 password는 이전에 다운받은 initial_ec2.sh 파일에서 설정한 값이다. 자세한 건 아래서 설명한다!)

둘다 ok인지 확인!

Close하고 Save 버튼을 누른다.

Connect 버튼 클릭!

그럼 이제 내 컴퓨터에서 robo3T를 이용하여 내가 만든 사이트의 DB에 접속을 할 수 있다.

 

💡 mongoDB에서 아이디와 비밀번호 설정?

이전에 내 컴퓨터에서 깔아서 썼던 mongoDB를 사용할 때에는 아이디와 비밀번호를 입력하지 않았다. 그런데 서버에 깐 mongoDB는 아이디와 비밀번호를 입력했었다. 왜? 다른 사람이 들어와서 DB를 조작하면 안되기 때문이다.

 

💡 mongoDB의 아이디와 비밀번호 변경하기

이전에 다운받은 initial_ec2.sh 파일을 파이참에서 연다. 여기서 userpwd 부분을 원하는 걸로 변경한 후에 터미널로 업로드 한 후 실행하면 된다.

 

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

원페이지 쇼핑몰의 코드도 pymongo의 user와 pwd의 정보를 추가해야 한다.

-코드: pymongo 계정 접속

client = MongoClient('mongodb://user:pwd@localhost', 27017)

- app.py: 현재 나의 경우는 user와 pwd가 모두 'test이므로 다음과 같이 작성하였다.

from flask import Flask, render_template, jsonify, request

app = Flask(__name__)

from pymongo import MongoClient

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

 

변경한 원페이지 쇼핑몰 파일을 FileZilla에 업로드하자. C:\...\sparta\homework에서 static, templates, app.py를 모두 옮긴다.

그리고 터미널에서 python app.py를 입력한다.

그리고 사이트에 접속해보자. 페이지가 잘 뜬다.

 

이 웹 페이지는 이 터미널을 통해 해당 페이지의 서버를 켜 놓았을 때

서버 켜기

내 컴퓨터 뿐만 아니라 모든 컴퓨터에서 접속하면 뜬다.

 

앞으로 할 것

  1. 웹 페이지 주소의 포트번호인 5000을 뗄 것이고,
  2. 터미널을 꺼서 접속이 끊어져도 서버가 여전히 켜져있도록 설정할 것이다.

 

 

4.6 포트포워딩

 웹 페이지 주소에 포트 번호를 떼어보자.

 

포트는 창구 번호와 같다고 했다. 5000번 포트로 들어오면 flask와 만나고, 27017포트와 만나면 mongoDB와 만나는 거다.

naver.com:80에 접속해보자. 뒤에 포트번호가 없어지면서 네이버 웹 사이트가 뜬다. 즉, 포트번호 80을 붙이지 않아도 된다는 거다.

80포트는 http의 기본 포트이다. 그러므로 http://주소에서 80포트를 붙이는 것과 붙이지 않는 것과 동일하다.

 

포트포워딩: (80포트 ➡ 5000포트)

여기서 우리가 할 것은, 80포트로 들어오는 요청을 모두 5000포트로 돌아가는 flask로 '포워딩'을 시켜주어야 한다. 

'야 혹시 80포트로 들어왔니? 그럼 5000번 포트로 가!'

 

이 세팅은 사실 아까 initial_ec2.sh에 코드가 포함되어 있었기 때문에 미리 다 설정해두었다. 80포트로 들어오는 요청을 5000포트로 넘겨주는 명령어는 다음과 같다.

$ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 5000

 

 

4.7 nohup 설정하기

터미널을 끄고 컴퓨터를 꺼도 사이트가 돌아가야만 내가 서버를 산 의미가 있는데! 이제 이걸 해보자!

 

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

이 명령어를 입력해보자.

# 아래의 명령어로 실행하면 된다
nohup python app.py &

그러면 계속 입력할 수 있는 상태가 된다.

터미널을 끄고 우리가 만든 웹 페이지가 접속해보면 접속이 된다!

 

 

서버 종료하기

터미널을 다시 켜고 실행시키는 코드를 입력하자.

$ ssh -i /c/Users/nno3o/Downloads/spartakeypair.pem ubuntu@3.34.191.21

그리고 다음 명령어를 입력하면 서버가 강제종료된다.

# 아래 명령어로 미리 pid 값(프로세스 번호)을 본다
ps -ef | grep 'app.py'

# 아래 명령어로 특정 프로세스를 죽인다
kill -9 [pid값]

미리 pid값을 살펴보면, 현재 31361와 31371을 강제종료 해주어야 한다.

pid값을 입력하여 강제종료해주었다. 이제 사이트를 들어가도 접속이 되지 않는다.

 

어떤 경우에 사용할까?

예로 들면 파일이 업데이트된 경우에는 서버를 강제종료하고, 파일을 재업로드한 후에 다시 켜도록 해야 한다.

 

 

요약

  1. 서버 계속 실행
    • nohup python app.py &
  2. 종료
    • ps -ef | grep 'app.py'
    • kill -9 [pid값]

 

 

4.8 도메인 구입하기

가비아 홈페이지에 접속하고 로그인을 한다. 

  • 'My 가비아' - DNS 관리툴

설정 버튼 클릭

레코드 수정 버튼 클릭

레코드 추가 버튼 - 호스트:@ /: 퍼블릭 IPv4 주소 입력 - 상태에 확인 버튼 - 저장 버튼

이제 서버를 켜고 생성한 도메인으로 접속하면 우리 사이트로 접속할 수 있다. 이 과정에서 길게는 한 시간 정도 소요되므로 조금만 기다리자!

 

 

4.9 og 태그

og 태그 만들기

나홀로 메모장에서 크롤링할 때 사용한 og 태그를 살짝 엿봤었다. 이 og 태그를 세팅해보자!

 

index.html의 <head> 태그 내에 해당 코드를 넣는다.

og 태그 넣기 코드

<meta property="og:title" content="내 사이트의 제목" />
<meta property="og:description" content="보고 있는 페이지의 내용 요약" />
<meta property="og:image" content="{{ url_for('static', filename='ogimage.png') }}" />

title과 description을 원하는 텍스트로 입력한다. image는 static 폴더 내에 있는 사진을 사용하는데, 현재는 static 폴더 내에 아무 것도 들어있지 않다. 이걸 다운받으러 고우고우~

 

구글에 '000 800x400'을 검색하자. 원하는 그림을 static 파일에 'ogimage'이름으로 저장한다.

이제 서버를 잠시 종료한 후, 변경된 파일들을 FileZilla에 재업로드한다. 그리고 다시 서버를 실행하고 친구에게 카톡이나 페이스북으로 우리가 만든 웹 페이지 주소를 보내자.

카카오톡

만약에 다음과 같이 뜨지 않거나, 혹은 og태그의 내용을 변경한 후에 업로드 했을 때 변경한 사항이 반영되지 않을 수도 있다. 이는 카카오톡이나 페이스북에서 처음에 우리가 만든 것을 한동안 저장해놓기 때문이다. 따라서 따로 카카오톡이나 페이스북의 og 태그를 초기화해야 한다.

초기화 한 후에 다시 보면 입력하면 변경된 사항이 반영된다!

 

(위) 변경전: 오타'ㅎ', (아래) 변경후

 

 

4. 5주차 끝 & 숙제 설명

우리가 만든 페이지 주소를 숙제로 제출하면 끝!

http://nno3onn.shop/

 

댜니 쇼핑몰

꿀사과 쇼핑몰 웹 서비스

nno3onn.shop

 

 

반응형