[TIL] 9월 15일: 간단한 싱글페이지 구현

Jung·2021년 9월 15일
0

TIL

목록 보기
3/77
post-thumbnail

세 번째 TIL

지금까지 공부했던 것들을 기반으로 간단한 프로젝트를 만들고 있다. Flask와 MongoDB를 사용해보지 않았는데 이번 기회에 사용해볼 수 있어서 좋았고 개인적으로 토이 프로젝트도 만들어 봐야겠다는 생각이 들었다.

Flask, MongoDB를 활용해서 만든 결과물을 리마인드 시킬 겸 포스팅 한다.

주문 사이트

Flask, Ajax - 서버와 클라이언트 통신
MongoDB - 입력한 값을 DB에 삽입, DB에 있는 데이터를 조회

일단 결과물은 아래와 같다.


MongoDB (Robo3T)


api에서 가져온 달러와 원 환율이 반영이 되고 input 태그에 입력한 값들이 MongoDB에 삽입된다. 그리고 DB에 저장된 데이터들을 조회해서 화면 아래 테이블에 나오게 구현했다.

생각해보면 어려운 내용은 아니었지만 오류랑 자주 싸워봤으니까... 난 괜찮다..!🤣

서버

from flask import Flask, render_template, jsonify, request

app = Flask(__name__)

from pymongo import MongoClient

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

flask와 각종 기능들을 사용하기 위한 라이브러리들을 import하고 db를 지정한다.

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

localhost:5000/로 들어가면 index.html이 렌더링 되게 설정한다.
(5000 포트는 뒤에서 설정)

@app.route('/order', methods=['GET'])
def view_orders():
    shoppingInfo = list(db.shopping.find({}, {'_id': False}))

    return jsonify({'shoppingInfos': shoppingInfo})

localhost:5000/order에 GET 요청이 왔을 때 실행이 되는 코드다.
이 코드에선 DB shopping 컬렉션에 저장되어 있는 데이터들을 조회하고 리스트로 만든 후에 변수에 저장한다. DB에 데이터 넣는 작업은 POST 요청에서 진행된다.
jsonify는 flask 프레임워크 기능인데 json 형태로 응답을 주는 기능이다.
localhost:5000/order에 가보면 아래와 같은 리턴 결과를 확인할 수 있다.

{
    shoppingInfos: [
        {
            address: "Seoul",
            name: "kj",
            phoneNum: "010-1234-1234",
            quantity: "1"
        },
        {
            address: "Seoul",
            name: "user1",
            phoneNum: "010-1234-1234",
            quantity: "2"
        }
    ]
}
@app.route('/order', methods=['POST'])
def save_order():
    name_receive = request.form['name_give']
    quantity_receive = request.form['quantity_give']
    address_receive = request.form['address_give']
    phoneNum_receive = request.form['phoneNum_give']

    doc = {
        'name':name_receive,
        'quantity':quantity_receive,
        'address':address_receive,
        'phoneNum':phoneNum_receive
    }
    if name_receive and quantity_receive and address_receive and phoneNum_receive:
        result = 'ok'
        db.shopping.insert_one(doc)

    return jsonify({'result':result})

localhost:5000/order에 POST 요청이 왔을 때 실행이 되는 코드다.
Ajax를 통해 request를 서버에 보내면 request에 담긴 데이터들을 불러와 변수에 저장한다.
저장한 값을 db에 insert한다.

if name_receive and quantity_receive and address_receive and phoneNum_receive:
    result = 'ok'
    db.shopping.insert_one(doc)

if문을 사용하지 않고 insert를 해버리면 입력창에 모든 데이터를 입력하지 않고 요청을 보냈을 때에도 db에 저장이 되기 때문에 입력창에 값을 전부 입력했을 때 db에 insert 되게 했다.

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

포트를 5000으로 설정한다.

클라이언트

<script>
    $(document).ready(function () {
        getRate();
        showOrder();
    });
</script>

