선발대

[스파르타] 웹 프로그래밍 A-Z 기초 5주차 (완강) 본문

스파르타코딩클럽/강의 정리

[스파르타] 웹 프로그래밍 A-Z 기초 5주차 (완강)

신선한 스타트 2021. 12. 16. 17:11

1. 수업 후기

 

  • 강의 개수: 14개
  • 총 강의시간: 1시간 6분
  • 수업 목표:
  • 1. Flask 프레임워크를 활용해서 API를 만들 수 있다.
  • 2. '버킷리스트'를 완성한다.
  • 3. EC2에 내 프로젝트를 올리고, 자랑한다!

 

내가 만든 홈페이지 (클릭) / 지금은 내렸다!

 

 드디어 완강했다. 총 수강시간6시간 정도 걸린 것 같다. 드디어 서버 배포 과정을 배웠는데, 코딩보다는 새로운 서비스를 결제하고 연결하는 방법을 주로 배웠다. 지난 강의에 이어 이번 5주차 강의에서는 3번째 미니 프로젝트를 진행했다. 처음의 아리송함은 다소 해소되었지만 나중에 더 익숙해지는 과정이 필요할 것 같다. 그래도 내용 정리한 것을 보면서 진행하면 미니 프로젝트와 비슷한 난이도의 과제는 잘 끝낼 수 있을 것 같다.

 

 모든 과정을 다 끝내고 전체적인 과정을 돌아보니, 내가 어려워했던 부분은 아직 중간지점이었다. 그때는 이 과정이 어떻게 최종 화면에 적용되는지 이해할 수 없었는데, 지금 와서 보니 필수적이기 때문에 어쩔 수 없이 넘어야 했었던 지점이었다. 오히려 요소 하나씩 꼼꼼히 분석하는 것보다 전체적인 숲을 보고 부족한 부분으로 다시 돌아오는 것이 나에게 맞는 공부법이었다. 물론 매 수업은 최선을 다해야 한다. 그래야 나중에 따라갈 수 있다.

 

 지난주까지는 파이썬에 대해 정말 기초적인 지식만 있었는데, 1주일 만에 나만의 홈페이지를 만들고 다른 사람들에게 배포할 수 있다는 점이 놀랍다. 어려워 보였는데 차근차근해나가니 할 수 있었다. 마지막으로 갈수록 새로운 개념이 많아서 진도가 조금 늘어진 경향이 있는데 어차피 끝내야 할 일들이니, 다른 강의에서는 부지런히 잘 마무리해야겠다. 

 

 웹 기초이다 보니 수업시간에 다루는 핵심기능을 제외하고, 디자인이나 다른 기능들은 코드 스니펫으로 미리 작성되어 있는 경우가 많았다. 다른 강의들과 미니 프로젝트를 진행하면서 나중에는 혼자의 힘으로 홈페이지를 만들어보고 싶다. 그러니까 앞으로도 화이팅~

 

2. 수업내용 정리

5-1. 5주차 오늘 배울 것 & 설치
더보기

01. 오늘 배울 것 이야기 - 5주차: 미니 프로젝트 3

 

  • 같은 난이도의 유사한 프로젝트를 진행하며 지난번 배운 것들 복습.
  • 버킷리스트 제작 및 팬명록 배포까지 마무리하기.

 

02. 이번 주 수업을 위해 설치할 것들!

 

 

Download FileZilla Client for Windows (64bit x86)

Download FileZilla Client for Windows (64bit x86) The latest stable version of FileZilla Client is 3.57.0 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

 

 

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

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

www.gabia.com

 

5-2. [버킷리스트] - 프로젝트 세팅
더보기

01. 문제 분석 - 완성작부터 보기!

 

완성된 홈페이지 화면

 

02. 프로젝트 설정 - flask 폴더 구조 만들기

 

  • static, templates 폴더 + app.py

 

03. 패키지 설치하기

 

  • 3개: flask, pymongo, dnspython

 

5-3. [버킷리스트] - 뼈대 준비하기
더보기

