
먼저 코딩에 도움이 되는 사이트를 소개하겠다.
모든 개발 언어 백과사전(교육형): https://www.w3schools.com/html/default.asp
Html, CSS, JS등 웹개발관련 백과사전: https://developer.mozilla.org/en-US/
Html, CSS, JS 실시간 반영 사이트: https://codepen.io/pen/
CSS속성 확인 사이트: https://cssgenerator.org/
그린 그림이나 사진을 토대로 html과 css 작성 사이트: https://makereal.tldraw.com/
프로그래밍 특화 챗GPT: https://claude.ai/login?returnTo=%2F%3F
부트스트랩: https://getbootstrap.kr/
폰트형 아이콘: https://fontawesome.com/v4/icons/
구글 폰트: https://fonts.google.com/?subset=korean
(폰트 적용법: link 태그를 복사해서 head 사이에, CSS를 복사해서 style 사이에 넣습니다.)
단축키 모음(Mac기준)
코드 재정렬: Shift + Option(Alt) + F
주석 처리: Command(Ctrl) + /
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML 기본 요소</title>
</head>
<body>
<!-- 구역을 나누는 태그들 -->
<div>div 태그는 구역을 나눈다.</div>
<div>
<p>p는 문단이다.</p>
<p>문단 사이에는 줄바꿈이 일어난다.</p>
<div>
<ul>
<li> bullet point!1 </li>
<li> bullet point!2 </li>
</ul>
<!-- 구역 내 콘텐츠 태그들 -->
<h1>h1은 제목</h1>
<h2>h2는 소제목</h2>
<h3>h3~h6으로 갈수록 글씨가 작아진다.</h3>
<hr>
가로줄인 hr 태그는 종료 태그가 따로 없는 empty 태그이다.
<hr>
span 태그는 요소 안에서 특정 <span style="color:red">글자</span>를 꾸밀 때 쓸 수 있다.
<hr>
a 태그: <a href="http://naver.com/"> 하이퍼링크 </a>
<hr>
img 태그: <img src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png" />
<hr>
input 태그: <input type="text" />
<hr>
button 태그: <button>버튼</button>
<hr>
textarea 태그: <textarea>여러 줄을 입력할 수 있다.</textarea>
</body>
</html>
/* 모든 태그에 적용하고 싶을 때 */
* {
속성: 선택지;
}
/* 특정 태그를 지칭할 때 */
태그 {
속성1: 선택지1;
속성2: 선택지2;
}
/* 클래스 이름 앞에는 .을 찍는다. */
.클래스 {
속성: 선택지;
}
/* 아이디 앞에는 #을 붙인다. */
#아이디 {
속성: 선택지;
}
/* 특정 클래스를 갖는 특정 태그를 지칭할 때는 클래스를 뒤에 붙여 쓴다 */
태그.클래스 {
속성: 선택지;
}
/* 자식 선택자는 > 뒤에 적는다 */
/* 즉, 아래는 '아이디'라는 아이디를 갖는 요소 바로 안의 '태그' 태그를 선택한 것이다 */
#아이디 > 태그 {
속성: 선택지;
}
/* 자손 선택자는 띄어쓰기로 구분한다. */
/* 즉, 아래는 '클래스'라는 클래스를 갖는 '태그1' 태그 안에 있는 모든 '태그2'를 선택한 것이다 */
태그1.클래스 태그2 {
속성: 선택지;
}
각 항목에 대한 속성 요소들도 많은데, 그것은 인터넷을 찾아보자
변수선언
let
ex) let 변수명 = 값
변수 값을 확인할때
[console.log(변수명)]으로 콘솔에서 값을 확인 가능
또는 콘솔창에서 변수명만 쳐도 값이 확인된다.
새값을 넣을때
[변수명 = 새 값]으로 새 값을 넣어주면 된다.
다른 변수 값을 새 변수에 넣을수 있다.
[let 변수명 = 새 변수명]
변수명 선언시
snake case(first_name)과 camel case(firstName)을 많이 쓴다.
자료형과 기본 연산
숫자형(+ - * / %, ++, +=)
문자열("문자" + "문자")
함수명.toUpperCase(): 모든 알파벳 대문자로
특정글자만 추출할때 split을 쓴다.
let myemail = 'test@gmail.com'
let result = myemail.split('@') // ['test','gmail.com']
result[0] // test (리스트의 첫번째 요소)
result[1] // gmail.com (리스트의 두 번째 요소)
//각 요소는 0부터 시작이다.
let result2 = result[1].split('.') // ['gmail','com']
result2[0] // gmail -> 우리가 알고 싶었던 것
result2[1] // com
// 한 줄로 쓸 수도 있다. 보통 해당 코드를 많이 사용
myemail.split('@')[1].split('.')[0]
해당 코드를 활용하여 특정문자를 다른 문자로 바꿀수 있다.
let txt = '서울시-마포구-망원동'
let names = txt.split('-'); // '서울시','마포구','망원동'
let result = names.join('>'); // '서울시>마포구>망원동'
Boolean 자료형
참과 거짓을 나타낸다.
대문자로 쓰면 변수명으로 판단하기 때문에 소문자로 써야한다.
let 변수명= true 또는 false
비교연산자(< > <= >= == !=)
AND 연산자(&&)
OR 연산자(||)
리스트와 딕셔너리
숫자, 문자열 등 다른 값들을 여러 개 갖는 자료형.
리스트의 요소에는 순서가 있음. 그래서 인덱스를 이용하여 값을 받아올 수 있다.
ex) let 리스트 명 = [리스트 항목]
리스트 항목에는 ''로 된 단어도 가능함.
헷갈릴수 있는 내용은 let list = [1, 2, 3, 4]일때
1은 인덱스가 0이다
list[1] 은 2라는 말이다.
리스트 안에 리스트를 추가하는 것도 가능하다.
ex)let list = [1, 2, 3, [4, 5]]
키와 벨류로 이루어진 딕셔러리를 입력하는 것도 가능하다.
ex) let dict = [{'name':'Tom', 'age':'23'}, {'name':'Jerry', 'age':'20'}]
함수
function 함수이름(변수들) {
내릴 명령 순차 작성
}
// 사용시
함수이름(변수들)
조건문
조건에 따라 다른 코드를 실행해야할 때 씀.
조건에는 boolean 자료형이 들어가며 보통 비교연산자를 사용.
if (조건1) {
조건1 만족 시 실행
}
else if (조건2) {
조건1을 불만족하고 조건2를 만족할 때 실행
}
else {
조건1과 조건2 둘다 불만족할 때 실행
}
반복문
같은 실행을 반복시 사용.
for (1. 시작조건; 2. 반복조건; 4. 더하기) {
3. 조건을 만족할 때 실행
}
//1 -> 2 -> 3 -> 4 -> 1 순서 실행
JS의 미리 작성된 코드를 모아둔 것. 부트스트랩같이 임포트해서 사용한다.
다음과 같이 복잡한 JS 코드를
document.getElementById("element").style.display = "none"; //JS
$('#element').hide(); //jQuery
//템플릿리터럴은 다음과 같이 쓴다.
let temp_html = `<div class="card">
<img class="card-img-top"
src="${img_url}"
alt="Card image cap">
<div class="card-body">
<a href="${link_url}" class="card-title">${title}</a>
<p class="card-text">${desc}</p>
<p class="card-text comment">${comment}</p>
</div>
</div>`;
$('#cards-box').append("추가 내용");
서버에서 요청을 보내고 응답을 받기 위해 정의된 명세.
API 응답으로 Html 전체가 아닌 데이터(JSON)만 따로 정리해서 보내줄 수 있다.
브라우저-서버 간 통신에서 데이터를 전달하기 위해 인간이 읽을 수 있는 텍스르를 사용하는 개방형 표준 포맷.
다음은 서울시 JSON 형식의 오픈 API이다.
RealtimeCityAir: {
list_total_count: 25,
RESULT: {
CODE: "INFO-000",
MESSAGE: "정상 처리되었습니다"
},
row: [
{
MSRDT: "202501301500",
MSRRGN_NM: "도심권",
MSRSTE_NM: "중구",
PM10: 18,
PM25: 11,
O3: 0.032,
NO2: 0.014,
CO: 0.3,
SO2: 0.003,
IDEX_NM: "보통",
IDEX_MVL: 52,
ARPLT_MAIN: "O3"
}
RealtimeCityAir가 키가 되고
뒤의 중괄호{}인 각 도시별 정보가 value가 된다.
※ Ajax 세팅 주의
<script
src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0="
crossorigin="anonymous"
></script>
해당 코드로 불러와야함. 기존꺼로는 불가하다.
비동기적인 웹 애플리케이션 제작에 쓰이는 웹 개발 기법.
기본적인 형태는 다음과 같다.
$.ajax({
type: "GET", // GET 방식으로 요청한다.
url: "http://openapi.seoul.go.kr:8088/6d4d776b466c656533356a4b4b5872/json/RealtimeCityAir/1/99",
data: {}, // 요청하면서 함께 줄 데이터 (GET 요청시엔 비워야함)
success: function(response){ // 성공시, 서버에서 준 결과를 response라는 변수에 입력됨
console.log(response) // 서버에서 준 결과를 이용해서 나머지 코드를 작성
}
})
function q1() {
$.ajax({
type: "GET",
url: "원하는 사진 관련 URL",
data: {},
success: function(response){
let imgurl = response[0]['URL요소'];
$("#img-cat").attr("src", imgurl);
}
})
}
//고양이 사진 랜덤 코드
function q1() {
$.ajax({
type: "GET",
url: "https://api.thecatapi.com/v1/images/search",
data: {},
success: function(response){
let imgurl = response[0]['url'];
$("#img-cat").attr("src", imgurl);
}
})
}
자연어처리, 머신러닝 등 직접 구현하기 어려운 기능들을 다른 개발자의 라이브러리를 이용해 쉽게 코드를 작성 가능
//문자열 코드
변수명.upper() //모든 알파벳 대문자로 바꾸기
result = 변수명.split('기준문자')
//split을 통해 리스트를 나눌수 있다.
변수명.split('@')[1].split('.')[0]
//이와 같이 쓰면 이메일의 원하는 정보만 가져온다.
변수명 = txt.replace('바꿀 대상 문자', '바꾼 문자')
//replace를 통해 대치시킬수 있다.
불 자료형인 참, 거짓 자료형을 나타낼 수 있다. 그러나 JS(소문자)와 달리 첫 글자가 대문자여야 한다.
만약, 소문자로 적으면 변수명으로 인식한다.
비교연산자(< > <= >= == !=),
논리연산자(and, or) 사용가능
리스트는 JS와 비슷하다. 리스트명 = {}와 []를 쓴다. len(리스트명)은 리스트의 길이를 구한다. 리스트 간 덧셈과 자연수 곱셈도 가능하다.
ex) 리스트명 = [{'name':'Tom', 'age':'23'}, {'name':'Jerry', 'age':'20'}]
함수는 JS에서 function을 썻다면, 파이썬에선 def형식을 쓴다.
def 함수명(x):
return 2*x+3
함수명(2) #7이 답이다.
def 조건문명(age):
if age > 20:
print('성인입니다')
elif age >= 13:
print('청소년이에요')
else:
print('어린이네요!')
조건문명(23) #성인입니다
리스트명 = ['사과','배','감','귤']
for fruit in 리스트명:
print(fruit)
#리스트 항목이 한 개씩 한줄로 나온다.
//JS에서는 다음과 같이 나타낸다.
리스트명 = ['사과','배','감','귤']
for i in range(len(리스트명)): # i 가 0, 1, 2, 3일 때
fruit = 리스트명[i]
print(fruit)
패키지는 모듈을 모아 놓은 단위. 이런 패키지의 묶음을 라이브러리라고 하며 보통 두 용어를 혼용해서 많이 쓴다.
-> 효율적인 패키지 관리를 위해 가상환경을 쓰는 것이 좋다. 이유는 많기 때문에 인터넷에 찾아보는 것이 좋을 것 같다.
해당 순서대로 bash에서 명령어를 실행하면 된다. 디렉터리는 수정해야한다.
python3 -m venv /Users/유저명/Documents/JungleProject/파일명/.venv
source /Users/유저명/Documents/JungleProject/파일명/.venv/bin/activate
디렉터리 앞에 (.venv)가 뜬다면 가상환경 활성화된 것
Pip로 원하는 패키지 설치, 설치 차트는 밑에 참고(bash에서 안되면 비주얼 스튜디오 코드 bash에서 해보기)
비주얼 스튜디오 코드에서 Command shift p 로 인터럽터 가상으로 잡기
Flask: python3 -m pip install flask
Requests: pip install requests
Bs4: pip install beautifulsoup4
pymongo: pip install pymongo
//복붙하지 말고 손수치는걸 권장한다.
웹 페이지에서 우리가 원하는 부분의 데이터를 수집해오는 것.
반면, 웹 크롤링은 주기적으로 웹에서 정보를 분류/색인하고 업데이트 부분을 찾는 것이라 둘의 의미는 엄연히 다르다.
beautifulsoup4라는 패킷을 통해 웹 스크래핑을 할 수 있다.(pip install bs4)
사용법은 다음과 같다.
import requests
from bs4 import BeautifulSoup //bs4임포트
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')
movies = soup.select('.받아올 클래스 > .하위 클래스 > 하위태그명')
//soup.select 관련된 내용은 아래를 참고하자.
# 선택자를 사용하는 방법 (copy selector)
soup.select('태그명')
soup.select('.클래스명')
soup.select('#아이디명')
# class 명 내의 띄어쓰기(공백)은 '.'으로 바꾸어 쓰거나, 조건이 겹치지 않는다면 띄어쓰기를 기준으로 class들을 분리하고 마지막 class만 써주세요.
# 위의 단순한 3가지 형태만 쓸 경우 여러 요소가 선택될 수도 있습니다.
# 예: soup.select('a')는 문서 내의 모든 <a></a> 요소를 찾습니다.
# 이를 좀 더 구체화해서 아래처럼 어떤 경로를 거쳐 요소를 찾아야 되는지 명시할 수 있습니다.
soup.select('상위태그명 > 하위태그명 > 하위태그명')
soup.select('상위태그명.클래스명 > 하위태그명.클래스명')
# 앞의 예에서처럼 여러 <li>를 가질 때 몇 번째 <li> 인지를
# 부모의 몇 번째 자식인지 명시해서 지정할 수도 있습니다.
soup.select('.클래스명:nth-child(자식의순서)')
# 태그와 속성값으로 찾는 방법
soup.select('태그명[속성="값"]')
# 한 개만 가져오고 싶은 경우
soup.select_one('위와 동일')
DB에는 크게 RDBMS(MySQL, OracleDB)와 NoSQL(MongoDB)로 나뉜다.
MongoDB는 다양한 플랫폼에서 사용 가능하며 JSON과 비슷한 형태로 자료를 정리한다.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
brew tap mongodb/brew
brew install mongodb-community
brew services start mongodb-community

이러한 MongoDB에 데이터를 입력하기 위해서는 pymongo라는 라이브러리를 사용해야한다.
shell에서 pip install pymongo를 설치하고, 원하는 프로젝트에 다음 코드를 작성한다.
from pymongo import MongoClient
client = MongoClient('localhost', 27017)
db = client.jungle
DB조작은 다음과 같이한다.
#DB에 instert하는 예시는 다음과 같다.
#users라는 테이블에 다음과 같은 컬럼이 들어간다.
db.users.insert_one({'name':'bobby','age':21})
db.users.insert_one({'name':'kay','age':27})
db.users.insert_one({'name':'john','age':30})
# MongoDB에서 데이터 모두 보기
all_users = list(db.users.find({}))
# 참고) MongoDB에서 특정 조건의 데이터 모두 보기
same_ages = list(db.users.find({'age':21}))
#특정 결과 값 뽑기
user = db.users.find_one({'name':'bobby'})
print(user)
# 그 중 특정 키 값을 빼고 보기
user = db.users.find_one({'name':'bobby'},{'_id':False})
print(user)
#수정하기
# 생김새
db.people.update_many({찾을조건},{ '$set': {어떻게바꿀지}})
# 예시
db.users.update_one({'name':'bobby'},{'$set':{'age':19}})
#수정값 조회
user = db.users.find_one({'name':'bobby'})
print(user)
#삭제하기(잘 안쓴다)
db.users.delete_one({'name':'bobby'})
user = db.users.find_one({'name':'bobby'})
print(user)
사용법을 간단히 나타내면 다음과 같다.
# 저장 - 예시
doc = {'name':'bobby','age':21}
db.users.insert_one(doc)
# 한 개 찾기 - 예시
user = db.users.find_one({'name':'bobby'})
# 여러개 찾기 - 예시 ( _id 값은 제외하고 출력)
same_ages = list(db.users.find({'age':21},{'_id':False}))
# 바꾸기 - 예시
db.users.update_one({'name':'bobby'},{'$set':{'age':19}})
# 지우기 - 예시
db.users.delete_one({'name':'bobby'})
이와 같은 기술을 사용해서 웹 스크래핑 결과를 DB에도 저장할 수 있다.
파이썬으로 쓰인 웹 프레임워크로, 서버를 구동하는 데 필요한 여러 기능들을 제공한다.
가상환경을 설정한 뒤, 비주얼 스튜디오 코드의 인터럽터에서 Flask를 설치한 후 사용한다.
보통 프로젝트 파일명을 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)
Mac은 5000번 포트가 AirPlay로 쓰고 있을 텐데, 설정에서 AirPlay를 비활성화하고 PID를 죽여서 5000번 포트를 사용할 수 있게 할 수 있다. EC2 서버로 올릴때 5000번으로 바꾸는 귀찮음이 있어, 나는 이렇게 사용했다. AirPlay사용하고 싶으면 5000번 포트 확보후 활성화 시키면 자동으로 다른 포트로 잡는다.
※ Flask 프로젝트 파일 실행시: 비주얼 스튜디오 코드의 zsh창에 python app.py를 쳐서 실행한다.

