웹개발 5주차

yurimLee·2023년 2월 23일
0

1. AWS

아마존에서 운영하는 클라우드 서비스

클라우드 서비스란? 인터넷에 있는 컴퓨터를 빌려 쓰는 서비스이다.

2. 버킷 리스트

  1. 프로젝트 세팅하기

  2. 패키지 설치코드

    pip install flask pymongo dnspython
  3. 뼈대 준비하기

  • app.py
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

@app.route("/bucket", methods=["POST"])
def bucket_post():
    sample_receive = request.form['sample_give']
    print(sample_receive)
    return jsonify({'msg': 'POST 연결 완료!'})
    
@app.route("/bucket", methods=["GET"])
def bucket_get():
    return jsonify({'msg': 'GET 연결 완료!'})

if __name__ == '__main__':
    app.run('0.0.0.0', port=5000, debug=True)
  • index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
      crossorigin="anonymous"
    />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
      crossorigin="anonymous"
    ></script>

    <link
      href="https://fonts.googleapis.com/css2?family=Gowun+Dodum&display=swap"
      rel="stylesheet"
    />

    <title>인생 버킷리스트</title>

    <style>
      * {
        font-family: "Gowun Dodum", sans-serif;
      }
      .mypic {
        width: 100%;
        height: 200px;

        background-image: linear-gradient(
            0deg,
            rgba(0, 0, 0, 0.5),
            rgba(0, 0, 0, 0.5)
          ),
          url("https://images.unsplash.com/photo-1601024445121-e5b82f020549?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1189&q=80");
        background-position: center;
        background-size: cover;

        color: white;

        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
      }
      .mypic > h1 {
        font-size: 30px;
      }
      .mybox {
        width: 95%;
        max-width: 700px;
        padding: 20px;
        box-shadow: 0px 0px 10px 0px lightblue;
        margin: 20px auto;
      }
      .mybucket {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
      }

      .mybucket > input {
        width: 70%;
      }
      .mybox > li {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;

        margin-bottom: 10px;
        min-height: 48px;
      }
      .mybox > li > h2 {
        max-width: 75%;
        font-size: 20px;
        font-weight: 500;
        margin-right: auto;
        margin-bottom: 0px;
      }
      .mybox > li > h2.done {
        text-decoration: line-through;
      }
    </style>
    <script>
      $(document).ready(function () {
        show_bucket();
      });
      function show_bucket() {
        fetch('/bucket').then(res => res.json()).then(data => {
                // console.log(data)
            })
      }

      function save_bucket() {
        let formData = new FormData();
        formData.append("sample_give", "샘플데이터");

        fetch('/bucket', {method: "POST",body: formData,}).then((response) => response.json()).then((data) => {
            alert(data["msg"]);
            window.location.reload();
          });
      }
      
    </script>
  </head>
  <body>
    <div class="mypic">
      <h1>나의 버킷리스트</h1>
    </div>
    <div class="mybox">
      <div class="mybucket">
        <input
          id="bucket"
          class="form-control"
          type="text"
          placeholder="이루고 싶은 것을 입력하세요"
        />
        <button onclick="save_bucket()" type="button" class="btn btn-outline-primary">기록하기</button>
      </div>
    </div>
    <div class="mybox" id="bucket-list">
      <li>
        <h2>✅ 호주에서 스카이다이빙 하기</h2>
        <button onclick="done_bucket(5)" type="button" class="btn btn-outline-primary">완료!</button>
      </li>
      <li>
        <h2 class="done">✅ 호주에서 스카이다이빙 하기</h2>
      </li>
      <li>
        <h2>✅ 호주에서 스카이다이빙 하기</h2>
        <button type="button" class="btn btn-outline-primary">완료!</button>
      </li>
    </div>
  </body>
</html>

4. POST, GET 최종 코드

  • app.py
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)

from pymongo import MongoClient
client = MongoClient('mongodb+srv://sparta:test@cluster0.mmgalfj.mongodb.net/?retryWrites=true&w=majority') 
db = client.dbsparta

@app.route('/')
def home():
    return render_template('index.html')

# 버킷 리스트 입력하기
@app.route("/bucket", methods=["POST"])
def bucket_post():
    bucket_receive = request.form['bucket_give']
    doc = {
        'bucket': bucket_receive
    }
    db.bucket.insert_one(doc)
    return jsonify({'msg': '저장 완료!'})

