웹 풀스택(Full-Stack)
웹 애플리케이션을 개발하는 데 필요한 모든 기술과 영역을 포괄하는 개념
1. 프론트엔드 (Front-End) : 사용자 인터페이스(UI)와 사용자 경험(UX)에 관한 부분을 담당
- 프로그래밍 언어 : HTML, CSS, JavaScript 등을 사용하여 웹 페이지를 디자인하고, 이를 구현
- 리액트(React), 앵귤러(Angular), 뷰(View) 등의 프레임워크나 라이브러리를 사용
2. 백엔드 (Back-End) : 프론트엔드에서 요청하는 데이터를 처리하고, 데이터베이스를 다루며, 보안과 같은 기능을 담당 → 서버 사이드 로직(Server-Side Logic)을 구현하는 영역
- 프로그래밍 언어 : 자바(Java), 파이썬(Python), 루비(Ruby)
- 백엔드 프레임워크 : 스프링(Spring), 쟁고(Django), 레일즈(Rails) 등
3. 데브옵스 (DevOps) : 소프트웨어 개발과 배포, 운영에 관련된 모든 프로세스를 관리하는 영역
- 소프트웨어 배포를 자동화, 코드의 통합 & 테스트 & 릴리즈를 자동화, 문제가 생길 때 빠르게 대처할 수 있도록 하는 등의 작업을 담당
- 도커(Docker), 젠킨스(Jenkins), AWS 등의 도구를 사용
MVVM Pattern
소프트웨어 개발에서 사용되는 아키텍처 패턴 중 하나로, 프레젠테이션 레이어를 위한 *디자인패턴
*디자인 패턴 : 프로그램 개발시 자주 나타나는 문제를 해결하기 위한 방법 / 규약을 묶어, 이름을 붙인 것
- Model : 실제 데이터를 처리하는 소스 코드
- View : UI에 해당하는 소스코드
- ViewModel : View를 표현하기 위해 만들어진 코드 / View에서 발생한 이벤트를 받아 Model을 update 또는 Model의 변경사항을 VIew에 반영
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- vue.js에서 vnnm 모델 -> 데이터와 html을 일치화시키는 방식 -->
<script>
const h1 = document.createElement('h1');
document.querySelector('body').append(h1);
const viewModel = {};
let model = "";
Object.defineProperty(viewModel, 'model', {
get(){
return model;
},
set(value){
model = value;
h1.textContent = model;
}
});
</script>
</body>
</html>
Vue.js
- new Vue
- el
- “#app”으로 지정된 div를 Vue 형식으로 만든다.
- data(){}
- Vue Instance에서 변수를 생성할 때 사용하는 객체; 함수 안에 변수를 정의
- el
v-on, @click 사용법
- v-on : 이벤트핸들러 지정 시 사용
- -@ : v-on의 축약형
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- Vue에서 데이터를 나타낼 때 {{ }} 사용 -->
<h1>{{message}}</h1>
<!-- v-on:click 또는 @click -->
<!--
Vue에서 event를 활용하는 경우, "inline 방식"으로 작성
v-on:click="bbq" === @click="bbq"
-->
<button @click="changeText">클릭</button>
</div>
<!-- Vue를 사용하기 위한 script 정의 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.min.js"></script>
<script>
const app = new Vue({
<!-- element 중 id가 app인 것에 대해 적용한다는 의미 -->
el : "#app",
<!-- 데이터 정의 -->
data(){
return{
message: "클릭을 눌러주세요.",
nextMessage: "하하",
}
},
<!-- vue 내부에서 data를 변경하는 경우, 해당 methods에 정의한다. -->
methods:{
<!-- html 파트 외부에서 data나 다른 methods에 접근하는 경우
"this" 를 붙어야 한다. -->
changeText(){
this.message = this.nextMessage;
<!-- 다른 methods를 가져오는 경우도 this. 로 가져온다. -->
this.test();
},
test(){
console.log("check");
}
}
})
</script>
</body>
</html>
데이터 바인딩
- Data 객체 내 변수와, 화면의 데이터를 연동하는 것을 의미
- Vue Instance의 data 객체 멤버 변경 시, 화면에 binding된 변수가 즉시 수정되어 화면 변경
- 단방향 바인딩 : v-bind, {{}};
- 양방향 바인딩 : v-model
v-bind 활용 1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- v-bind:href === :href
표시된 내용은 vue에 정의된 내용이 들어간다. -->
<a v-bind:href="url1">구글</a>
<a :href="url2">네이버</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.min.js"></script>
<script>
const app = new Vue({
el : "#app",
data(){
return{
url1: "https://www.google.com",
url2: "https://www.naver.com"
}
}
})
</script>
v-bind 활용 2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.colorBlue{
color: blue;
}
.colorRed{
color: red;
}
</style>
</head>
<body>
<div id="app">
<h1 v-bind:class="colorOfHi">HI</h1>
<button @click="changeColor">컬러 바꾸기</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: "#app",
data(){
return{
colorOfHi : "colorBlue"
}
},
methods:{
changeColor(){
this.colorOfHi = "colorRed";
}
}
})
</script>
</body>
</html>
v-model : input 값 수정 시, HTML 출력 값도 바뀜
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="message">
<div>{{ message }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: "#app",
data(){
return{
message: "",
}
}
})
</script>
</body>
</html>
v-if
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<p v-if="seen">이제 나를 볼 수 있어요</p>
<button v-on:click="openYourEyes">open your eyes</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: "#app",
data(){
return{
seen: false,
}
},
methods: {
openYourEyes(){
this.seen = true;
}
}
})
</script>
</body>
</html>
v-else, v-else-if와 혼용 가능
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<p v-if="renderA">A가 보입니다</p>
<p v-else-if="renderB">B가 보입니다</p>
<p v-else>둘 다 안보입니다.</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: "#app",
data(){
return{
renderA: true,
renderB: false
}
}
})
</script>
</body>
</html>
v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- v-for=" (변수, index) in lists " v-bind:key="index" -->
<!-- key를 넣는 이유 : Virtual DOM 설정 시 중복방지를 위함 -->
<ul>
<li v-for="(li_, index) in lists" :key="index">
{{ li_ }}
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: "#app",
data(){
return{
// lists.reduce((acc, cur) => (html 태그 ~~~), "") 도 가능
lists: ["밥먹기", "점심먹기", "코딩하기"]
}
}
})
</script>
</body>
</html>
Life cycle
자주 쓰는 Life Cycle
1. 생성 (created) : 화면이 생기기 전 데이터 호출
- 생성되었지만 화면에 적용 x
- 이 시점에 비동기 호출 진행
- 따라서 DOM에 접근 불가능
2. 부착 (mounted) : 화면에 접근해서 데이터 수정
- 화면에 부착된 이후
- DOM에 접근 가능
3. 수정 (updated) : 컴포넌트의 데이터가 변경되어 다시 렌더링될 때 호출
- DOM에 접근 가능
4. 삭제 (destroyed) : Vue 인스턴스가 제거되기 전에 호출
- 컴포넌트가 사용한 자원을 해제
- 이벤트 리스너 제거 등
Created 사용 예시
<!-- 필요한 부분만 보이기 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- {{ todo }} -->
<div>{{ todo.id }}</div>
<div>{{ todo.titl
<div>{{ todo.completed }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.min.js"></script>
<script>
const app = new Vue({
el: "#app",
data(){
return{
todo: {}
}
},
// Lifecycle created <- 내장 함수
// 데이터를 비동기 호출하기 좋은 시점
async created(){
const result = await axios.get("https://jsonplaceholder.typicode.com/todos/1")
console.log(result.data);
//호출이 되었고, 이 데이터를 todo에 넣는다.
this.todo = result.data;
}
})
</script>
</body>
</html>
Mounted 사용 예시
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- vue에서 DOM에 접근할 경우, ref 사용 -->
<input ref="input_ref" type="text">
<p ref="ss">hello</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.8/dist/vue.min.js"></script>
<script>
const app = new Vue({
el : "#app",
created(){
console.log("created");
console.log(this.$refs);
console.log(this.$refs.input_ref);
// -> mounted에서 접근하지 않아 undefined 출력됨
},
// mounted()가 created()의 윗 단에 있어도, created가 먼저 호출된다.
// mounted는 DOM에 접근할 특별한 경우에 사용
// focus가 대표적
mounted(){
console.log("mounted");
console.log(this.$refs);
console.log(this.$refs.input_ref);
this.$refs.input_ref.focus(); // cursor가 input을 가리킴
this.$refs.ss.style.color = "blue";
}
})
</script>
</body>
</html>