Finalize란?

Class의 resource를 자동으로 관리해주기 위한 장치이다. 

비유하자면, c++의 destructor(소멸자)의 역할을 한다. 

ex) file open을 한 후 작업이 끝났을 때, finalize에서 file close 작업을 처리하도록 등록을 한다. 그러면 객체 소멸 시 finalize가 실행 되면서 file close 작업을 진행하게 된다. 

* Finalize의 의의는 resource 소유권을 객체의 수명에 묶어서, 개발자가 아닌 platform/software에 의해 관리되도록 개발하는 것이다. 

 

하지만?

* Java 9에서 deprecated 되었다. 

resource 관리의 안전성을 보장해주는 method가 어째서 deprecated되었을까?

 

Finalize의 단점

Finalize를 override한 객체는 GC(garbage collector)에서 특별하게 처리된다. 

 

할당이 해제된 후 바로 GC에 수집되지 않는다. 해당 객체는 queue에 등록된 후 별도의 종료 thread가 queue에서 pop을 시켜 순차적으로 종료 시킨다. 때문에 finalize가 요청된 시점과는 다른 주기에 소멸 작업이 진행된다.

 

위 과정에서 발생하는 thread의 생성과 실행은 오버헤드를 발생시킨다. 

JVM는 작업의 안전성 보장을 위해 finalize 처리용 thread를 생성하는데, 해당 thread가 finalize 작업을 진행하는 과정 중에 오류가 발생하거나 blocking이 발생 할 수 있다. 

 

resource의 회수 및 객체 소멸에 대한 처리를 하는데 위와 같은 오버헤드의 위험도를 매번 감수할 수는 없다.

때문에 공식적으로도 finalize를 사용하지 않는 방향으로 개발할 것을 추천해왔고, Java 9버전에 와서 deprecated 처리가 된 것이다. 

 

필요하다면?

resource의 회수와 소멸 기능의 구현이 필요할 때 추천되는 구현 방식은 try-catch-finally를 사용한 logic block을 통한 처리 방식이다. 

 

List interface 하위 Class

  1. Vector (deprecated)
    1. Stack
  2. ArrayList
  3. LinkedList

 

주의사항

Stack은 Vector를 상속받은 불필요한 로직만 추가된 클래스이고(책피셜)

Vector는 deprecated 된 삭제 예정 클래스이다.

실제 사용할 수 있는 클래스는 LinkedList와 ArrayList 두 개라고 생각하면 된다.

 

ArrayList

고정 크기의 Array를 기반으로 구현되는 List Class이다.

 

LinkedList

Doubly Linked List(양방향 연결 리스트)로 구현되는 동적 증가가 가능한 List Class이다.

 

ArrayList vs. LinkedList

데이터 접근/수정 패턴에 따라 사용해야 할 Class를 정해야 한다.

  • element add 비용
    • list end node에서의 add
      • ArrayList는 element의 수가 공간의 크기보다 커지면, 새로운 Array 생성을 위한 공간 할당 비용이 추가로 발생한다.
      • LinkedList는 end node에 new node의 reference를 추가하기 때문에, O(1)의 고정 비용만 발생한다.
    • 중간 index에서의 add
      • ArrayList는 해당 index 기준 우측의 element들을 모두 한 칸씩 이동시켜야 한다.
      • LinkedList는 삽입 지점으로의 node 탐색 비용 O(n)이 발생한다. 대신 양쪽 node의 reference를 해제한 후 new element에 재등록하는 O(2)의 비용이 발생한다.

* element 삭제에도 동일한 비용이 발생한다.

 

결론

List의 Random index 조회가 빈번할 경우, 조회 비용 O(1)을 보장하는 ArrayList가 유리하다.

순차 조회 혹은 List element 삭제/추가가 빈번할 경우 LinkedList가 유리하다.

 

확인 필요 사항

LinkedList의 순환을 하면서 element 조회를 할 때

LinkedList의 각 element 조회 비용 O(n)이 필요한지, 아니면 순환 동작을 통한 O(1)로 가능한지는 확인이 필요하다.

 

 

 

 

1. 문제 발생

- 신규 서버 프로젝트의 구조 및 개발 방향 구상 중, DB model object(이하 DTO)와 Service model object(VO)을 따로 구현 및 관리하기로 결정이 되었음

- 기존 운영 프로젝트에선 DTO의 구조가 그대로 Client까지 전달이 되었지만, 신규 구성에선 그런 동작을 방지하기로 결정 