# 버킷 리스트 조회하기
@app.route("/bucket", methods=["GET"])
def bucket_get():
    all_buckets = list(db.bucket.find({}, {'_id': False}))
    return jsonify({'result': all_buckets})

if __name__ == '__main__':
    app.run('0.0.0.0', port=5000, debug=True)
  • index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
      crossorigin="anonymous"
    />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script
      src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
      crossorigin="anonymous"
    ></script>

    <link
      href="https://fonts.googleapis.com/css2?family=Gowun+Dodum&display=swap"
      rel="stylesheet"
    />

    <title>인생 버킷리스트</title>

    <style>
      * {
        font-family: "Gowun Dodum", sans-serif;
      }
      .mypic {
        width: 100%;
        height: 200px;

        background-image: linear-gradient(
            0deg,
            rgba(0, 0, 0, 0.5),
            rgba(0, 0, 0, 0.5)
          ),
          url("https://images.unsplash.com/photo-1601024445121-e5b82f020549?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1189&q=80");
        background-position: center;
        background-size: cover;

        color: white;

        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
      }
      .mypic > h1 {
        font-size: 30px;
      }
      .mybox {
        width: 95%;
        max-width: 700px;
        padding: 20px;
        box-shadow: 0px 0px 10px 0px lightblue;
        margin: 20px auto;
      }
      .mybucket {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
      }

      .mybucket > input {
        width: 70%;
      }
      .mybox > li {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;

        margin-bottom: 10px;
        min-height: 48px;
      }
      .mybox > li > h2 {
        max-width: 75%;
        font-size: 20px;
        font-weight: 500;
        margin-right: auto;
        margin-bottom: 0px;
      }
      .mybox > li > h2.done {
        text-decoration: line-through;
      }
    </style>
    <script>
      $(document).ready(function () {
        show_bucket();
      });

      // 버킷 리스트 조회하기
      function show_bucket() {
        fetch('/bucket').then(res => res.json()).then(data => {
            let rows = data['result']
            $('#bucket-list').empty()
            rows.forEach((a)=>{
                let bucket = a['bucket']
                let temp_html = `<li>
                                    <h2>✅ ${bucket}</h2>
                                </li>`
                $('#bucket-list').append(temp_html)
            })
        })
      }

      // 버킷 리스트 입력하기
      function save_bucket() {
        let bucket = $('#bucket').val()

        let formData = new FormData();
        formData.append("bucket_give", bucket);

        fetch('/bucket', {method: "POST",body: formData,}).then((response) => response.json()).then((data) => {
            alert(data["msg"]);
            window.location.reload();
          });
      }
      
    </script>
  </head>
  <body>
    <div class="mypic">
      <h1>나의 버킷리스트</h1>
    </div>
    <div class="mybox">
      <div class="mybucket">
        <input
          id="bucket"
          class="form-control"
          type="text"
          placeholder="이루고 싶은 것을 입력하세요"
        />
        <button onclick="save_bucket()" type="button" class="btn btn-outline-primary">기록하기</button>
      </div>
    </div>
    <div class="mybox" id="bucket-list">
      <li>
        <h2>✅ 호주에서 스카이다이빙 하기</h2>
        <button onclick="done_bucket(5)" type="button" class="btn btn-outline-primary">완료!</button>
      </li>
      <li>
        <h2 class="done">✅ 호주에서 스카이다이빙 하기</h2>
      </li>
      <li>
        <h2>✅ 호주에서 스카이다이빙 하기</h2>
        <button type="button" class="btn btn-outline-primary">완료!</button>
      </li>
    </div>
  </body>
</html>

3. 팬명록

  • app.py
from flask import Flask, render_template, request, jsonify
app = Flask(__name__)

from pymongo import MongoClient
client = MongoClient('mongodb+srv://sparta:test@cluster0.mmgalfj.mongodb.net/?retryWrites=true&w=majority')
db = client.dbsparta

@app.route('/')
def home():
   return render_template('index.html')

# 댓글 저장
@app.route("/guestbook", methods=["POST"])
def guestbook_post():
    # 1. 데이터 명세
    name_receive = request.form['name_give']
    comment_receive = request.form['comment_give']

    # 2. 다큐먼트
    doc = {
        'name': name_receive,
        'comment': comment_receive
    }

    # 3. DB 저장
    db.fan.insert_one(doc)

    # 4. 메시지 수정
    return jsonify({'msg': '저장 완료!'})