01. 프로젝트 준비 - index.html, app.py 준비하기

 

  • 코드스니펫으로 기본 코드 붙여넣기

 

02. 프로젝트 준비 - mongoDB Atlas 창 띄워두기

 

  • app.py 실행해서 mongoDB랑 연결되는지 확인

 

5-4. [버킷리스트] - POST연습 (기록하기)
더보기

01. API 만들고 사용하기 - 버킷리스트 기록 API (Create → POST)

 

  • 0. 미리 요약하자면
  • 우리가 하고 싶은 것: 입력 > '기록하기' 버튼 클릭 > 아래에 리스트 쌓임
  • (1) 요청정보: URL = /bucket, 요청방식 = POST
  • (2) 클라(Ajax) → 서버(flask) : bucket
  • (3) 서버(flask) → 클라(ajax) : 메세지를 보냄 (기록 완료!)
  • (4) 서버에서 번호를 만들어 함께 넣어주는 작업해야됨. (그래야 업데이트 가능)

 

  • 1. 클라이언트와 서버 연결 확인하기
  • 서버 코드: app.py, 클라이언트 코드: index.html

 

  • 2. 서버부터 만들기
  • bucket 정보를 받아서 저장함.
  • + 버킷 번호와 완료여부를 함께 넣어주기.

 

  • 3. 클라이언트 만들기
  • bucket 정보만 보내주면 됨

 

  • 4. 완성 확인하기
  • DB에 데이터 잘 들어갔나 확인. num, done도 확인.

 

5-5. [버킷리스트] - GET연습 (보여주기)
더보기

01. API 만들고 사용하기 - 버킷리스트 조회 API (Read → GET)

 

  • 0. 미리 요약하자면
  • (1) 요청정보: URL = /bucket, 요청방식 = GET
  • (2) 클라(Ajax) → 서버(flask) : 없음
  • (3) 서버(flask) → 클라(ajax) : 전체 버킷리스트 보여주기

 

  • 1. 클라이언트와 서버 연결 확인하기
  • 서버 코드: app.py, 클라이언트 코드: index.html

 

  • 2. 서버부터 만들기
  • 따로 받을 것 없이 buckets에 주문정보를 담아서 내려주기만 하면 됨.

 

  • 3. 클라이언트 만들기
  • 응답을 잘 받아서 for문으로 붙여주기.

 

  • 4. 완성 확인하기
  • 버킷리스트 잘 붙었는지 확인.

 

5-6. [버킷리스트] - POST연습 (완료하기)
더보기

01. API 만들고 사용하기 - 버킷리스트 완료 API (Update → POST)

 

  • 0. 미리 요약하자면
  • (1) 요청정보: URL = /bucket/done, 요청방식 = POST
  • (2) 클라(Ajax) → 서버(flask) : num (버킷 넘버) -- 어떤 bucket의 done 값을 0 → 1 해야하는지 알 수 있음.
  • (3) 서버(flask) → 클라(ajax) : 메세지를 보냄 (버킷 완료!)

 

  • 1. 클라이언트와 서버 연결 확인하기
  • 서버 코드: app.py, 클라이언트 코드: index.html

 

  • 2. 서버부터 만들기
  • 버킷 번호를 받아서 업데이트하면 됨.
  • num_receive는 문자열로 들어오므로 숫자로 변환 필요.
  • (클라이언트로부터 숫자를 받아도 서버에서는 문자열로 처리됨. 따라서 처리 필요.)

 

  • 3. 클라이언트 만들기
  • HTML 만들어질 때 적힌 버킷 넘버 보여주기

 

  • 4. 완성 확인하기
  • 잘 작동하는지 확인

 

02. 전체 완성 코드

 

## 서버코드 app.py