- 하지만 클라이언트로 전달되지 말아야 하는 데이터 이외의 대부분의 값들은 Client에게 전달이 되어야 하는 상황

 

2. 방안 1

- DTO로 받은 각 값들을 일일이 소스 코드에서 변환 처리 해준다

- 개인적으로는 이게 취향

- 성능적으로도 솔직히 이것만큼 예측이 쉽고 문제 원인이 될 것도 없음

- 하지만 Human error의 위험 및 엄청난 귀차니즘, 장기간의 소스 코드 관리의 문제가 발생할 수 있음 

- 나중에 DB table 구조에 수정 및 추가가 생기면 다 수정해야 하는 시간 비용도 두려움

 

3. 방안 2 (진행)

- DTO와 VO간의 자동 변환 기능을 만들자

- 솔직히 아마 검색해보면 분명히 있을거지만, 요즘 개인 개발이 좀 느슨해진김에 해볼까 함

- 개념상으로만 알고 있던 Reflection 코딩 적용하면, 약간의 규칙만 정해주면 가능할 것 같았음

- 결과가 괜찮으면 검토 건의 해보지 뭐 ㅋ

 

4. 구성 및 기초 설계

4-1. 규칙 1

DTO와 VO간의 동일한 타입 및 이름이어야 한다.

"DB에서 int로 쓰고있지만 클라이언트는 String으로 받아서 쓸 것이다"라는 규칙으로 개발을 해봤지만, 좋은 꼴을 본 적이 없다.

4-2. 규칙 2

규칙 1을 기반으로, 각 객체의 field는 Java에서 제안하는 getter/setter 규격을 따라야 한다. 이 네이밍 규칙을 기준으로 데이터 복사 작업을 진행할 것이다. 또한 최근 자바 프로젝트는 다 이 규격을 사용하는 lombok 라이브러리를 통해 관리하기 때문에 이렇게 판단했다. 

 

5. 구현 

더보기
package reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;

public class ConverterUtil{

    public static <T_DTO, T_VO> void convertObject(T_DTO objectDTO, T_VO objectVO) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 1. 공통 method 조회(Object Class method 제외 처리에 사용)
        HashSet<String> objectMethodSet = new HashSet<>();
        {
            Object testObj = new Object();
            Method[] objectMethods = testObj.getClass().getMethods();
            for(int i = 0 ; i < objectMethods.length ; i ++){
                objectMethodSet.add(objectMethods[i].getName());
            }
        }

        // 2. DTO getter method 정리
        HashSet<String> DTO_getterSet = new HashSet<>();
        {
            Method[] methods = objectDTO.getClass().getMethods();
            for(int i = 0 ; i < methods.length ; i ++){
                if(!objectMethodSet.contains(methods[i].getName())){
                    if(methods[i].getName().substring(0,3).equals("get")){
                        DTO_getterSet.add(methods[i].getName());
                    }
                }
            }
        }


        {
            // 3. VO setter method 
            HashMap<String, String> VO_getter_Map = new HashMap<>();
            HashMap<String, String> VO_setter_Map = new HashMap<>();

            Method[] methods = objectVO.getClass().getMethods();
            for (int i = 0; i < methods.length; i++) {
                if (!objectMethodSet.contains(methods[i].getName())) {
                    if (methods[i].getName().substring(0, 3).equals("get")) {
                        VO_getter_Map.put(methods[i].getName().substring(3, methods[i].getName().length()), methods[i].getName());
                    }
                    if (methods[i].getName().substring(0, 3).equals("set")) {
                        VO_setter_Map.put(methods[i].getName().substring(3, methods[i].getName().length()), methods[i].getName());
                    }
                }
            }

            // 4. 복사 작업 진행
            Iterator<String> getterKeyItr = DTO_getterSet.iterator();
            while (getterKeyItr.hasNext()) {

                String getKey = getterKeyItr.next();
                String fieldName = getKey.substring(3, getKey.length());
                if (VO_getter_Map.containsKey(fieldName)) {

                    Method testVOGetMethod = objectVO.getClass().getMethod(getKey);

                    Class dtoClass = objectDTO.getClass().getMethod(getKey).invoke(objectDTO).getClass();
                    Class objToPriClass = null;
                    if (dtoClass == Integer.class) {
                        objToPriClass = int.class;
                    } else if (dtoClass == Double.class) {
                        objToPriClass = double.class;
                    } else if (dtoClass == Float.class) {
                        objToPriClass = float.class;
                    } else if (dtoClass == Character.class) {
                        objToPriClass = char.class;
                    } else if (dtoClass == Long.class) {
                        objToPriClass = long.class;
                    } else if (dtoClass == Byte.class) {
                        objToPriClass = byte.class;
                    } else if (dtoClass == Boolean.class) {
                        objToPriClass = boolean.class;
                    } else if (dtoClass == Short.class) {
                        objToPriClass = short.class;
                    } else {
                        objToPriClass = objectDTO.getClass().getMethod(getKey).invoke(objectDTO).getClass();
                    }

                    Method testVOSetMethod = objectVO.getClass().getMethod(VO_setter_Map.get(fieldName), objToPriClass);

                    testVOSetMethod.setAccessible(true);

                    testVOSetMethod.invoke(
                            objectVO,
                            objectDTO.getClass().getMethod(getKey).invoke(objectDTO)
                    );

                }
            }
        }
    }
}