# 댓글 조회
@app.route("/guestbook", methods=["GET"])
def guestbook_get():
    # 1. DB 데이터 여러 개 조회
    all_comments = list(db.fan.find({}, {'_id': False}))
    return jsonify({'result': all_comments})

if __name__ == '__main__':
   app.run('0.0.0.0', port=5000, debug=True)
  • index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
        crossorigin="anonymous"></script>

    <title>초미니홈피 - 팬명록</title>

    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+KR:wght@200;300;400;500;600;700;900&display=swap"
        rel="stylesheet" />
    <style>
        * {
            font-family: "Noto Serif KR", serif;
        }

        .mypic {
            width: 100%;
            height: 300px;

            background-image: linear-gradient(0deg,
                    rgba(0, 0, 0, 0.5),
                    rgba(0, 0, 0, 0.5)),
                url("https://cdn.topstarnews.net/news/photo/201807/456143_108614_510.jpg");
            background-position: center 30%;
            background-size: cover;

            color: white;

            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
        }

        .mypost {
            width: 95%;
            max-width: 500px;
            margin: 20px auto 20px auto;

            box-shadow: 0px 0px 3px 0px black;
            padding: 20px;
        }

        .mypost>button {
            margin-top: 15px;
        }

        .mycards {
            width: 95%;
            max-width: 500px;
            margin: auto;
        }

        .mycards>.card {
            margin-top: 10px;
            margin-bottom: 10px;
        }
    </style>
    <script>
        $(document).ready(function () {
            set_temp();
            show_comment();
        });

        // 날씨 세팅
        function set_temp() {
            fetch("http://spartacodingclub.shop/sparta_api/weather/seoul").then((res) => res.json()).then((data) => {
                let temp = data['temp']
                $('#temp').text(temp)
            });
        }

        // 댓글 저장
        function save_comment() {
            // 5. 데이터 명세, html에서 값 가져오기
            let name = $('#name').val()
            let comment = $('#comment').val()

            // 6. 값 전달
            let formData = new FormData();
            formData.append("name_give", name);
            formData.append("comment_give", comment);

            fetch('/guestbook', { method: "POST", body: formData, }).then((res) => res.json()).then((data) => {
                alert(data["msg"]);
                // 7. 새로고침
                window.location.reload()
            });
        }

        // 댓글 조회
        function show_comment() {
            fetch('/guestbook').then((res) => res.json()).then((data) => {
                // 2. DB 데이터 불러오기
                let rows = data['result']

                // 6. 기존 코멘트 없애주기
                $('#comment-list').empty()

                // 3. 데이터 명세
                rows.forEach((a) => {
                    let name = a['name']
                    let comment = a['comment']

                    // 4. html에 붙이기
                    let temp_html = `<div class="card">
                                        <div class="card-body">
                                            <blockquote class="blockquote mb-0">
                                                <p>${comment}</p>
                                                <footer class="blockquote-footer">${name}</footer>
                                            </blockquote>
                                        </div>
                                    </div>`

                    // 5. 데이터를 붙일 html 위치 표기
                    $('#comment-list').append(temp_html)
                })
            })
        }
    </script>
</head>

<body>
    <div class="mypic">
        <h1>십센치(10cm) 팬명록</h1>
        <p>현재기온: <span id="temp">36</span></p>
    </div>
    <div class="mypost">
        <div class="form-floating mb-3">
            <input type="text" class="form-control" id="name" placeholder="url" />
            <label for="floatingInput">닉네임</label>
        </div>
        <div class="form-floating">
            <textarea class="form-control" placeholder="Leave a comment here" id="comment"
                style="height: 100px"></textarea>
            <label for="floatingTextarea2">응원댓글</label>
        </div>
        <button onclick="save_comment()" type="button" class="btn btn-dark">
            댓글 남기기
        </button>
    </div>
    <div class="mycards" id="comment-list">
        <div class="card">
            <div class="card-body">
                <blockquote class="blockquote mb-0">
                    <p>새로운 앨범 너무 멋져요!</p>
                    <footer class="blockquote-footer">호빵맨</footer>
                </blockquote>
            </div>
        </div>
        <div class="card">
            <div class="card-body">
                <blockquote class="blockquote mb-0">
                    <p>새로운 앨범 너무 멋져요!</p>
                    <footer class="blockquote-footer">호빵맨</footer>
                </blockquote>
            </div>
        </div>
        <div class="card">
            <div class="card-body">
                <blockquote class="blockquote mb-0">
                    <p>새로운 앨범 너무 멋져요!</p>
                    <footer class="blockquote-footer">호빵맨</footer>
                </blockquote>
            </div>
        </div>
    </div>