from pymongo import MongoClient # [POST] 2. 코드 붙여넣어주기
import certifi
ca = certifi.where()
client = MongoClient('mongodb+srv://test:sparta@cluster0.frvlk.mongodb.net/Cluster0?retryWrites=true&w=majority', tlsCAFile=ca)
db = client.dbsparta

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():
    bucket_receive = request.form['bucket_give'] # [POST] 1. 변수 설정

    # [POST] 4. 버킷리스트 전체 불러와서 count에 순번 저장
    bucket_list = list(db.bucket.find({}, {'_id': False}))
    count = len(bucket_list) + 1

    # [POST] 3. DB에 데이터 저장
    doc = {
        'num': count, # 버킷리스트 순번
        'bucket': bucket_receive,
        'done': 0 # 완료(1), 미완료(0)
    }
    db.bucket.insert_one(doc)
    return jsonify({'msg': '등록 완료!'})


@app.route("/bucket/done", methods=["POST"])
def bucket_done(): # 2[GET] 1. 변수 받아오고 업데이트 하기
    num_receive = request.form['num_give']
    # 클라이언트에서 서버로 숫자를 넘겨줘도, 서버는 문자로 받음. 따라서 따로 변환 필요함.
    db.bucket.update_one({'num': int(num_receive)}, {'$set': {'done': 1}})
    return jsonify({'msg': '버킷 완료!'})


@app.route("/bucket", methods=["GET"])
def bucket_get():
    # [GET] 1. 서버에서 모든 데이터 가져오기
    bucket_list = list(db.bucket.find({}, {'_id': False}))
    # [GET] 2. bucket_list 담아서 클라이언트로 내려주기, 이러면 서버 끝!
    return jsonify({'buckets': bucket_list})


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

 

// 클라이언트 코드: index.html

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

        function show_bucket() {
            $.ajax({
                type: "GET",
                url: "/bucket",
                data: {},
                success: function (response) {
                    // [GET] 3. 사전형 데이터를 변수 각각에 할당하기
                    let rows = response['buckets']
                    for (let i = 0; i < rows.length; i++) {
                        let bucket = rows[i]['bucket']
                        let num = rows[i]['num']
                        let done = rows[i]['done']

                        // [GET] 4. done 에 따라서 li의 형태 바꿔주기
                        let temp_html = ``
                        if (done == 0) { // 아직 안한 것
                            temp_html = `<li>
                                            <h2>✅ ${bucket}</h2>
                                             <button onClick="done_bucket(${num})" type="button" class="btn btn-outline-primary">완료!</button>
                                            </button>
                                        </li>` // 같은 script 안은 #'' 아님, 이건 ID
                        } else{
                            temp_html = `<li>
                                            <h2 class="done">✅ ${bucket}</h2>
                                        </li>`
                        }
                        // [GET] 5. 기존의 데이터에 붙여주기
                        $('#bucket-list').append(temp_html)

                    }

                    // console.log(response) -- Object 형태로 나옴
                    // console.log(response['buckets']) -- bucket, done, num 사전형으로 나옴.

                }
            });
        }

        function save_bucket() {
            // [POST] 5. 입력받은 데이터를 변수에 저장
            let bucket = $('#bucket').val()

            $.ajax({
                type: "POST",
                url: "/bucket",
                data: {bucket_give:bucket}, // [POST] 6. 서버로 보내주기
                success: function (response) {
                    alert(response["msg"])
                    window.location.reload() // [POST] 7. 새로고침
                }
            });
        }

        function done_bucket(num) { // 새로운 줄이 생성될 때부터 줄의 번호와 같이 생성되어야 함.
            $.ajax({
                type: "POST",
                url: "/bucket/done",
                // [2GET] 2. 아예 num을 바로 넘겨준다.
                data: {'num_give': num},
                success: function (response) {
                    alert(response["msg"])
                    window.location.reload() // [2GET] 3. 새로고침
                }
            });
        }
    </script>

 

5-7. 내 프로젝트를 서버에 올리기
더보기

