전체 방문자
오늘
어제
  • 전체 글
    • HTML
    • CSS
    • Javascript
    • React
    • Typescript
    • Next.js
    • Webpack
    • Vue.js
    • Git & GitHub
    • Error
    • Study
    • 개발 일지✨

블로그 메뉴

  • 💡
  • ⚙️
hELLO · Designed By 정상우.
하루

Home

스파르타 코딩클럽 5주차
개발 일지✨

스파르타 코딩클럽 5주차

2021. 12. 17. 00:07
5주차
프로젝트 진행과 배포까지!!

 

설치

  • Filezilla
  • 가비아 가입하기 & 도메인 구입하기

 

[프로젝트] 무비스타

DB 만들기 (데이터 쌓기)

데이터를 먼저 모아두고 데이터를 보여주는 작업을 한다.

API를 설계하고 만드는 것에 집중할 수 있게 사용할 데이터를 웹스크래핑해서 데이터베이스에 저장하는 코드를 미리 작성해두었다.

init_db.py

더보기

⭐ 코드 스니펫

파일을 실행하면 내 mongoDB mystar collection에 영화인 정보가 저장된다.

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()

 

뼈대 준비하기

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)

 

API 설계

  1. 조회 기능(Read): 영화인 정보 전체를 조회
  2. 좋아요 기능(Update): 클라이언트에서 받은 이름(name_give)으로 찾아서 좋아요(like)를 증가
  3. 삭제 기능(Delete): 클라이언트에서 받은 이름(name_give)으로 영화인을 찾고, 해당 영화인을 삭제

 

영화인 조회 (Read → GET)

A. 요청정보

  • 요청 URL= /api/list, 요청방식= GET
  • 요청데이터: 없음

B. 서버가 제공할 기능

  • 데이터베이스에 영화인 정보를 조회(Read)하고, 영화인 정보를 응답 데이터로 보냄

C. 응답 데이터

  • (JSON 형식) 'stars_list'=영화인 정보 리스트 

 

1. 클라이언트와 서버 연결 확인하기

서버

# API 역할을 하는 부분
@app.route('/api/list', methods=['GET'])
def show_stars():
    sample_receive = request.args.get('sample_give')  #클라이언트로부터 받아온 데이터
    print(sample_receive)
    return jsonify({'msg': 'list 연결되었습니다!'})

클라이언트

function showStar() {
    $.ajax({
        type: 'GET',
        url: '/api/list?sample_give=샘플데이터',
        data: {},
        success: function (response) {
            alert(response['msg']);
        }
    });
}

새로 고침 했을 때, 'list 연결되었습니다!' 라는 메시지가 뜨면 동작한다.

 

2. 서버부터 만들기

영화인 정보 전체를 조회하기 위해서는 서버가 클라이언트로부터 받을 정보는 없다.

서버 로직은 다음과 같이 구성한다.

  1. mystar 목록 전체를 검색 - ID는 제외하고 like가 많은 순으로 정렬 (숫자 역순)
  2. 성공하면 success 메시지와 함께 stars_list 목록을 클라이언트에 전달

pymongo에 정렬해서 뽑는 기능을 이용해서 좋아요 순으로 정렬해서 보내준다.

정렬방법 sort

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

 

3. 클라이언트 만들기

클라이언트에서는 서버로부터 내려온 데이터를 받아서 찍어준다.

클라이언트 로직은 다음과 같다.

  1. #star_box의 내부 html 태그 모두 삭제
  2. 서버에 GET 방식으로, /api/list 라는 주소로 stars_list를 요청
  3. 서버가 돌려준 stars_list를 stars라는 변수에 저장
  4. for 문을 활용하여 stars 배열의 요소를 차례대로 조회
  5. stars[i] 요소의 name, url, img_url, recent, like 키 값을 활용하여 값 조회
  6. 영화인 카드 코드 만들어 #star-box에 붙이기
더보기
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="#" 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)
            }
        }
    });
}

 

4. 완성 확인하기

