SPA 중심에는 대표적인 라이브러리/프론트프레임워크 React, Vue/Angular가 있다.
SPA란?
SPA란 Single Page Application의 약자이다.
단일 페이지 어플리케이션(SPA)는 현재 웹개발의 트랜드이다.
기존 웹 서비스는 요청시마다 서버로부터 리소스들과 데이터를 해석하고 화면에 렌더링하는 방식이다. SPA형태는 브라우저에 최초에 한번 페이지 전체를 로드하고, 이후부터는 특정 부분만 Ajax를 통해 데이터를 바인딩하는 방식이다.
전통적인 페이지 vs 단일 페이지 어플리케이션 비교
예전부터 개발자들은 지속적으로 웹서비스와 개발방식을 발전시켜왔다. CSS, JS 리소스 등을 cdn형태로 캐싱 및 압축하고, View에서 템플릿엔진 들을 사용하고, 초기의 SPA 개념인 Backbone.js, Angular.js 라이브러리들이 나왔고, 지금은 템플릿 개념을 지나 컴포넌트 개념인 React.js, Vue.js, Angular2 등 이렇게 다양한 라이브러리와 프레임워크가 등장했고 아직도 자바스크립트는 발전해가고 있다.
컴포넌트 개념
SPA 구현을 쉽게 말하면 jsp파일 없이 index.html파일 하나에서 js, css등 리소스 파일들과 모듈들을 로드해서 페이지 이동 없이 특정영역만 새로 모듈을 호출하고 데이터를 바인딩하는 개념이다.
물론 이와 같이 개발하기 위해서는 위해서는 ES6, Node.js와 npm 그리고 webpack, Babel 같은 번들러 등 개념을 한번 정도는 잡고 접근해야 할게 많다.
예제 [axios]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
function fn_list(){
//emp_list.ajax
axios.post('/emp_list.ajax', {
}).then(function (resp) {
console.log(resp.data.list);
var list = resp.data.list;
var txt ="";
for(var i=0; i<list.length; i++){
var vo = list[i];
var e_id = vo.e_id;
var e_name = vo.e_name;
var gen = vo.gen;
var addr = vo.addr;
txt +=`
<tr>
<td><a href="javascript:fn_one('${e_id}')">${e_id}</a></td>
<td>${e_name}</td>
<td>${gen}</td>
<td>${addr}</td>
</tr>
`;
}
//console.log(txt);
document.querySelector("#my_tbody").innerHTML = txt;
})
}
function fn_one(e_id){
axios.post('/emp_one.ajax', {
e_id : e_id
}).then(function (resp) {
var vo = resp.data.vo;
document.querySelector("#e_id").value = vo.e_id;
document.querySelector("#e_name").value = vo.e_name;
document.querySelector("#gen").value = vo.gen;
document.querySelector("#addr").value = vo.addr;
console.log(resp.data.vo);
})
}
function fn_add(){
//emp_add.ajax
axios.post('/emp_add.ajax', {
e_id : document.querySelector("#e_id").value,
e_name : document.querySelector("#e_name").value,
gen : document.querySelector("#gen").value,
addr : document.querySelector("#addr").value
}).then(function (resp) {
var cnt = resp.data.cnt;
if(cnt ==1){
alert("정상적으로 추가되었습니다.");
fn_list();
document.querySelector("#e_id").value="",
document.querySelector("#e_name").value="",
document.querySelector("#gen").value="",
document.querySelector("#addr").value=""
}else {
alert("추가 도중 문제가 발생했습니다.")
}
//console.log(resp);
})
}
function fn_mod(){
//emp_mod.ajax
axios.post('/emp_mod.ajax', {
e_id : document.querySelector("#e_id").value,
e_name : document.querySelector("#e_name").value,
gen : document.querySelector("#gen").value,
addr : document.querySelector("#addr").value
}).then(function (resp) {
var cnt = resp.data.cnt;
if(cnt ==1){
alert("정상적으로 수정되었습니다.");
fn_list();
document.querySelector("#e_id").value="",
document.querySelector("#e_name").value="",
document.querySelector("#gen").value="",
document.querySelector("#addr").value=""
}else {
alert("수정 도중 문제가 발생했습니다.")
}
//console.log(resp);
})
}
function fn_del(){
//emp_del.ajax
var flag = confirm("한번 지워진 데이터는 복구 불가. 그래도 지우실겁니까?")
if(!flag) {
return;
}
axios.post('/emp_del.ajax', {
e_id : document.querySelector("#e_id").value
}).then(function (resp) {
var cnt = resp.data.cnt;
if(cnt !=0){
alert("정상적으로 삭제되었습니다.");
fn_list();
document.querySelector("#e_id").value="",
document.querySelector("#e_name").value="",
document.querySelector("#gen").value="",
document.querySelector("#addr").value=""
}else {
alert("삭제 도중 문제가 발생했습니다.")
}
//console.log(resp);
})
}
</script>
</head>
<body onload="fn_list()">
<table border="1">
<thead>
<tr>
<td>사번</td>
<td>이름</td>
<td>성별</td>
<td>주소</td>
</tr>
</thead>
<tbody id="my_tbody">
<tr>
<td colspan="4">
검색된 데이터가 없습니다.
</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<td>사번</td>
<td>
<input type="text" id="e_id">
</td>
</tr>
<tr>
<td>이름</td>
<td>
<input type="text" id="e_name">
</td>
</tr>
<tr>
<td>성별</td>
<td>
<input type="text" id="gen">
</td>
</tr>
<tr>
<td>주소</td>
<td>
<input type="text" id="addr">
</td>
</tr>
<tr>
<td colspan="2">
<input type="button" value="추가" onclick="fn_add()"/>
<input type="button" value="수정" onclick="fn_mod()"/>
<input type="button" value="삭제" onclick="fn_del()"/>
</td>
</tr>
</tbody>
</table>
</body>
</html>
from flask import Flask, jsonify,redirect, json
from flask.globals import request
from flask.templating import render_template
from day09.daoemp import DaoEmp
app = Flask(__name__)
@app.route("/")
def main():
return redirect("/static/emp.html")
@app.route("/emp_list.ajax",methods=['POST'])
def ajax_emp_list():
de = DaoEmp()
list = de.selectList()
return jsonify({'list':list})
@app.route("/emp_one.ajax",methods=['POST'])
def ajax_emp_one():
param = json.loads(request.data)
e_id=param['e_id']
de = DaoEmp()
vo= de.selectOne(e_id)
return jsonify({'vo':vo})
@app.route("/emp_add.ajax",methods=['POST'])
def ajax_emp_add():
param = json.loads(request.data)
e_id = param['e_id']
e_name = param['e_name']
gen = param['gen']
addr = param['addr']
de = DaoEmp()
cnt = de.insert(e_id, e_name, gen, addr)
return jsonify({'cnt':cnt})
@app.route("/emp_mod.ajax",methods=['POST'])
def ajax_emp_mode():
param = json.loads(request.data)
e_id = param['e_id']
e_name = param['e_name']
gen = param['gen']
addr = param['addr']
de = DaoEmp()
cnt = de.update(e_id, e_name, gen, addr)
return jsonify({'cnt':cnt})
@app.route("/emp_del.ajax",methods=['POST'])
def ajax_emp_del():
param = json.loads(request.data)
e_id = param['e_id']
de = DaoEmp()
cnt= de.delete(e_id)
return jsonify({'cnt':cnt})
if __name__ == "__main__":
app.run(host="0.0.0.0",debug=True, port=80)
예제 [ajax]
from flask import Flask,jsonify,redirect,json
from flask.globals import request
from flask.templating import render_template
from day13.daoemp import DaoEmp
app = Flask(__name__)
@app.route("/")
def main():
return redirect("/static/emp.html")
@app.route('/emp_list.ajax', methods=['POST'])
def ajax_emp_list():
de = DaoEmp()
list = de.selectList()
return jsonify({'list':list})
@app.route('/emp_one.ajax', methods=['POST'])
def ajax_emp_one():
e_id = request.form['e_id']
de = DaoEmp()
vo= de.selectOne(e_id)
return jsonify({'vo':vo})
@app.route('/emp_add.ajax', methods=['POST'])
def ajax_emp_add():
e_id =request.form['e_id']
e_name =request.form['e_name']
gen =request.form['gen']
addr =request.form['addr']
de = DaoEmp()
cnt = de.insert(e_id, e_name, gen, addr)
return jsonify({'cnt':cnt})
@app.route('/emp_mod.ajax', methods=['POST'])
def ajax_emp_mod():
e_id =request.form['e_id']
e_name =request.form['e_name']
gen =request.form['gen']
addr =request.form['addr']
de = DaoEmp()
cnt = de.update(e_id, e_name, gen, addr)
return jsonify({'cnt':cnt})
@app.route('/emp_del.ajax', methods=['POST'])
def ajax_emp_del():
e_id =request.form['e_id']
de = DaoEmp()
cnt = de.delete(e_id)
return jsonify({'cnt':cnt})
if __name__ == "__main__":
app.run(host="0.0.0.0",debug=True, port=80)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="jquery-3.7.1.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="text/javascript">
function fn_list(){
//emp_list.ajax
$.ajax({
type: "POST",
url: "/emp_list.ajax",
success: function(res){
//console.log(resp.data.list);
var list = res.list;
var txt ="";
for(var i=0; i<list.length; i++){
var vo = list[i];
var e_id = vo.e_id;
var e_name = vo.e_name;
var gen = vo.gen;
var addr = vo.addr;
txt +=`
<tr>
<td><a href="javascript:fn_one('${e_id}')">${e_id}</a></td>
<td>${e_name}</td>
<td>${gen}</td>
<td>${addr}</td>
</tr>
`;
}
$("#my_tbody").html(txt);
}
})
}
function fn_one(e_id){
//emp_one.ajax
$.ajax({
type: "POST",
url: "/emp_one.ajax",
data : {'e_id':e_id},
success: function(res){
//console.log(resp.data.list);
var vo = res.vo;
$("#e_id").val(vo.e_id)
$("#e_name").val(vo.e_name)
$("#gen").val(vo.gen)
$("#addr").val(vo.addr)
}
})
}
function fn_add(){
//emp_add.ajax
$.ajax({
type: "POST",
url: "/emp_add.ajax",
data : {e_id : $("#e_id").val(),
e_name : $("#e_name").val(),
gen : $("#gen").val(),
addr : $("#addr").val()
},
success: function(res){
//console.log(resp.data.list);
var cnt = res.cnt;
if(cnt ==1){
alert("정상적으로 추가되었습니다.");
fn_list();
$("#e_id").val("")
$("#e_name").val("")
$("#gen").val("")
$("#addr").val("")
}else {
alert("추가 도중 문제가 발생했습니다.")
}
}
})
}
function fn_mod(){
//emp_mod.ajax
$.ajax({
type: "POST",
url: "/emp_mod.ajax",
data : {e_id : $("#e_id").val(),
e_name : $("#e_name").val(),
gen : $("#gen").val(),
addr : $("#addr").val()
},
success: function(res){
//console.log(resp.data.list);
var cnt = res.cnt;
if(cnt ==1){
alert("정상적으로 수정되었습니다.");
fn_list();
$("#e_id").val("")
$("#e_name").val("")
$("#gen").val("")
$("#addr").val("")
}else {
alert("수정 도중 문제가 발생했습니다.")
}
}
})
}
function fn_del(){
//emp_del.ajax
$.ajax({
type: "POST",
url: "/emp_del.ajax",
data : {e_id : $("#e_id").val(),
},
success: function(res){
//console.log(resp.data.list);
var cnt = res.cnt;
if(cnt ==1){
alert("정상적으로 삭제되었습니다.");
fn_list();
$("#e_id").val("")
$("#e_name").val("")
$("#gen").val("")
$("#addr").val("")
}else {
alert("삭제 도중 문제가 발생했습니다.")
}
}
})
}
</script>
</head>
<body onload="fn_list()">
<table border="1">
<thead>
<tr>
<td>사번</td>
<td>이름</td>
<td>성별</td>
<td>주소</td>
</tr>
</thead>
<tbody id="my_tbody">
<tr>
<td colspan="4">
검색된 데이터가 없습니다.
</td>
</tr>
</tbody>
</table>
<table border="1">
<tbody>
<tr>
<td>사번</td>
<td>
<input type="text" id="e_id">
</td>
</tr>
<tr>
<td>이름</td>
<td>
<input type="text" id="e_name">
</td>
</tr>
<tr>
<td>성별</td>
<td>
<input type="text" id="gen">
</td>
</tr>
<tr>
<td>주소</td>
<td>
<input type="text" id="addr">
</td>
</tr>
<tr>
<td colspan="2">
<input type="button" value="추가" onclick="fn_add()"/>
<input type="button" value="수정" onclick="fn_mod()"/>
<input type="button" value="삭제" onclick="fn_del()"/>
</td>
</tr>
</tbody>
</table>
</body>
</html>
'파이썬 > 수업내용' 카테고리의 다른 글
[Python] Vue.js (0) | 2024.07.15 |
---|---|
[Python] Node.js / intellij 설치 다운로드 및 설치하기 (0) | 2024.07.11 |
[ Python] Flask - Ajax / Fetch / axios (0) | 2024.07.09 |
[Python] jquery (0) | 2024.07.09 |
[Python] web외 연동하여 로또 생성하기 / 구구단 / 가위바위보 / 전회번호 출력하기 / 야구게임 (0) | 2024.07.08 |