01. "웹서비스 런칭"에 필요한 개념 소개

 

  • 배포: 누구나 내 서비스를 사용할 수 있게 하기 위한 작업들
  • 이제 내가 만든 프로젝트를 배포함. 웹 서비스 런칭하는 것.
  • 웹 서비스 런칭하려면 언제나 클라이언트 요청에 응답할 수 있는 서버에 프로젝트 실행해야 함.

 

  • localhost:5000을 모두가 접근할 수 있게, 언제나 요청에 응답하기 위해서는:
  • (1) 컴퓨터가 항상 켜져있고 프로그램이 계속 실행되어야 함. -- (옛날) 회사 서버실, (현재) 클라우드 서비스
  • (2) 모두 접근할 수 있는 공개 주소인 공개 IP주소(Public IP Address)로 내 웹 서비스에 접근 할 수 있도록.
  • 서버는 그냥 컴퓨터이므로, 내 컴퓨터를 외부 접속이 가능하게 설정해서 서버로 사용할 수 있음.
  • 우리는 AWS 클라우드 서비스에서 편하게 관리하기 위해,
  • 항상 켜 놓을 수 있는 컴퓨터인 EC2 사용권 구입하여 서버로 사용할 것임.
  • mongoDB도 클라우드 환경에서 작동되기 때문에, 트래픽 대응도 편함.

 

5-8. AWS 서버 구매하기
더보기

01. EC2 서버 구매하기

  • AWS EC2 서버 사기:
  • (1) 클릭만으로 내가 원하는 서버(컴퓨터)의 설정을 정하고,
  • 거기에 컴퓨터를 실행시키기 위한 운영체제(OS)를 설치할 것임.
  • (2) OS로 리눅스 Ubuntu 설치. 오픈소스로 발전된 OS.
  • 오픈소스 리눅스이기 때문에, 대부분 컴퓨터 빌려쓸 때는 리눅스가 깔린 컴퓨터를 빌려쓰게 됨.
  • AWS EC2: https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-2
 

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

 

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

  • 리눅스는 마우스가 없어서 전부 명령어로 실행해야 함.
  • ex. 폴더만들기: mkdir 폴더명, 리눅스는 아무 일도 없으면 잘된 것임.
  • ls: 지금 내 위치에서 폴더들을 보는 것.
  • cd 폴더명: 원하는 폴더로 이동
  • cd.. : 폴더 밖으로 나가기
  • 리눅스 명령어 안 외워도 된다.

 

02. EC2 서버 종료하는 방법 (1년 후 자동결제 방지!)

  • 인스턴스 중지: 컴퓨터 전원 끄기, 인스턴스 종료: 컴퓨터 반납 (무료 기간 1년 지나기 전에 종료!)
  • 새 컴퓨터 만드려면 인스턴스 종료 누르고 새 인스턴스 생성함.

 

03. EC2 접속하기

 

  • AWS EC2에 접속하기 (준비 상식 편):
  • SSH(Secure Shell Protocol): 다른 컴퓨터에 접속할 때 쓰는 프로그램. 
  • 다른 것들보다 보안이 상대적으로 뛰어남. 22번 포트가 열려있어야 컴퓨터가 접속 가능함.
  • AWS EC2는 이미 22번 포트가 열려 있음.

 

  • AWS EC2에 접속하기:
  • Mac OS: Mac은 ssh가 있어서, 명령어로 바로 접근 가능.
  • Window: ssh가 없으므로 git bash라는 프로그램 이용.

 

Git Bash 로 리눅스 컴퓨터에 접속한 모습

 

04. 간단한 리눅스 명령어 연습하기

 

  • 리눅스는 윈도우와 달리 '쉘 명령어'로 OS를 조작한다. (일종의 마우스 역할)
  • 리눅스 커널에서 윗화살표 누르면 바로 전에 쓴 명령어 나옴.
  • 먼저 ls로 자신이 어디인지 확인 후, cd로 원하는 곳으로 간다. 파이썬 파일은 python 
  • 가장 많이 쓰는 명령어:
ls 내 위치의 모든 파일을 보여준다.
pwd 내 위치(폴더의 경로)를 알려준다.
mkdir 내 위치 아래에 폴더를 하나 만든다.
cd [폴더명] 나를 [폴더명] 폴더로 이동시킨다.
cd .. 나를 상위폴더로 이동시킨다.
cp -r [복사할 것] [붙여넣을 것] 복사, 붙여넣기
rm - rf [지울 것] 지우기
sudo [명령어] 관리자 권한으로 명령어를 실행한다.
sudo su 관리가 권한으로 들어간다. (나올 때는 exit으로 나온다.)

 