좋아요 개수에 따라서 역순으로 정렬되는지 확인해야 한다.

아직 업데이트 기능은 구현되지 않았기 때문에 DB에서 좋아요 수를 임의로 설정한 후 새로고침 했을 때 좋아요 개수가 많은 것이 위로 와있으면 성공!

 

좋아요 API (Update → POST)

좋아요 버튼을 누르면 해당 영화인에 좋아요+1 해주는 기능을 만들 것이다.

클라이언트에서 받은 이름으로 찾아서 좋아요를 증가시켜주면 된다.

 

A. 요청 정보

  • 요청 URL= /api/like, 요청방식= POST
  • 요청 데이터: 영화인 이름(name_give)

B. 서버가 제공할 기능

  • 영화인 이름(요청 데이터)과 일치하는 영화인 정보의 좋아요 수를 한 개 증가시켜 데이터베이스에 업데이트하고(Update), 성공했다고 응답 메세지를 보냄

C. 응답 데이터

  • (JSON 형식) 'msg'='좋아요 완료!'

 

1. 클라이언트와 서버 연결 확인하기

서버

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

클라이언트

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

 

2. 서버 만들기

영화인의 좋아요 수를 증가시키기 위해 서버가 클라이언트로부터 영화인의 이름(name_give)을 전달받아야 한다.

서버 로직은 다음 단계로 구성된다.

  1. 클라이언트가 전달한 name_give를 name_receive 변수에 넣는다.
  2. mystar 목록에서 find_one으로 name이 name_receive와 일치하는 star를 찾는다.
  3. star의 like에 1을 더해준 new_like 변수를 만든다.
  4. mystar 목록에서 name이 name_receive인 문서의 like를 new_like로 변경한다.
@app.route('/api/like', methods=['POST'])
def like_star():
    name_receive = request.form['name_give'] # 좋아요 받은 영화인 이름을 클라이언트로부터 받는다.
    target_star = db.mystar.find_one({'name': name_receive}) # 해당 영화인의 이름을 DB에서 찾아서 지정한다.
    current_like = target_star['like'] # 해당 영화인의 현재 좋아요 수를 가져온다.
    new_like = current_like + 1 # 현재 좋아요 수에 +1 을 추가해준다.
    db.mystar.update_one({'name': name_receive}, {'$set': {'like': new_like}}) # 새로운 좋아요 수로 바꿔서 업데이트 해준다.

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

 

3. 클라이언트 만들기

클라이언트 로직은 다음 단계로 구성된다.

  1. 서버에 POST 방식으로, /api/like 라는 url에, name_give라는 이름으로 name을 전달한다. (참고: POST 방식이므로 data: {'name_give': name} 사용)
  2. '좋아요 완료!' alert 창을 띄운다.
  3. 변경된 정보를 반영하기 위해 새로고침 한다.
function likeStar(name) {
    $.ajax({
        type: 'POST',
        url: '/api/like',
        data: {name_give: name},
        success: function (response) {
            alert(response['msg']);
            window.location.reload();
        }
    });
}

 

4. 완성 확인하기

좋아요를 눌렀을 때 '좋아요 완료' 얼럿창이 뜨고, 숫자가 업데이트 된 것이 보이면 성공!

 

카드 삭제하기 (Delete →  POST)

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

 

A. 요청 정보

  • 요청 URL= /api/delete, 요청 방식=POST
  • 요청 데이터: 영화인 이름(name_give)

B. 서버가 제공할 기능

  • 영화인 이름(요청 데이터)와 일치하는 영화인 정보를 데이터 베이스에서 삭제(Delete)하고, 성공했다고 응답 메세지를 보낸다.

C. 응답 데이터

  • (JSON 형식) 'msg'='삭제 완료!'

 

1. 클라이언트와 서버 연결 확인하기

서버

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

클라이언트

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

잘 연결되었다면 삭제버튼을 눌렀을 때 얼럿창이 뜰 것이다.

 

2. 서버 만들기