6. 테스트 진행

test.zip
0.01MB

프로젝트의 testMain.java 실행하면 된다. 

jdk 1.8 기준으로 작성했다.

그냥 객체 두 개 두고 복사되는지만 봤다. 안보는게 낫다 

 

7. 결론 및 후기 

어차피 공부 겸 재미용으로 만든 코드이기 때문에 테스트를 여러가지 케이스에서 막 굴리지는 않았다. 

무조건 이름이 같은 경우에만 복사하고 아님 말고의 방식으로 개발되어, 규칙을 지켜주며 객체 생성을 하지 않을거라면 못쓰는 코드에 가깝다. 

무엇보다 이거 괜찮은거 맞나? 싶다. 모든 서버 API 반환부에서 저 함수가 실행된다고 생각하면, 매번 method를 순회하고 타입 비교를 해가면서 변환 시켜준다는 것이 cpu 성능을 필요 이상으로 사용하는 건 아닌가 하는 걱정이 든다. 솔직히 개발 중간에 이럴거면 뭐하러 만드나 하는 생각까지 했지만, 그래 어차피 연습용이니까 하고 진행했다. 

까놓고 옛날에 xml 설정으로 각 객체간 mapping 등록을 해서 복사해주는 방식도 본적이 있긴한데 걔나 얘나 다 별로같다. 

 

* 귀찮아서 그냥 진행하긴 했는데 여기서 말하는 DTO가 Entity 객체고, VO가 DTO다. 시작할 때 네이밍을 잘못 정했다. 

* 빡치게 진짜 있네 

https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application

근데 이 라이브러리도 내부를 까본건 아니지만 parameter가 객체와 class type을 받아가는 것 보면, 결국 방향성은 내 코드와 비슷해보인다. 물론 예외처리나 최적화는 더 잘했겠지만!

Vue.js 개인 프로젝트 진행 중, 이전에 v-bind의 true-value, false-value 속성을 사용한 분기만 있는 것이 별로 도움이 되지 않아 다른 방법을 작성한다. 

 

이전 작성글 (v-bind 바인딩)

https://chainbell.tistory.com/entry/Vuejs-6-v-model%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-%EC%9E%85%EB%A0%A5-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B0%94%EC%9D%B8%EB%94%A9?category=784113

 

[Vue.js] 6. v-model과 v-bind를 사용한 데이터 바인딩

1. v-model 모델 바인딩 v-model 지시자는 주로 값을 입력하고, 그 값을 활용할 때 사용된다. 위 코드는 HTML input tag와 vue instance의 data를 맵핑 시켜놓은 것이다. 데이터 모델 numberModel, textModel을..

chainbell.tistory.com

 

* 작성 코드가 이전 글과 다르게 vue 파일로 되어있다. 

 

1. 목표 

기능 구현 목표는 [로그인 페이지에서 아이디/비밀번호가 미기재 상태일 때, 입력을 유도하기 위한 표시]를 하는 것이다. 

새로운 글자를 출력할 필요 없이, input type text의 테두리에 빨간 테두리를 표시만 해줄 것이다. 

 

class 분기가 될 페이지

2. 템플릿 

v-bind를 통한 class 분기가 적용될 템플릿

input_box와 input_box_invalid는 vue 파일 하단에 기재된 css class 명이다. 

 

3. Vue instance 

class 분기를 판단할 data property

아이디/패스워드 각 입력칸이 별도로 움직일 것이기 때문에, 그를 위한 변수를 하나씩 생성해준다. 