5-9. 서버 세팅하기
더보기

01. 서버 환경 통일하기

 

  • 우리는 지금 막 컴퓨터를 구매한 상태임.
  • 세팅(업그레이드, DB설치, 명령어 통일 등)을 해줘야 이용에 편리함.

 

02. filezilla를 이용해서, 간단한 python 파일을 올려봅시다.

 

  • 파일질라 왼쪽이 내 컴퓨터, 오른쪽은 내가 산 컴퓨터.
  • Host: 내 EC2 서버의 ip, User: ubuntu 로 입력.

 

03. 파이썬 파일을 실행해보기

 

Git Bash 로 폴더 생성, 폴더 내용물 확인 완료

 

04. [한걸음 더] 서버 환경 세팅 - 한 줄씩 설명

 

  • 실제 업무에서는 아래 내용을 인프라 엔지니어, 개발팀장이 하는 경우가 많음.
  • 모든 사람들이 외우고 있는 코드가 아니므로, 맥락만 이해하도록.
# python3 -> python: python3를 python으로 명령 내리겠다.
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 10

# pip3 -> pip: pip3라는 패키지 마법사를 설치한다. 
sudo apt-get update
sudo apt-get install -y python3-pip
# 그 후 pip3 명령어를 pip로 사용할 수 있게 하는 명령어
sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1

# port forwarding: localhost:5000에서 5000을 분리하는 명령어, 80포트로 들어오는 요청을 5000포트로 넘겨줌.
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 5000

# 원격 접속 종료해도 서버 계속 돌아가게 하기
nohup python app.py &

# nohub으로 유지된 서버 강제종료하기
ps -ef | grep 'python app.py' | awk '{print $2}' | xargs kill

 

5-10. Flask 서버를 실행해보기
더보기

01. 팬명록 완성본을 filezilla로 EC2에 업로드해봅니다.

 

  • 파일질라에 homework 폴더를 드래그 드롭으로 EC2 인스턴스 > home/ubuntu 폴더에 업로드

 

02. pip로 패키지를 설치하기

 

  • PyCharm 설정에서 했던 작업을 명령어로 작성.
pip install flask

 

03. 하는 김에, 다른 패키지들도 설치해줄까요?

 

  • pymongo, dnspython 도 설치

 

04. 다시 flask 서버를 실행해보기

 

  • flask 서버 실행 명령어: python app.py
  • 서버 실행 후, 크롬에서 접속한다. http://[내 EC2 IP]:5000/
  • 아직 작동하지 않음 → AWS에서 약간의 설정이 더 필요함.

 

05. AWS에서 5000 포트를 열어주기

 

  • EC2 서버(=가상의 내 컴퓨터)에서 포트 따로 설정하는 것 외에도,
  • AWS EC2에서 자체적으로 포트를 열고 닫을 수 있게 관리함.
  • ∴ AWS EC2 Security Group에서 인바운드 요청 포트를 열어줘야 함.
  • 규칙 추가해서 포트 5000, 80 총 2개 생성해준다.
  • 그리고 다시 퍼블릭 주소 입력하면 휴대폰에서도 접속 가능해짐, 인터넷 배포 완료!
  • 그렇지만 Git Bash 끄면 연결도 같이 끊어짐. 내 컴퓨터 계속 켜둘 수 없으니, 창 닫아도 홈페이지 연결 유지하게!

 

06. 어떻게 되는 걸까? 포트 번호 없애기 - 기본 개념

 

  • 우리는 위에서 이미 포트포워딩 세팅 해뒀으므로, 여기에서는 개념만 숙지.
  • 5000포트에서 웹 서비스 실행되므로, 매번 :5000 이 따라옴. 이 포트 번호를 없애려면?
  • 즉, 포트번호가 없어도 자동으로 접속될 수 있게 하려면?

 

  • http 요청에서는 80포트가 기본이므로 :80 안 붙여도 자동으로 연결됨. (붙여도 연결됨)
  • ∴ 포트포워딩(port forwarding)를 사용한다: 80포트로 오는 요청을 5000포트로 전달한다.
  • 리눅스에서 기본으로 제공해주는 포트포워딩 사용.

 

 