영화인 카드를 삭제하기 위해서는 영화인의 이름(name_give)에 관한 정보가 필요하다.

  1. 클라이언트가 전달한 name_give를 name_receive 변수에 넣는다.
  2. mystar에서 delete_one으로 name이 name_receive와 일치하는 star를 제거한다.
  3. 성공하면 '삭제 완료!' 메시지를 반환한다.
@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': '삭제 완료!'})

 

3. 클라이언트 만들기

클라이언트에서는 서버로 영화인의 이름을 전달해주어야 한다.

  1. 서버에 POST 방식으로 /api/delete 라는 url에, name_give라는 이름으로 name을 전달한다. (참고: POST 방식이므로 data: {'name_give': name})
  2. '삭제 완료!' alert 창 띄우기
  3. 변경된 정보를 반영하기 위해 새로고침
function deleteStar(name) {
      $.ajax({
          type: 'POST',
          url: '/api/delete',
          data: {name_give:name},
          success: function (response) {
              alert(response['msg']);
              window.location.reload()
          }
      });
  }

 

4. 완성 확인하기

삭제 버튼을 눌렀을 때 영화인 카드가 삭제되면 성공!

 

전체코드

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="#" 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)
                        }
                    }
                });
            }

            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}) # 해당 영화인의 이름을 DB에서 찾아서 지정한다.
    current_like = target_star['like'] # 해당 영화인의 현재 좋아요 수를 가져온다.
    new_like = current_like + 1 # 현재 좋아요 수에 +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)

 

1. 내 프로젝트를 서버에 올리려면

내가 만든 프로젝트를 서버에 배포해보자!

브라우저가 요청을 하면 브라우저가 그릴 것을 주거나, Ajax로 요청을 하면 응답 데이터를 주는 등 클라이언트의 요청을 받는 행위를 하는 것이 서버의 역할이다. 웹 서비스를 런칭하기 위해 요청에 항상 응답해줄 수 있는 서버에 프로젝트를 실행시켜준다.

 

언제나 요청에 응답하려면

  1. 컴퓨터가 항상 켜져있고 프로그램이 실행되어 있어야하고
  2. 모두가 접근할 수 있는 공개 주소인 공개 IP주소(Public IP Address)로 나의 웹 서비스에 접근할 수 있도록 해야한다.

우리는 AWS 라는 클라우드 서비스에서 편하게 서버를 관리하기 위해서 항상 켜놓을 수 있는 컴퓨터인 EC2 사용권(무료 1년)을 구입해 서버로 사용할 것이다.

그 중 Ubuntu Server 18.04 - t2micro 타입으로 생성했다. 키페어를 새로 생성하거나 기존의 키페어를 가져온다.

 

AWS EC2에 접속하기

SSH(Secure Shell Protocol)

다른 컴퓨터에 접속할 때 쓰는 프로그램으로, 다른 것들 보다 보안이 상대적으로 뛰어나다.

접속할 컴퓨터가 22번 포트가 열려있어야 접속 가능하다. AWS EC2의 경우, 이미 22번 포트가 열려있다.

 

Windows

ssh가 없으므로 Git bash를 이용! gitbash를 실행하고 아래를 입력

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

그러면 우분투를 통해 우리가 산 서버에 원격 접속을 한 것이다.

⭐ gitbash를 종료할 때는 exit 명령어를 입력하여 ssh 접속을 먼저 끊어주고 종료하기!

 

리눅스 명령어

팁! 리눅스 커널에서 윗화살표를 누르면 바로 전에 썼던 명령어가 나온다.

ls: 내 위치의 모든 파일을 보여준다.

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

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

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

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

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

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

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

 

2. 서버 세팅하기

앞서 설치했던 filezilla는 내 컴퓨터에 있는 파일을 업로드/다운로드 해주는 역할이다.

 

Filezila

1. 사이트 관리자 열기

2. New site

3. 프로토콜 SFTP 로 설정

4. 정보들을 입력하고 ok 누르면 서버의 파일들을 볼 수 있다.

  • Host: 내 EC2 서버의 ip
  • Port: 22
  • 로그온 유형: 키 파일
  • 파일 가져오기: 키페어 파일
  • User: ubuntu 로 입력

 