class_id_input_box는 아이디, class_pw_input_box는 비밀번호에 적용시킬 것이다. 

 

위 함수는 로그인 버튼 클릭 시 호출되는 함수이다. (로그인 버튼 관련 내용은 언급하지는 않았다.)

간단하게 각 입력값이 빈 문자열이라면, 각 data 인자를 false로 바꿔 템플릿에서 다른 css가 적용된 class를 받아가도록 되어있다. 

 

4. 결과

미입력 후 로그인 실행 시, 이렇게 빨간색으로 테두리가 생긴다. 

1. v-for 반복문 바인딩

v-for 지시자는 list, map과 같은 다수의 데이터를 포함한 객체형 변수를 반복하여 출력할 때 사용된다. 

Template 코드
Javascript 코드

먼저 상단의 Template을 보면,

(1) 상수값 5에 따라 인덱스를 출력하는 반복문

(2) list형 변수의 값을 전체 출력하는 반복문

(3) map형 변수의 key, value를 받아 동시에 출력하는 반복문 

총 세 종류를 확인할 수 있다. 

 

최초 페이지 출력 상태를 보자. 

최초 페이지 로드 시 화면

 

(1) 상수값 5에 따라 인덱스를 출력하는 반복문

보통 개발 언어의 인덱스는 0 base(zero base) indexing에 따라 0부터 시작하기 마련이지만, v-for을 이용한 출력에서는 1 base 방식인 것을 확인할 수 있다. 

 

(2) list형 변수의 값을 전체 출력하는 반복문

list의 경우, 처음에는 값이 비워져 있어 버튼만 출력된 것을 볼 수 있다.

여기서 버튼 이벤트를 실행해보자.

( * 실행 순서는 push, push, pop, push, pop 이다. [push : 1 된 숫자 추가, pop : 목록의 마지막 숫자를 제외] )

 

push, push, pop, push, pop 순서로 실행된 출력 상태

화살표 순서를 따라 보면, list 변수값에 따라 양방향 바인딩을 통해 목록이 동적으로 변하는 것을 확인할 수 있다.

 

(3) map형 변수의 key, value를 받아 동시에 출력하는 반복문

map형 변수의 경우, 예시 데이터를 보면 순서가 고의적으로 바뀌어 있는 것을 알 수 있다.

key 4가 두 번째 위치에 있는 상태로 반복 출력을 실행한 상태이다. 결과를 보면 알 수 있듯이, 값의 입력 순서를 기준으로 출력되고 있다. 

v-for.html
0.00MB

1. v-model 모델 바인딩

v-model 지시자는 주로 값을 입력하고, 그 값을 활용할 때 사용된다. 

 

위 코드는 HTML input tag와 vue instance의 data를 맵핑 시켜놓은 것이다. 

데이터 모델 numberModel, textModel을 입력받고 바로 아래에 출력하도록 하였다. 

vue의 양방향 데이터 바인딩 정책에 따라 입력과 동시에 하단에 출력이 이루어질 것이다. 

[ input element 입력 -> vue instance data 업데이트 -> HTML 값 출력 element 반영 ]

최초 실행 시 화면

위 상태에서 input에 입력을 하면 

input 입력 시 출력

이렇게 바로 적용이 된다. 

 

2. v-bind 속성 바인딩

v-bind 지시자는 HTML element의 속성에 바인딩 할 때 사용한다. 

v-bind checkbox 활용 예제

 

input type checkbox의 경우, 체크가 되어있는지 여부에 따라 값을 결정하게 된다. 이럴 때 v-bind 하위 속성인 true-value와 false-value를 사용하여 값을 지정한다. 

v-bind checkbox 최초 실행 시 

HTML 파일을 호출하면, 위와 같이 기본값으로 출력된 상태로 출력된다.

이 상태에서 체크박스를 체크하게 되면 

체크박스 선택 후 

이렇게 model에 bind된 값이 입력되며 출력까지 수정되는 것을 볼 수 있다. 

 

checkbox 이외에도 img tag에서 v-bind:src로 이미지 파일을, v-bind:class로 HTML class를, v-bind:value로 HTML element의 지정값을 바인딩 시킬 수 있다.

1. v-show & Computed

v-show 지시자는 HTML 요소를 조건부로 출력하고 싶을 때 사용한다. 일단 예시 코드를 보자

일단 v-show와 computed가 새롭게 추가되었다. 

