https://github.com/HongJungKim-dev/hobby-hive
배포주소
https://hobby-hive-eight.vercel.app/
Hobby Hive - 취미 공유 커뮤니티
취미 이미지 공유 나만의 취미 활동을 이미지로 기록하고 다른 사람들과 공유해보세요. 당신의 취미 활동을 사진으로 기록하고, 다른 사람들과 함께 나눠보세요. 취미 커뮤니티에서 새로운 아
hobby-hive-eight.vercel.app
위의 프로젝트는 Next, React환경에서 만든 프로젝트이고 아래 레포에서 vue로 진행중이지만 vue로 구현한 레포는 아직 배포 및 퍼블리싱이 미비되어서 프로젝트 내용은 상단 코드와 배포주소에서 확인 가능합니다.
https://github.com/HongJungKim-dev/hobby-hive-vue
렌더링 매커니즘 - Vue3를 React와 비교하면서
- 렌더링 파이프라인
템플릿 → 컴파일 → 렌더 함수 → 가상 DOM 트리 → 패치 → 실제 DOM
템플릿: HTML 템플릿을 사용해 UI를 정의
컴파일: 이 템플릿이 렌더 함수로 변환. 렌더 함수는 가상 DOM 트리를 생성하는 JavaScript 코드
가상 DOM 트리 : React처럼 가상 DOM을 사용해 변경 사항을 추적.
패치 : 변경된 부분만 실제 DOM에 반영.
실제 DOM : 최종적으로 브라우저에 렌더링된 결과
- 마운트 및 업데이트
공통점 : 이전 상태와 새로운 상태를 비교(diffing)한 뒤 변경된 부분만 실제 DOM에 반영
Vue : 반응형 데이터(ref, reactive)를 기반으로 변경을 감지
React :상태(useState)나 props 변경에 따라 컴포넌트가 리렌더링
- 패치 및 최적화
템플릿 vs JSX |
- JSX로 UI를 정의 <div>{state}</div> |
- <template>를 사용해 UI 정의 <div>{{ state }}</div><br>- JSX도 사용 가능 (render 함수나 JSX 활용). |
상태 관리 | - useState로 상태 관리 setState로 상태 업데이트 시 리렌더링 트리거. |
- ref로 반응형 데이터 생성 ref 값 변경 시 자동으로 UI 갱신 반응형 시스템이 렌더링 자동 트리거. |
리렌더링 | - 상태나 props 변경 시 컴포넌트 리렌더링 useEffect로 부수 효과 처리 |
- 반응형 데이터 변경 시 가상 DOM 트리 갱신, 변경된 부분만 패치 watch 또는 computed로 부수 효과 처리 |
기본구조
<template>
<a-modal
:visible="isOpen"
@update:visible="updateIsOpen"
:width="400"
centered
@cancel="closeModal"
>
<AuthComponent />
</a-modal>
</template>
<script setup>
import { defineProps, defineEmits } from 'vue'
import { useRouter } from 'vue-router'
import AuthComponent from './AuthComponent.vue'
const props = defineProps({
isOpen: {
type: Boolean,
required: true,
},
})
const emit = defineEmits(['update:isOpen', 'close']) // 상태 변경 이벤트와 닫기 이벤트 정의
const router = useRouter()
const closeModal = () => {
emit('close') // close 이벤트를 부모로 전달
if (router.currentRoute.value.path === '/login') {
router.back() // /login 경로인 경우 뒤로 이동
}
}
// 부모로 상태 업데이트를 전달하는 함수
const updateIsOpen = (value) => {
emit('update:isOpen', value) // 부모 컴포넌트로 새로운 visible 값 전달
}
</script>
ref
ref는 Vue 3에서 단일 값(원시 값 또는 객체)을 반응형으로 만들기 위해 사용
const loading = ref(true)
// 생략
loading.value = false
reactive
이벤트
<Child v-model="parentValue" />
<script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps(['value']);
const emit = defineEmits(['update:value']);
const updateValue = (newValue) => emit('update:value', newValue);
</script>
<template>
<input :value="props.value" @input="updateValue($event.target.value)" />
</template>
value prop으로 부모 → 자식 데이터 전달 (단방향)
update:value 이벤트로 자식 → 부모 데이터 전달 (단방향)
결과적으로 부모의 parentValue와 자식의 입력값이 동기화
v-model은 자식이 직접 부모의 데이터를 수정X
자식은 emit으로 이벤트를 보내고, 부모가 자신의 상태를 업데이트
설계 목적
- watch:
- Vue에서 명시적으로 특정 데이터의 변화를 감시하고, 그에 따라 정의된 콜백을 실행
- 반응형 시스템에 특화되어 있어, 감시 대상이 변경될 때만 반응
- useEffect:
- React에서 렌더링 이후 부수 효과를 처리하기 위한 훅
실행시점
- watch:
- 감시 대상이 변경될 때마다 즉시 실행
- immediate: true 옵션을 추가하면 처음에도 실행
- 변경 감지에 초점이 맞춰져 있어, 값이 바뀌지 않으면 실행X
- useEffect:
- 렌더링이 완료된 후 실행
- 의존성 배열이 변경되지 않으면 실행되지 않지만, 배열을 생략하면 매 렌더링마다 실행
- 초기 렌더링에서도 기본적으로 실행
Pinia 사용 예제
import { defineStore } from 'pinia'
export const useModalStore = defineStore('modal', {
state: () => ({
isLoginModalOpen: false,
}),
actions: {
openLoginModal() {
this.isLoginModalOpen = true
},
closeLoginModal() {
this.isLoginModalOpen = false
},
},
})
<LoginModal :isOpen="modalStore.isLoginModalOpen" @close="modalStore.closeLoginModal" />
느낀점
React를 주로 쓰다가 Vue를 사용해보니 Vue가 팀원간의 코드 일관성은 더 높을 수 있다고 생각했습니다. React가 자유도가 높은 대신에, Vue는 문법적 설탕이 있지만 템플릿화 되어있기 때문입니다.
다음시간에는 다음 링크를 학습해서 vue의 반응형 심화를 공부해보고자 합니다.
https://ko.vuejs.org/guide/extras/reactivity-in-depth
Vue.js
Vue.js - 프로그래시브 자바스트립트 프레임워크
ko.vuejs.org
참고
- Vue.js 렌더링 메커니즘 (https://ko.vuejs.org/guide/extras/rendering-mechanism#render-pipeline)
'실무 > 라이브러리 및 프레임워크' 카테고리의 다른 글
react-fast-marquee v1.6.5: Duration 계산 불안정으로 인한 속도 불일치 이슈 제기 (0) | 2025.03.28 |
---|---|
라이브러리 선택 과정 정리 및 공유 (0) | 2025.03.16 |
댓글