화면이 렌더링 됐을 때 콜백함수를 실행한다.

<script>
function getRate() {
    $.ajax({
        type: "GET",
        url: "http://spartacodingclub.shop/sparta_api/rate",
        data: {},
        success: function (response) {
            let rate = response['rate'];
            $('#rate').append(rate);
        }
    })
}
</script>

http://spartacodingclub.shop/sparta_api/rate 에는 달러-원 환율 데이터가 json 형태로 있다. 이곳에서 'rate'라는 키가 가진 값을 가져와 id가 rate인 자리에 이어 붙인다.

<script>
    function showOrder() {
    	$.ajax({
    	    type: "GET",
            url: "/order",
            data: {},
            success: function (response) {
                let shoppingInfo = response['shoppingInfos'];
                for (let i = 0; i < shoppingInfo.length; i++) {
                    let name = shoppingInfo[i]['name'];
                    let quantity = shoppingInfo[i]['quantity'];
                    let address = shoppingInfo[i]['address'];
                    let phoneNum = shoppingInfo[i]['phoneNum'];

                    let temp_html = `<tr>
                                         <td>${name}</td>
                                         <td>${quantity}</td>
                                         <td>${address}</td>
                                         <td>${phoneNum}</td>
                                     </tr>`;
                    $('#orders-box').append(temp_html);
                }
            }
        })
    }
</script>

서버에서 localhost:5000/order에 GET 요청이 오면 db 데이터들을 조회해서 jsonify로 json 형태로 리턴되게 했다.
거기서 각각의 데이터들을 가져와 html 화면에 넣는 코드다.

<script>
    function order() {
        let name = $('#name').val();
        let quantity = $('#quantity').val();
        let address = $('#address').val();
        let phoneNum = $('#phoneNum').val();

        let patternPhone = /^(01[016789]{1}|02|0[3-9]{1}[0-9]{1})[-][0-9]{3,4}[-][0-9]{4}$/;

        if (!name) {
            alert('이름을 입력해주세요');
            $('#name').focus();
            return;
        } else if (!quantity) {
            alert('수량을 선택해주세요');
            $('#quantity').focus();
            return;
        } else if (!address) {
            alert('주소를 입력해주세요');
            $('#address').focus();
            return;
        } else if (!phoneNum) {
            alert('휴대폰번호를 입력해주세요');
            $('#phoneNum').focus();
            return;
        } else if (!patternPhone.test(phoneNum)) {
            alert('휴대폰번호 입력 형식이 틀립니다. \n010-0000-0000으로 입력해주세요')
            return;
        }

        $.ajax({
            type: "POST",
            url: "/order",
            data: {name_give: name, quantity_give: quantity, address_give: address, phoneNum_give: phoneNum},
            success: function (response) {
                if (response['result'] == 'ok') {
                    alert('주문 완료');
                    window.location.reload();
                }
            }
        })
    }
</script>

localhost:5000/order에 POST 요청을 보낼 때 실행되는 코드다.
alert 함수들은 입력창에 값이 없는 채로 요청을 보내면 경고창이 뜨게 한다.

let patternPhone = /^(01[016789]{1}|02|0[3-9]{1}[0-9]{1})[-][0-9]{3,4}[-][0-9]{4}$/;

이 부분은 전화번호 양식에 맞게 하기 위해 정규표현식을 사용했다.

data: {name_give: name, quantity_give: quantity, address_give: address, phoneNum_give: phoneNum}

localhost:5000/order에 POST 요청을 보낼 때 이 데이터들을 key:value 형태로 서버에 보낸다. 정상적으로 보내지면 서버는 이 값들을 사용할 수 있다.

서버의 응답 데이터가 클라이언트에게 도착하면 자동으로

if (response['result'] == 'ok') {
    alert('주문 완료');
    window.location.reload()
}

위 코드가 실행된다.

서버에서 입력창 데이터들이 전부 입력되면

{
    'result': 'ok'
}

위와 같은 json 형태가 리턴되도록 했다.