서버 환경 통일하기

원격 컴퓨터를 산 것이나 다름없다! 여기에 이런저런 세팅들(업그레이드, DB설치, 명령어 통일 등)을 해줘야 본격적으로 이용할 때 편리하다!

EC2 한방에 세팅하기

 

해당 파일을 파일질라로 업로드하고, git bash(또는 터미널)에서 다음 코드를 차례대로 입력한다.

sudo chmod 755 initial_ec2.sh
./initial_ec2.sh

 

서버가 꼬이거나 잘 안될 때는 서버를 인스턴스 종료한 후에 새로 만든다. (인스턴스 시작)

똑같이 스크립트 파일을 업로드 해주어 서버환경을 세팅해준다.

 

3. Flask 서버 실행해보기

Flask로 서버를 실행하는 python 파일 app.py 를 파일질라로 서버에 업로드하고 실행해보자.

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)
# 실행
python app.py

해당 파일을 실행하면 flask카 패키지가 없다고 에러가 난다.

 

패키지 설치하는 방법

우리는 pip로 패키지를 설치해준다.

파이참에서 file - settings - pip 버튼을 누르고 검색했던 설치작업을 명령어로 진행할 것이다.

pip install flask

 

Flask 패키지를 설치하고, 아까 전의 app.py 파일을 다시 실행시켜보면 Flask가 작동하면서 서버가 실행되는 것을 볼 수 있다. 서버실행 후 기본 컴퓨터에서 했던 것과 같이 원격 컴퓨터인의 EC2 IP 주소를 가져와서 http://[내 EC2 IP]:5000/ 을 입력하고 접속하면 아직 작동하지 않는다! 

이는 AWS의 자체 방화벽으로 인해 접속되지 않는다. 따라서 구멍을 뚫어서 우리가 접속할 수 있게 만들어주어야 한다.

 

4. AWS에서 포트 열어주기

사용하고 있는 인스턴스를 누르고 아래에서 보안 > 보안 그룹 > 인바운드 규칙 편집 > 규칙 추가 > 저장

 

인바운드 규칙에 보면 앞에서 우리가 열어주었던 포트 22가 추가되어 있는 것을 확인할 수 있다.

여기에 우리가 사용하는 서버의 포트 5000도 추가해주어야 한다.

  • 규칙 추가 > 포트범위: 5000 > 소스: 위치무관(Anywhere-IPv4) : Flask 서버 포트 5000
  • 규칙 추가 > 포트범위: 80 > 소스: 위치무관(Anywhere-IPv4) : http 기본 포트
  • 규칙 추가 > 포트범위: 27017 > 소스: 위치무관(Anywhere-IPv4) : mongoDB

이렇게 포트를 열어주고 나면 서버가 정상적으로 돌아가고 있는 것을 볼 수 있다.

app.py 실행을 통해 Flask 서버를 실행시켰기 때문에 서버가 돌아가고 있는 Gitbash 창에서 Ctrl + C 를 누르면 종료된다. 그리고 서버도 함께 종료되어 해당 사이트를 이용할 수 없는 상태가 된다.

 

5. 원페이지 쇼핑몰 업로드하기

과제로 만들었던 원페이지 쇼핑몰 작품을 내가 산 서버에 올리고 서버를 실행시키는 일을 해볼 것이다.

 

DB 서버와 연결하기

쇼핑몰 페이지에서 DB를 이용하기 떄문에 데이터가 잘 들어갔는지 확인하려면, 마찬가지로 내 컴퓨터에서 서버에 있는 mongoDB로 내 Robo3T를 접속해놔야 한다. 

 

  • mongoDB > create > Address: 서버 IP 주소

  • Authenticatioin > Perfom authentication 체크 > 이름과 비밀번호 입력 > Test > 체크 확인

  • Save > Connect

내 컴퓨터에서 Robo3T를 이용해서 내가 만든 서버에 DB에 접속 완료!