위와 같이 나오면 성공이고 Ctrl + C를 누르면 종료가 된다.
http://localhost:5000/ 에 들어가면 프로젝트 결과를 확인할 수 있다.
다음과 같이 작성해 URL마다 다른 글씨를 띄울 수 있다.
from flask import Flask
app = Flask(__name__)
@app.route('/') //첫번째 http://localhost:5000/페이지
def home():
return 'This is Home!'
@app.route('/mypage') //두번째 http://localhost:5000/mypage 페이지
def mypage():
return 'This is My Page!'
if __name__ == '__main__':
app.run('0.0.0.0',port=5000,debug=True)
Flask의 기본 폴더 구조는 항상 프로젝트 파일안에 static(사진 등), templates(index인 프론트엔드)폴더와 app.py를 생성하여 시작한다.(가상화 폴더인 .venv는 건들지 말 것)
<img src="{{ url_for('static', filename='rome.jpg') }}"/>
와 같이 작성한다. 기존의 Html 작성과 다르다.
Flask에서는 API를 통해 데이터를 주고 받는다.
요청 방식에는 GET, HEAD, PUT, DELETE 등 많지만 우선적으로 GET, POST를 기반으로 설명해보겠다.
GET: 통상적으로 데이터 조회(Read)를 요청할 때
ex) 영화 목록 조회 → 데이터 전달: URL 뒤에 물음표를 붙여 key=value로 전달(google.com?q=북극곰)
POST: 통상적으로 데이터 생성(Create), 변경(Update), 삭제(Delete) 요청 할 때
ex) 회원가입, 회원탈퇴, 비밀번호 수정 → 데이터 전달: 바로 보이지 않는 HTML body에 key:value 형태로 전달
GET, POST 요청에서 클라이언트의 데이터를 받는 방법은 다음과 같다.
#GET 요청 API코드(app.py)
@app.route('/test', methods=['GET'])
def test_get():
title_receive = request.args.get('title_give')
print(title_receive)
return jsonify({'result':'success', 'msg': 'GET 완료'})
#GET 요청 확인 Ajax코드(index.html)
$.ajax({
type: "GET",
url: "/test?title_give=봄날은간다",
data: {},
success: function(response){
console.log(response)
}
})
#POST 요청 API코드(app.py)
@app.route('/test', methods=['POST'])
def test_post():
title_receive = request.form['title_give']
print(title_receive)
return jsonify({'result':'success', 'msg': 'POST 완료'})
#POST 요청 확인 Ajax코드(index.html)
$.ajax({
type: "POST",
url: "/test",
data: { title_give:'봄날은간다' },
success: function(response){
console.log(response)
}
})
이러한 기술들을 사용해 다양한 웹 사이트 구현이 가능하다.
웹 서비스 런칭을 위해 클라이언트 요청을 항상 응답해줄 수 있는 서버에 프로젝트를 실행시켜야한다. AWS의 EC2를 통해 구현해 볼 것이다.
만약, 해당 기술이 없다면 컴퓨터가 항상 켜져있어야할 것이다.
1.AWS EC2서버를 구매하자 https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-2 에 들어가 가입 후 서울로 지역을 바꾸자.
2. 인스턴스 시작을 눌러 이름을 설정하고 퀵스타트를 ubuntu로 바꾸자, AMI는 프리 티어 사용 가능이라고 되어있는 것을 선택해야 과금이 되지 않는다.
3. 인스턴스 유형또한 프리 티어 사용 가능으로 되어 있는걸 고르면 된다.(작성당시 t2.micro)
4. 키페어는 새로 생성하여 저장해두자. 나중에 접속할때 해당 키로 인증해서 들어갈 것이다.
5. 네트워크 설정에서 SSH, HTTP, HTTPS 모두 트래픽 허용을 체크해주자.
6. 스토리지 구성은 최대 30GB라고 되어있으니 30GB로 설정해주자
7. 인스턴스 시작 버튼을 누르면 끝난다.
※ 앞으로 구축할 서버는 1년간 무료이므로 1년이 되기전에 해지해야 과금이 되지 않는다.
이제 Mac 기준, AWS EC2를 터미널을 통해 ssh로 연결해 보겠다.
다음 명령어를 차례로 실행하자(다운받은 키페어 필요)
//키페어 접근 권한을 바꾼다)
sudo chmod 400 받은키페어를끌어다놓기(자동으로 디렉터리가 써진다)
//ssh로 접속한다(띄어쓰기 유의)
ssh -i 받은키페어를끌어다놓기 ubuntu@AWS에적힌 서버IPv4
ex)ssh -i /path/my-key-pair.pem ubuntu@13.125.250.20
접속되면 터미널에서 ubuntu@AWS에적힌 서버IPv4 로 앞에 명령어가 바뀔 것이다. 연결된 터미널창은 닫지말자.
EC2가 리눅스 시스템으로 돌아가므로 리눅스 명령어를 알면 좋다. 명령어는 다음과 같다.
ls: 내 위치의 모든 파일을 보여준다.
pwd: 내 위치(폴더의 경로)를 알려준다.
mkdir: 내 위치 아래에 폴더를 하나 만든다.
cd [갈 곳]: 나를 [갈 곳] 폴더로 이동시킨다.
cd .. : 나를 상위 폴더로 이동시킨다.
cp -r [복사할 것] [붙여넣기 할 것]: 복사 붙여넣기
rm -rf [지울 것]: 지우기
sudo [실행 할 명령어]: 명령어를 관리자 권한으로 실행한다.
sudo su: 관리가 권한으로 들어간다. (나올때는 exit으로 나옴)
명령어로 하나하나 쓰기 귀찮으므로 Filezilla를 통해 EC2에 파일을 올려보겠다.
파일질라를 실행하고 새 접속을 열어
General: SFRP -SSH~
HOST: AWS서버IPv4
Port: 22
Logon Type: Key file
User: ubuntu
Key file: 키페어파일 있는 디렉터리로 설정
OK버튼 클릭
이렇게하면 왼쪽에는 내컴퓨터가 오른쪽에는 접속한 EC2 리눅스 폴더가 뜬다. 원하는 파일을 드래그해 업로드 다운로드 할 수 있다. 원격 파일탐색기라고 생각하면 편하다.
다시 아까 열어둔 터미널에서 파이썬 파일을 실행해보겠다.
# python 이라는 명령어로 3 버전 이상을 실행하도록 하는 명령어입니다.
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 10
# 프로젝트 디렉토리로 이동
cd app.py가 있는 디렉토리(파일질라참고, 홈이면 'cd ~'이다)
# 실행. 콘솔창에 hellow world!가 뜨는 것을 확인 할 수 있습니다.
python hello.py
# pip3 설치
sudo apt-get update
sudo apt-get install -y python3-pip
# 버전 확인
pip3 --version
# pip3 대신 pip 라고 입력하기 위한 명령어
# 아래 명령어를 입력하면 pip 라고 쳐도 pip3를 작동시킬 수 있습니다.
sudo update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1
#pip를 사용해 flask설치
pip install flask
#추후 프로젝트를 위해 다른 패키지로 설치하자.
Flask: python3 -m pip install flask
Requests: pip install requests
Bs4: pip install beautifulsoup4
pymongo: pip install pymongo
#복붙하지 말고 손수치는걸 권장한다.
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)
그리고 파일질라를 통해 home/ubuntu/jungle 폴더에 해당파일을 업로드하자.
터미널에서 cd를 통해 디렉터리를 이동하자(cd /home/ubuntu/jungle)
그리고 python app.py 라고 치면 Flask가 실행된다.
여기서 EC2홈페이지에서 설정해줘야하는게 있는데, 그게바로 보안그룹 설정이다.(5000번 포트를 열어줘야함)
EC2관리 콘솔에서 보안>보안 그룹 항목 클릭> EC2서버 체크 후 인바운드 규칙 편집> HTTP, SSH와 사용자 지정 TCP로 포트범위를 5000번, 27017번을 소스 Anywhere-IPv4로 열어준다. 규칙저장을 눌러 저장한다.
이제 http://[내 EC2 IPv4주소]:5000/ 로 접속하면 작동하는 것을 확인할 수 있다.
각각의 리눅스 버전에 따라 설치방법이 다르다. 이 문서는 Ubuntu 24.04 (Noble) 설치 방법을 다루겠다.
자세한 설치법은 https://www.mongodb.com/ko-kr/docs/manual/tutorial/install-mongodb-on-ubuntu/ 다음 사이트를 참고하자.
SSH 터미널에서 순서대로 명령어를 실행하자.
sudo apt-get install gnupg curl
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg \
--dearmor
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
sudo apt-get update
sudo apt-get install -y mongodb-org
이렇게 하면 설치가 될 것이다. 이제 실행하고 접속 계정을 생성해 보겠다.
sudo service mongod start
#실행이 성공적이면 아무 글도 안나온다.
# MongoDB쉘에 들어가기(접속시 ">"로 뜸)
mongosh
# admin으로 계정 바꾸기
use admin;
# 계정 생성하기(test자리에 본인이 원하는 내용써도 된다)
db.createUser({user: "test", pwd: "test", roles:["root"]});
밑에와 같이 나오면 성공이다.