(1) v-show 지시자는 받는 결과값이 true일 때, 출력을 하게 된다. 

(2) Vue instance내에 포함된 computed는 data의 값이 바뀌면 수정된 것을 감지하여 실행되는 함수를 가진다. 앞서 나왔던 filter와 비슷한 역할을 하지만, 더 동적으로 데이터를 처리할 수 있게 해준다. 

 

위 코드에서 showComputed는 clickConfig의 값이 변경되면, 변경사항을 감지하여 결과값을 반환하게 된다. 

실행 순서는

[버튼 이벤트 실행 -> clickMethod 함수 실행 -> clickConfig 값 수정 -> computed 감지 -> showComputed 실행 -> v-show 지시자가 결과를 받음 -> 화면 출력]

이다.

화면 첫 로딩 시, default true로 되어있기 때문에 출력되는 것을 알 수 있다. 이 상태에서 "클릭 이벤트 버튼"을 누르게 되면, 

이렇게 "보여주겠습니다!" 문구가 출력되지 않게 된다. 

 

(참고 1) v-show는 보여줄지 말지를 선택하는 지시자다. 기본 원리는 display: none을 해주는 것으로 데이터 자체는 잔류하게 된다. 보안상이나 임의 조작을 막아야 하는 경우에 사용하는 것은 바람직하지 못하다. 

2. v-if & v-else

v-show와 다르게 HTML element 자체를 제거시키는 방법이 필요할 때는 v-if를 사용하면 된다. 

실행 순서와 구현 내용은 v-show와 동일하다. 다른 점이 있다면, v-show가 있던 자리에 v-if와 v-else가 있다는 점이다. 

v-if 역시 받는 결과가 true일 때 실행된다.

처음 실행 되었을 때, 두 버튼이 모두 활성화 되어있는 것을 볼 수 있다. 여기서 "클릭 이벤트 버튼"을 클릭하면

이렇게 클릭이 비활성화된 버튼으로 바뀌게 된다. 

v-if.html
0.00MB
v-show.html
0.00MB

 

v-on 지시자는 UI에서 사용할 event와 실행할 Vue instance내의 mehtod를 등록한다.

예시 코드를 보면, HTML 구간에 v-on:click="clickMethod" 라고 작성되어있다. 읽는 그대로 click이벤트가 발생을 하면, instanceElement라는 이름의 Vue instance내에 구현된 clickMethod를 호출하겠다는 의미이다.

위 예시는 

[button 클릭 -> 클릭 이벤트 실행 -> clickMethod 함수 실행 -> Vue instance내 data "clickConfig"값이 수정] 

순서로 실행된다.

최초 페이지 실행 시에는 

버튼 하나와 default 값 true로 된 clickConfig가 출력되고 있다. 그리고 버튼을 클릭하게 되면 

clickMethod 함수가 실행되면서 clickConfig의 값이 false로 수정되고, 화면 출력값도 바뀌는 것을 알 수 있다. 

 

(참고 1) 위 예시 코드에서 값을 출력할 때, v-text나 v-html과 같은 출력용 지시자를 사용하지 않았다. 위 방법은 Vue instnace내 data 값을 그대로 출력시키는 방식으로 {{data-key}} 과 같은 방식으로 출력한다.

 

(참고 2) data의 값이 수정되는 과정은 소스 코드의 동작 상에 있지만, 수정된 값을 HTML에 update하는 과정은 없었다. 이것은 Vue.js의 데이터 관리에 대한 기본 철학이 데이터 양방향 바인딩을 따르고 있기 때문이다. 순수 Javascript로 개발하거나 Jquery로 개발할 때는 단방향 바인딩으로, 데이터의 수정과 HTML로의 수정을 별도로 개발하는 것과 다르게 data의 수정을 통해 바로 수정되도록 하는 것이 Vue.js가 가지는 프레임워크로서의 차별점이다. 

 

1. 지시자 및 인스턴스 객체 설명 

(1) v-text

    - Vue 인스턴스 data의 값을 text로 출력한다. data 값이 html tag를 포함하고 있다면, tag 역시 text로 그대로 출력한다.

(2) v-html

    - Vue 인스턴스 data의 값을 출력하는데, 값에 html tag가 포함되어 있다면 tag를 인식하여 출력된다. 

(3) filter

    - data의 값을 입력 파라미터로 사용하여, filter로 등록한 함수의 결과값을 반환한다.

 

2. 예시 소스 코드 