우리가 내 컴퓨터에서 DB에 접속할 떄는 이름과 비밀번호 입력을 받지 않았었다.

서버에서도 아이디, 비밀번호를 입력받지 않고 접속하기 위해서 다음 코드를 입력해준다.

client = MongoClient('mongodb://유저이름:비밀번호@localhost', 27017)

app.py 파일에 원래 있던 client 대신 해당 코드로 바꿔주고 서버에 업로드해주고 실행하면 된다.

 

*업로드

filezilla에서 원래 있던 app.py 파일을 지우고 내 컴퓨터를 새로고침 한 후 업데이트할 파일을 업로드 해주면 된다.

 

🙋‍♀️ Robo3T 서버 이름/비밀번호 바꾸고 싶은 경우

대부분은 바꿀 필요 없긴하다.

위에서 서버환경세팅을 위해서 다운받는 파일 EC2 한번에 세팅하기 파일을 편집기에서 열면

#MongoDB set user, set conf file 부분에 user/pwd 부분을 원하는 이름과 비밀번호로 바꾼 뒤 업로드 한 다음에 실행하면 변경된다!

 

6. 포트포워딩

페이지 주소를 보면 IP주소/5000 으로 포트 번호가 붙어있다. 

이 포트 번호를 떼는 작업에 대해 알아볼 것이다.

  • http 요청에서는 80포트가 기본이기 때문에 굳이 :80을 붙이지 않아도 자동으로 연결된다.
  • 포트 번호를 입력하지 않아도 자동으로 접속되기 위해 우리는 80포트로 오는 요청을 5000 포트로 전달하게 하는 포트 포워딩(port forwarding)을 사용할 것이다.
  • 80으로 들어왔나요? 그럼 5000포트로 가세요! 

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

보통은 initial 세팅을 할 때 다 설정해준다. 우리는 앞서 설치한 initial 파일에 설정이 다 되어있어서 :5000 을 떼고 서버IP 주소만 입력해도 잘 접속된다!

 

7. nohup 설정하기

내 컴퓨터에서 서버를 돌리다가 GitBash를 종료하면(=SSH 접속을 끊으면) 프로세스가 종료되면서 서버도 함께 꺼진다.

서버가 잘 돌아가게 하려면 원격접속을 끊어도 서버는 계속 동작하게 만들어주어야 한다!

 

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

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

 

서버 종료하기 - 강제종료하는 방법

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

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

 

다시 켜기

nohup python app.py &

 

8. 도메인 구입하기

  • 가비아 > My가비아 > DNS 관리툴 > 해당 도메인: 설정
  • 레코드 수정 > 레코드 추가 > 호스트/IP주소 입력 > 저장

구매한 도메인과 IP 주소를 연결한 다음 해당 도메인 주소로 들어가면 위에서 만들었던 쇼핑몰 페이지로 연결 되는 것을 확인할 수 있다! 

네임서버에 내 도메인-IP가 매칭되는 시간이 있으므로 약간의 시간을 가진 후, 내 도메인으로 접근하면, 접속이 된다!

 

9. og 태그

내 프로젝트도 카톡, 페이스북, 슬랙 등 SNS에 공유했을 때 예쁘게 나오도록 꾸며보자!

  • '내 사이트의 제목' 입력하기
  • '보고 있는 페이지의 내용 요약' 입력하기
  • 적당한 이미지를 만들거나/골라서 static 폴더에 ogimage.png로 저장하기 (800*400)

 

og 태그 넣기

<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.kakao.com/tool/clear/og
  • 페이스북 og 태그 초기화하기: https://developers.facebook.com/tools/debug/

 

    '개발 일지✨' 카테고리의 다른 글
    • 내일배움단 프로젝트 챌린지 1일차 개발일지
    • [스파르타 코딩클럽 후기] 왕초보 비개발자를 위한, 웹개발 종합반 (프로그래밍 실무, 풀스택)
    • [4주차] 쇼핑몰 페이지 완성하기
    • 스파르타 코딩클럽 4주차

    티스토리툴바