IT_Study/Web

Web Framework (1) : Full-Stack, MVVM Pattern, Vue.js syntax, Life Cycle

__Vivacé__ 2023. 3. 17. 07:45

웹 풀스택(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>

 

viewModel.model의 값을 바꿀 때마다, 웹에 나타나는 단어가 변하는 것을 알 수 있음

 


Vue.js

 

  • new Vue
    • el
      • “#app”으로 지정된 div를 Vue 형식으로 만든다.
    • data(){}
      • Vue Instance에서 변수를 생성할 때 사용하는 객체; 함수 안에 변수를 정의

 

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

 

Do it! vue js 입문

 

자주 쓰는 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>