본문 바로가기

스파르타코딩 공부내용 정리/웹개발 플러스

1주차_나만의 일기장 예제로 웹개발 기본 익히기

수업의 목표

  1. 웹서비스 만들기 전 과정을 복습한다.
  2. 파일 올리기 기능을 구현한다.
  3. AWS에 배포 과정을 복습한다.

 

필수 프로그램

PyCharm, AWS 가입, Python, mongoDB, Studio 3T, Git Bash(Only Windows), Filezilla

 

이론 복습

  1. 클라이언트 : 브라우저 등 [User] | 요청하는 쪽
  2. 서버 : Flask 서버(app.py) 등 [Administrator] | 요청을 받아서 무언가를 돌려주는 쪽
  3. API : 요청을 받기 위해 뚫어놓은 '창구'
  4. 서버에서 해당하는 HTML, CSS, JS 찾아서 로딩
  5. DB : 정보 저장

주요 질문들

[서버]

  • 서버는 컴퓨터의 "ROLE"
  • HTML + CSS + JS 를 주기도 하지만 JSON을 주기도 한다
  • JSON은 항상 "ID : Value" 형태를 갖는다.

[API]

  • 데이터 수정 시 : POST
  • 데이터 가져올 시 : GET 등의 타입 존재

[HTML, CSS, JS]

  • HTML 뻐대 / CSS 꾸미기 / JS 움직이게 하는 것
  • CSS 꾸밀 때 이름표 붇이고(class="클래스명"), <style></style>안에 .클래스명 으로 작성

[JQuery]

  • JavaScript의 라이브러리로 HTML 조작 EASY
  • 라이브러리 -> 남이 만들어 놓은 코드를 갖다쓰기에 "임포트"해야 한다.
  • id로 이름표 (id="아이디"), $('#아이디').val()과 같이 input 박스의 값을 가져올 수 있다.

[Ajax]

  • 서버 통신 위해 필요
  • 생김새
$.ajax({
	type : "GET",
    url : "요청할 URL",
    data : {},
    success: function (response) {
    	// 서버가 준 데이터가 response에 담김
    }
})

[Flask]

  • 서버를 만드는 "프레임워크"
  • app.py를 만들고 아래 코드를 넣어 "http://localhost:5000/"으로 접속하면, index.html 페이지를 볼 수 있다.
from flask import Flask, render_template, jsonify, request
app = Flask(__name__)

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

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

 

프로젝트 준비

templates, static 폴더 만들고, app.py 파일 만들기

패키지 설치 : flask, pymongo

만들어가는 순서

  1. 생김새를 먼저 만들기 - HTML + CSS
  2. 만들어야 할 기능 파악 (API)
  3. 서버-클라이언트 연결 코드 만들기
  4. API 만들기

 

나홀로일기장 LV.1

[ 부트스트랩 시작 템플릿 ]

<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
        integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
        integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
        crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
        integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
        crossorigin="anonymous"></script>

    <title>스파르타코딩클럽 | 부트스트랩 연습하기</title>
</head>

<body>
    <h1>이걸로 시작해보죠!</h1>
</body>

</html>

[ 부트스트랩 컴포넌트 ]

https://getbootstrap.com/docs/4.0/components/alerts/

[ LV.1 완성코드 ]

<!doctype html>
<html lang="en">

<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
          integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"
            integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
            crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
            integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
            crossorigin="anonymous"></script>

    <title>스파르타코딩클럽 | 나홀로일기장</title>

    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Jua&display=swap" rel="stylesheet">

    <style>
        * {
            font-family: 'Jua', sans-serif;
        }
        .posting-box {
            width: 500px;
            margin-top: 20px;
        }
        .wrap {
            width: 900px;
            margin: auto;
        }
        .container {
            padding-left: 50px;
        }
    </style>
</head>

<body>
<div class="wrap">
    <div class="jumbotron jumbotron-fluid">
    <div class="container">
        <h1>나홀로 일기장</h1>
        <div class="posting-box">
            <div class="form-group">
                <input type="email" class="form-control" id="exampleFormControlInput1" placeholder="사진 제목">
            </div>
            <div class="form-group">
                <textarea class="form-control" id="exampleFormControlTextarea1" rows="3" placeholder="내용 입력"></textarea>
            </div>
            <button type="button" class="btn btn-primary">저장하기</button>
        </div>
    </div>
</div>
    <div class="card-columns">
    <div class="card">
<!--        <img class="card-img-top" src="..." alt="Card image cap">-->
        <div class="card-body">
            <h5 class="card-title">창덕궁</h5>
            <p class="card-text">날씨가 참 좋았다.</p>
        </div>
    </div>
    <div class="card">
<!--        <img class="card-img-top" src="..." alt="Card image cap">-->
        <div class="card-body">
            <h5 class="card-title">창덕궁</h5>
            <p class="card-text">날씨가 참 좋았다.</p>
        </div>
    </div>
    <div class="card">