07. 다시 접속해봅니다!

 

  • http://내아이피 → 잘 작동하는 것을 확인
  • 이제 app.py 파일 수정하고 다듬어서 올리면 진짜 프로젝트가 됨.

 

5-11. nohup 설정하기

 

더보기

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

 

  • 현재 상황: Git bash 또는 맥의 터미널 종료하면 ( = SSH 접속 끊으면) 프로세스 종료됨.
  • 따라서 서버도 작동 중지. 그러나 우리가 원격 접속 끊어도 서버는 계속 동작해야 함. 그럼 어떻게
  • 원격 접속 종료해도 서버 계속 돌아가게 하기: 기존의 python app.py 부분을 이걸로 대체한다.
nohup python app.py &
  •  서버 강제종료하는 방법:
ps -ef | grep 'python app.py' | awk '{print $2}' | xargs kill

 

02. SSH 접속을 종료한 뒤, 접속해봅니다!

 

  • 브라우저에서 접속하기: http://내AWS아이피/
  • 파이참에서 끝난 작업물들을 배포하는 법 정리:
  • 1. 파일 질라에서 내가 산 컴퓨터에 static, templates, app.py 만 올린다.
  • 2. nohub 이용해서 켜준다.
  • 3. 작업이 미완성인 경우, 위의 방법으로 강제종료하고 파일질라에서 새로운 파일로 교체한다.

 

5-12. 도메인 연결하기
더보기

01. 도메인 구입 / 연결

 

  • 도메인 구매란? 네임서버를 운영해주는 업체에 IP와 도메인 매칭 유지비를 내는 것.
  • 한국이든 글로벌 업체이든 상관없지만 우리는 한국의 '가비아' 에서 구입함.

 

02. 구입 후 아래 화면을 띄워주세요

 

 

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

 

dns.gabia.com

  •  DNS 설정 > 호스트이름: @, IP 주소 입력 > 확인, 저장 >> 내가 산 도메인으로 연결 완료!

 

03. 10분 정도 기다려주세요!

 

  • 네임서버에 내 도메인-IP가 매칭되는 시간 필요

 

04. IP주소로 접근해보기

 

# 내 IP주소로 flask 서버가 잘 돌고 있는지 확인.
http://내AWS아이피/

# 약간의 시간 후, 내 도메인으로 접근하면 접속됨.
http://내도메인/

 

5-13. og 태그
더보기

01. og 태그 만들기

 

  • 스파르타피디아의 og:image, og:title, og:description 태그 활용하여 개인 프로젝트에 사용
<!-- <head> 태그 안에 og 태그 넣어주기 -->

<meta property="og:title" content="내 사이트의 제목" />
<meta property="og:description" content="보고 있는 페이지의 내용 요약" />
<meta property="og:image" content="이미지URL" />
  • 내 컴퓨터에 있는 파일만 변경되었으니, 파일질라에서 홈페이지의 파일도 삭제하고 교체해야 함.
  • 전부 수정했는데 카카오톡에 올려도 변경된 이미지가 보이지 않았다.
  • 해결방법 출처: https://blog.secuof.net/30, OG 캐쉬 삭제했더니 수정된 이미지가 나타났다.
 

KakaoTalk 미리보기(오픈그래프) 이미지 캐쉬 삭제 방법

Meta Tag 이미지 지정 방법 Meta Tag에 og:image를 이용해 사용자에게 미리보기 이미지를 지정 및 제공할 수있다. 아래는 `https://www.kakaocorp.com/`의 Meta Tag의 og:image 정보이다. meta content="//t1.kaka..

blog.secuof.net

 

이제 카톡으로도 깔끔하게 보인다.

 

5-14. 5주차 끝 & 숙제 설명

 

Comments