</body>

</html>

4. og 태그

팬명록 서비스를 클라우드 환경에 올리기 전에, og 태그를 신경써야 한다.
og:image, og:title, og:description 태그를 나의 웹 사이트에 잘 넣어두면 카카오톡이나 페이스북에 url을 공유했을 때 자동으로 정보들이 만들어진 모습을 볼 수 있다.

  • index.html
<meta property="og:title" content="내 사이트의 제목" />
<meta property="og:description" content="보고 있는 페이지의 내용 요약" />
<meta property="og:image" content="이미지URL" />

5. 내 프로젝트를 서버에 돌리기

내 웹서비스를 런칭하는다는 것은 무엇일까?
지금까지 우리는 localhost:5000으로 서비스를 돌렸다.
여기서 몇가지 세팅만 더 해주면 내 컴퓨터를 끄지 않고 전세계 사람들이 서버에 방문해서 서비스를 받아갈 수 있다.
컴퓨터를 끄지 않는다는 것은 어떤 의미일까? 컴퓨터를 계속 켜놔야 서버에서 누군가 요청이 올 때마다 서비스를 제공할 수 있다는 말이다.
하지만 컴퓨터를 계속 킬 수 없다. 그렇기 때문에 보통 내 컴퓨터 대신 계속 켜놓을 컴퓨터를 구매하는데 그것을 '서버'라고 한다.
그런데 요새는 컴퓨터를 직접 사서 운영하지 않는다. 인터넷 환경에서 컴퓨터를 대여하고 내 파일들을 업로드한다. 결국, 실물 컴퓨터냐, 인터넷 컴퓨터냐의 차이이다.
인터넷 컴퓨터를 '클라우드 환경'이라고 얘기한다.
그 중 가장 유명한 클라우드 환경 회사가 AWS(아마존 웹 서비스)이다. 그 중에서도 AWS Elastic Beanstalk라고 하는 기능을 제공하고 있다. 굉장히 배포가 쉽고 자동화가 되어있는 방식이다.

1. 배포할 파일 세팅하기

  • 배포 명령어 모움
# 터미널 준비하기
mkdir deploy
cp app.py deploy/application.py
cp -r templates deploy/templates
pip freeze > deploy/requirements.txt
cd deploy

# appication.py 세팅하기
application = app = Flask(__name__)
app.run()

# 패키지 설치하기 
pip install awsebcli

# 보안 자격증명
eb init

# 초기 설정
eb create myweb

# 코드 수정 & 업데이트
eb deploy myweb
  • pip freeze > deploy/requirements.txt
    requirements.txt라는 파일에 우리가 여태까지 설치한 라이브러리를 적어달라는 명령 코드

  • deploy 폴더에 작업한 폴더 및 파일을 복사

2. 서버 사기

3. 서버에 파일 올리기

4. 서버에 올린 웹 페이지 수정하기

  1. 내 텀퓨터에서 작업하기
    delploy 폴더 안에 있는 파일들이 실제로 배포되는 것이기 때문에, 수정 작업을 할 때에는 내 컴퓨터인 localhost:5000에서 돌려 본 다음에 괜찮으면 배포하면 된다. (application.py가 아닌 app.py에서 작업)
  2. 배포 폴더로 파일 옮기기
    delploy 폴더 안으로 옮길 때는 local 파일을 싹다 복사한 다음 붙여넣기
  3. 배포 폴더로 이동 후 업로드하기
    cd deploy 후 eb deploy myweb

※ 주의사항

eb create를 할 때마다 서버를 구매하게 된다.
'AWS - Elastic Beanstalk - 환경/애플리케이션' 경로로 들어가면 애플리케이션이 하나만 있어야 한다. 두 개 이상이면 돈이 나간다.
만약 여러개가 있다면 작업 들어가서 애플리케이션을 삭제해야 한다.
또한 1년이 지나면 과금이 되니 삭제를 해야 한다.

6. 변경 코드 실서버에 업로드하기

  1. deploy에서 터미널 실행
  2. deploy 폴더로 이동
    cd deploy
  3. 업로드
    eb deploy myweb

0개의 댓글