# mongoDB 쉘에서 나오기
exit
# MongoDB 재시작
sudo systemctl restart mongod
근데, 여기서 문제가 있다. 외부에서 열어줄려면 MongoDB의 설정을 바꿔줘야한다. 해당 과정을 수행하자.
sudo vi /etc/mongod.conf
# sudo: 관리자(SuperUser) 권한으로 다음을 실행
# vi: 리눅스에서 VS Code 대신 사용하는 텍스트에디터인 Vim을 실행
i눌러 보이는 화면을 다음과 같이 편집하자.

# 내용 저장하고 에디터 종료하기. esc 누르고 다음 입력.
:wq
# 재시작
sudo systemctl restart mongod
이렇게 하면 외부에서도 접속이 가능하다.
그러면 DB조작이 편리한 Studio3T를 이용해서, 내 컴퓨터에서 EC2서버에 있는 MongoDB에 원격으로 접속하자.
Connect > New Connection > “Manual configure my connection settings” 선택하고, Next >
Server 탭 > Connection Type: Standalone > Server: AWS의 IPv4입력
Authentication 탭 > Authentication Mode: SCRAM-SHA-1 > user name: test(설정한 이름) > password: test(접속 계정의 비밀번호) > Authentication DB: admin(무조건)
이렇게 설정 후 Save하면 DB 설정은 완료된다.
파일 업로드전에 파이썬의 app.py의 내용 일부분을 다음과 같이 수정해야한다.
from pymongo import MongoClient
# 해당부분 수정
client = MongoClient('mongodb://test:test@localhost',27017)
db = client.dbjuingle
#다음과 같은 의미이다.
client = MongoClient('mongodb://설정한아이디:비밀번호@내AWS아이피',27017)
이후, app.py, templates, static 등 프로젝트 폴더를 파일질라를 통해 EC2 리눅스로 옮겨준다.
파일 실행전에 터미널SSH를 통해 패키지를 설치하자. 전에 했으면 안해도된다.
pip install requests beautifulsoup4 pymongo
# 설치후에 실행한다.
cd /home/프로젝트 업로드 디렉터리
python app.py
실행했으면 접속해보자.
http://내AWS IPv4주소:5000/
포트포워딩
포트포워딩은 기존의 80번 포트로 오는 요청을 5000번 포트로 전달하는 역할을 한다. 기존 URL을 보면 알듯이 :5000으로 끝나기에 포트포워딩을 통해 해당 번호를 없앤다.
또한, 배포시에 IP주소와 포트번호를 그대로 노출시키기엔 적합하지 않다. 그렇기 때문에 포트포워딩과 도메인 설정으로 서버를 완성해보겠다.
리눅스 포트포워딩 방법
해당 내용은 리눅스 24.04 우분투 ARM64버전 기준으로 기술하고 있으니 해당 외의 버전은 인터넷을 찾아보자
24.04는 네트워크 인터페이스가 enX0이다. 그래서 기존의 명령어와는 살짝 다르다. 다음 코드를 순차적으로 실행하자.
※ 포트포워딩전에 실행중인 Flask는 Ctrl + C로 중지
# 먼저 네트워크 관련 툴을 설치해야한다.
sudo apt install net-tools
# 포트포워딩 명령어
sudo iptables -t nat -A PREROUTING -i enX0 -p tcp --dport 80 -j REDIRECT --to-port 5000
# 포트포워딩 상태 확인(항목에 5000번으로 뜨면 성공)
sudo iptables -t nat -L
# 혹여나 명령어를 잘못쳤다면 해당 명령어로 제거하자
sudo iptables -D PREROUTING -t nat -i enX0 -p tcp --dport 80 -j REDIRECT --to-port 5000
이후 python app.py로 다시 시작하고, 웹 브라우저 접속해 실행 확인해보자.
맥의 연결된 SSH 터미널을 종료하면 원격접속이 끊기면서 서버가 종료된다. 그러므로 nohub설정을 하여 백그라운드로 파이썬을 실행시켜 웹서비스를 계속 가동하게끔 만들어야한다.
※ nohub 사용시
nohup: ignoring input and appending output to 'nohup.out'
는 정상출력이다.
# 아래의 명령어로 nohup을 설정한다.
nohup python app.py &
# 서버 종료시 다음과 같이한다.
# 아래 명령어로 미리 pid 값(프로세스 번호)을 본다
ps -ef | grep 'app.py'
# 아래 명령어로 특정 프로세스를 죽인다(위에 나온 PID값)
kill -9 [pid값]
다시 킬땐 맨 위에 nohup을 다시 실행하면 된다.
SSH를 끄고 브라우저에 접속하여 실행중인지 확인해보자.
가비아에서 도메인을 구매하여 연결해보자. 가비아는 네임서버를 운영해주는 업체이다.
회원가입을 하고 원하는 도메인을 구매하자(.shop추천)
1년권으로 500원을 지불하고 구매하면 된다.
마이페이지에서 기다리면 서비스 수가 '1'이 될텐데
서비스 관리 탭 > 관리툴 > 도메인 연결(설정) > 구매한 도메인 체크 후 DNS 설정 클릭 > 타입: A, 호스트: @, IP주소: AWS IPv4주소 입력 후 저장
15분정도 기다리자.
IP주소를 원래주소가 아닌 http://가비아에서 설정한 내도메인/ 으로 접속한다.
접속이 된다면 웹 사이트 만들기 성공이다!
완성된 프로젝트 app.py파일에 localhost를 빼고 다음과 같이 수정
client = MongoClient('mongodb://test:test@15.164.170.41',27017)
SSH 연결 후 다음 명령어 작성
# 다음 명령어로 실행중인 파이썬 프로세스 종료
ps -ef | grep 'app.py’
Kill -9 "pid값"
파일질라를 통해 app.py와 index.html 등 업데이트 파일을 업로드 한다.
cd 프로젝트 디렉토리 이동
#실행 확인 후 종료
python app.py
# SSH종료 후에도 계속 실행
nohup python app.py &
# nohup: ignoring input and appending output to 'nohup.out' 라고 나오면 성공
명령어가 안먹으면 직접 쳐봐야한다.