따라서 입력창 데이터들이 전부 입력됐을 때 주문 완료 메세지가 알림창으로 뜨게 했고 window.location.reload()를 통해 새로고침 되도록 했다.

AWS

웹 서비스를 배포하기 위해서 서버가 필요한데 우리가 사용하는 컴퓨터에 외부 접속이 가능하게 설정하고 서버로 사용할 수 있다. 하지만 보안도 위험하고 컴퓨터를 항상 켜놓아야 한다는 단점이 있기 때문에 요즘은 클라우드 서비스 AWS를 사용해 웹 서비스를 런칭할 수 있다.

AWS는 다양한 서비스를 제공한다. 그 중 EC2를 사용할 건데 AWS 홈페이지에 따르면 EC2는 아래와 같다.

Amazon Elastic Compute Cloud(Amazon EC2)는 안전하고 크기 조정이 가능한 컴퓨팅 용량을 클라우드에서 제공하는 웹 서비스입니다. 개발자가 더 쉽게 웹 규모의 클라우드 컴퓨팅 작업을 할 수 있도록 설계되었습니다. Amazon EC2의 간단한 웹 서비스 인터페이스를 통해 간편하게 필요한 용량을 얻고 구성할 수 있습니다. 컴퓨팅 리소스에 대한 포괄적인 제어권을 제공하며, Amazon의 검증된 컴퓨팅 인프라에서 실행할 수 있습니다.

EC2 인스턴스에 접속하는 방법은 개인적으로 정리한 노션 링크를 참고하면 된다.

노션 - EC2 인스턴스 접속

FileZilla

내 PC의 파일들을 AWS EC2 인스턴스로 전송하는 프로그램이다.

FileZilla를 실행시킨 후 New site를 한다. 프로토콜에는 SFTP로, 호스트에는 AWS 인스턴스의 퍼블릭 IPv4 주소, 로그온 유형은 키파일, 그리고 다운 받은 키 페어 파일을 선택한다. 우리는 AWS 인스턴스를 ubuntu로 했기 때문에 사용자는 ubuntu로 하면 된다.
이렇게 하면 연결이 돼서 내 PC 파일들을 EC2 인스턴스로 전송할 수 있다.

AWS에서 구매한 PC에서 각종 세팅들을 해야 이용할 때 편한데 보통 실무에서는 해당 업무를 인프라 엔지니어 또는 개발 팀장님이 하는 경우가 많다고 한다. 모든 것을 외울 수 없으니 인터넷에 검색해보면서 이해하는 것이 좋다고 생각한다. (알고 있어서 나쁠 건 없지만...😂)

AWS 인스턴스 접속 후 설정

[Mac] EC2 컴퓨터의 시간대를 한국으로 맞추는 명령어

ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

[Mac] python3 명령어를 python으로 사용할 수 있게 하는 명령어

update-alternatives --install /usr/bin/python python /usr/bin/python3 10

[Mac] pip3 설치, pip3 명령어를 pip로 사용할 수 있게 하는 명령어

# pip3 설치
apt-get update
apt-get install -y python3-pip

# pip3 대신 pip 라고 입력하기 위한 명령어
update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1

[Mac] 80포트로 들어오는 요청을 5000포트로 넘겨주는 명령어

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

Window
윈도우는 git bash를 이용해 앞에 sudo를 붙이면 된다.

nohup 설정

서버를 켜기 위해서는 SSH 접속이 유지되어야 하는데 SSH 접속을 끊었을 때도 서버가 켜진 상태로 유지하게 하려면 어떻게 할까?

원격 접속 종료 후에도 서버가 켜진 상태 유지하는 명령어

nohup python app.py &

서버 켜진 상태 유지하는 명령어 취소 - 강제 종료

# 아래 명령어로 pid 값(프로세스 번호) 확인
ps -ef | grep 'app.py'

# 아래 명령어로 해당 프로세스를 죽인다
kill -9 [pid값]
profile
97kim.github.io

0개의 댓글