<!--        <img class="card-img-top" src="..." alt="Card image cap">-->
        <div class="card-body">
            <h5 class="card-title">창덕궁</h5>
            <p class="card-text">날씨가 참 좋았다.</p>
        </div>
    </div>
    <div class="card">
<!--        <img class="card-img-top" src="..." alt="Card image cap">-->
        <div class="card-body">
            <h5 class="card-title">창덕궁</h5>
            <p class="card-text">날씨가 참 좋았다.</p>
        </div>
    </div>
    <div class="card">
<!--        <img class="card-img-top" src="..." alt="Card image cap">-->
        <div class="card-body">
            <h5 class="card-title">창덕궁</h5>
            <p class="card-text">날씨가 참 좋았다.</p>
        </div>
    </div>
    <div class="card">
<!--        <img class="card-img-top" src="..." alt="Card image cap">-->
        <div class="card-body">
            <h5 class="card-title">창덕궁</h5>
            <p class="card-text">날씨가 참 좋았다.</p>
        </div>
    </div>
</div>
</div>
</body>

</html>

 

GET 요청

[ JS 로딩 후 실행 ]

$(document).ready(function () {
		alert('안녕!')
})

[ GET 요청 Ajax ]

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

[ GET 요청 API ]

@app.route('/diary', methods=['GET'])
def show_diary():
    sample_receive = request.args.get('sample_give')
    print(sample_receive)
    return jsonify({'msg': 'GET 연결 완료!'})

 

POST 요청

[ Post 요청 Ajax ]

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

[ POST 요청 API ]

@app.route('/diary', methods=['POST'])
def save_diary():
    sample_receive = request.form['sample_give']
    print(sample_receive)
    return jsonify({'msg': 'POST 요청 완료!'})

 

이 프로젝트에서 필요한 API

Posting API and Listing API

 

IMG태그

<div class="card">
    <img src="../static/monet.jpg" class="card-img-top">
    <div class="card-body">
        <h5 class="card-title">모네의 그림</h5>
        <p class="card-text">그림을 보면 마음이 안정된다.</p>
    </div>
</div>

 

파일 업로드(HTML, CSS)

[ 파일업로드 라이브러리 ]

<script src="https://cdn.jsdelivr.net/npm/bs-custom-file-input/dist/bs-custom-file-input.js"></script>

[ 파일업로드 코드 ]

bsCustomFileInput.init()

 

파일 업로드(서버, 클라이언트)

[ 서버 쪽 받기 코드 ]

file = request.files["file_give"]

save_to = 'static/mypicture.jpg'
file.save(save_to)

[ 클라이언트 쪽 보내기 코드 ]

function posting() {
    let title = $('#title').val()
    let content = $("#content").val()

    let file = $('#file')[0].files[0]
    let form_data = new FormData()

    form_data.append("file_give", file)
    form_data.append("title_give", title)
    form_data.append("content_give", content)

    $.ajax({
        type: "POST",
        url: "/diary",
        data: form_data,
        cache: false,
        contentType: false,
        processData: false,
        success: function (response) {
            alert(response["msg"])
            window.location.reload()
        }
    });
}

 

파일 이름 변경 후 저장

[ 확장자 빼내기 ]

extension = file.filename.split('.')[-1]

[ 새로운 이름 만들어주기 ]

today = datetime.now()
mytime = today.strftime('%Y-%m-%d-%H-%M-%S')

filename = f'file-{mytime}'

[ 새로운 이름으로 저장하기 ]

save_to = f'static/{filename}.{extension}'
file.save(save_to)

[ 변경된 파일 이름을 db에도 저장하기 ]

doc = {
    'title':title_receive,
    'content':content_receive,
    'file':f'{filename}.{extension}',
}
db.diary.insert_one(doc)

 

 

간단한 리눅스 명령어

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

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

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

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

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

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

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

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

 

 

AWS-EC2 설정 포트 종류

[ Port # 80 ] : HTTP

[ Port # 5000 ] : Flask

[ Port # 27017 ] : mongoDB Access Port

 

EC2 세팅하기

[ 세팅 파일]

initial_ec2.sh
0.00MB

[ 업로드 후 git bash(MAC은 터미널) 명령어 ]

- 권한 설정

sudo chmod 755 initial_ec2.sh

- 실행

./initial_ec2.sh

 

AWS 배포 시 FLASK, PYMONGO 패키지 설치

[ FLASK ]

pip install flask

[ pymongo ]

pip install pymongo

 

포트포워딩

아무 포트로 들어와도 타깃 포트로 맞춰주는 것

http가 80이니까 80으로 들어오면 5000으로 맞춰주면 된다.

 

nohup 설정

설정 전에는 -> 컴퓨터 종료하면 바로 종료 => nohup 필요

[ nohup 켜기 및 다시 켜기 ]

nohup python app.py &

[ 서버 종료하기 ]

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

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

 

 

스파르타코딩클럽 1주차 Notion 주소

https://teamsparta.notion.site/1-eb7121fc88f1424da56a8bcb8a6b6782

 

[스파르타코딩클럽] 웹개발 플러스 - 1주차

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

teamsparta.notion.site