예시 소스 코드 
소스 코드 출력
simple-data-using.html
0.00MB

예시 코드에서 신경 써서 볼만한 것은 v-html과 filter 정도이다. 

data에 sample이라는 객체 아래 선언된 tagData는 <h1> 헤더 태그를 포함한 텍스트 값이다. tagData가 v-html로 출력되면 출력 결과를 보면 헤더 효과가 적용된 것과 그 밑에 v-text로 호출된 것은 <h1> 태그를 텍스트 그대로 출력하는 것을 볼 수 있다. 

filter의 경우, filters 아래 numberCheck 라는 콜백 함수가 선언되어 있고, {{ 데이터 변수 | filter 함수 }} 로 호출되어 해당 함수의 반환값이 출력되는 것을 알 수 있다. 예시에서는 함수 입력 파라미터가 int값인지 아닌지를 구별하여 문자열을 반환하고, 출력값에서 동작하는 것을 확인할 수 있다.

1. Vue instance

Vue는 Javacript 객체 인스턴스와 HTML 요소(element)가 맵핑되어 동작하게 된다. 

맵핑된 HTML element와 Vue instance

위 코드는 

HTML에서 id가 instnaceElement인 요소를 생성하고 

Javacript에서 Vue instance를 선언한 후 el(element)가 '#instanceElement'인 요소를 보도록 등록한 것이다.

 

2. Vue instance 굴러가는 걸 보자

굴러가는 것을 보기 위해

HTML 요소에 Vue에서 제공하는 v-text 지시자를 사용해 name value를 받아오고

Javascript의 Vue instance에 data 프로퍼티를 구성한다. 

 

* Vue instance에서 HTML과 Javascript에서 사용할 데이터를 data 프로퍼티에 구성한다. 

위와 같이 작성하면, 

이렇게 출력된다. 

 

 

 

3. 생명주기(LifeCycle)

간단한 출력문을 봤으니 생명주기를 확인해보자

생명 주기

Vue Instance는 각각 별도로 4단계의 생명 주기를 갖는다. 

   (1) 인스턴스 생성  

           - 인스턴스가 생성된다. 데이터 관찰자와 사용할 이벤트를 생성하고 초기화한다.

   (2) 템플릿 & 가상 DOM 생성

           - 렌더링 함수를 통해 템플릿을 컴파일한다. 그리고 가상 DOM을 만들고 결과를 HTML DOM에 마운트(mount) 한다.

   (3) 이벤트 루프

           - view-model의 Data를 감시(monitoring)한다. 값에 변화가 있을 때 다시 랜더링한다.

   (4) 인스턴스 소멸

           - 앱 소멸이 시작되면, 모든 관찰자/리스너/자식 컴포넌트들이 삭제된다. 

 

* 각 생명 주기 단계 별 간단한 설명을 작성했지만, 당장 이해하기에는 나오지 않은 기능 및 요소들이 있다. 개발에 있어서 가장 중요한 생명 주기인 만큼 지속적으로 보면서 나오는 내용들과 함께 겹쳐 봐야 할 것 같다. 

 

3. LifeCycle Hook

만약 안드로이드 개발을 한 적이 있다면, onCreate나 onResume과 같은 각 생명 주기를 감지해서 특정 시점에 원하는 함수를 실행하는 개발에 익숙할 것이다. 

Vue 역시 생명주기를 기반으로 개발을 할 수 있고, 그것을 도와주는 것이 Hook이다. 

생명주기 4단계에 따라 [create, mount, update, destroy]가 있고 각 주기별 [전/후]로 나누어 총 8개의 Hook이 있다. 

- 인스턴스 생성 : beforeCreate, created

- 템플릿 & 가상 DOM 생성 : beforeMount, mounted

- 이벤트 루프 : beforeUpdate, updated

- 인스턴스 소멸 : beforeDestroy, destroyed

 

* 코드가 길어져서 파일로 넣습니다. 

vue_instance.html
0.00MB

개발자 도구를 키고 해당 페이지를 호출하면, beforeCreate, created, beforeMount, mounted

네 개의 Hook이 호출되어 로그가 남는 것을 알 수 있다. 

* update와 destroy의 경우, 위 코드 중에서 데이터의 수정 및 인스턴스 소멸이 발생하지 않아서 호출이 안된 것이다. 

* 개발자 도구에서 생명 주기를 강제 호출할 수도 있지만, 당장 필요한 내용도 아니니 지나가겠다. 

 

 

+ Recent posts