vue.js (뷰) 3에는 composition API(컴포지션 API)라는것이 도입이 되었는데요,
이것이 무엇인지 알아봅시다.
composition API(컴포지션 API)
vuejs를 만든 Evan You는 컴포지션 API를 전역적으로 선언된 함수(function)를 이용해 라이프사이클 훅을 등록할 수 있는 기능과 결합된 반응형 API라고 설명하였습니다.
이는 컴포지션 API가 조직과 가독성을 훼손하지 않고 애플리케이션 내 모든 지점에서 반응성을 관리할 수 있는 다른 방법을 제공한다는 게 골자입니다.
컴포지션 API는 정말로 언어에 새로운 것을 추가하는 것이 아닙니다.
뷰가 이미 사용하는 내부 기능들(일명, 마법)을 노출시키고, 우리가 이러한 기능들을 구성 요소에서 직접 사용할 수 있게 합니다.
composition API를(컴포지션 API) 도입한 이유
단편화되고 복잡한 구성요소를 이해하고 유지하기 어렵운 기존 방식을 탈피하고자 컴포지션 API 가 도입되었습니다.
기존 방식인 option API는 근본적인 논리적 관심사를 파편화되게 만듭니다.
또한, 하나의 논리적 관심사를 작업할 때 우리는 관련 코드에 대한 옵션 블록을 중심으로 끊임없이 점프해야 합니다.
동일한 논리적 관심사와 관련된 코드를 한군데로 모을 수 있다면 코드를 이해하고 유지보수하는데 쉬울것입니다.
이것이 바로 컴포지션 API가 우리가 할 수 있게 하는 것입니다.
특정 사용자의 저장소 목록을 보여줄 수 있는 뷰 컴포넌트에 대한 코드를 작성하고,
여기에 검색 및 필터 기능을 적용하면 코드를 다음과 같이 작성할 수 있을것입니다.
// src/components/UserRepositories.vue
export default {
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props: {
user: {
type: String,
required: true
}
},
data () {
return {
repositories: [], // 1
filters: { ... }, // 3
searchQuery: '' // 2
}
},
computed: {
filteredRepositories () { ... }, // 3
repositoriesMatchingSearchQuery () { ... }, // 2
},
watch: {
user: 'getUserRepositories' // 1
},
methods: {
getUserRepositories () {
// using `this.user` to fetch user repositories
}, // 1
updateFilters () { ... }, // 3
},
mounted () {
this.getUserRepositories() // 1
}
}
이 컴포넌트는 다음과 같은 역할을 합니다.
- 사용자 이름에 대한 추정 외부 API에서 리포지토리를 가져와 사용자가 변경될 때마다 새로 고침 -- 1
- 검색 쿼리 문자열을 사용하여 리포지토리 검색 -- 2
- 필터 객체를 사용하여 리포지토리 필터링 -- 3
이 코드만 봐도 동일한 역할에 대해 코드들이 서로 떨어져 있는것 을 확인할 수있습니다.
규모가 커질수록 이러한 파현화는 더 커지고, 코드를 읽기도 힘들어져서 유지보수하는데 꽤나 고생할것입니다.
composition API(컴포지션 API) 사용하기, setup()
앞서 우리는 파편화된 논리적 구조를 가진 컴포넌트를 보았습니다.
이를 해결하기위해 도입된 vue3의 composition API 는 setup 이라는 메소드를 사용합니다.
setup()은 컴포넌트 선언시 아래와 같이 선언됩니다.
setup()의 return 안의 내용은 데이터를 그룹핑 하여 표현할 수 있습니다.
// src/components/UserRepositories.vue
export default {
components: { ... },
props: {...},
setup(props) {
return {
// 컴포넌트의 나머지부분은 무엇이든지 여기에 위치할 수 있습니다.
}
}
, ... ( 컴포넌트의 나머지부분 )
}
ref와 reactive
Vue 3.0에서는 ref()와 reactive() 함수로 임의의 변수를 반응성으로 만들 수 있습니다.
또한, toRef()를 이용하여 reactive를 ref로 변경할 수 있습니다.
import { ref, reactive } from "vue";
const counter = ref(0)
const person = reactive({ name: "mike" });
const toRef = toRefs(person);
ref나 reactive나 둘다 반응성으로 만들수 있습니다.
reactive는 객체만 매개변수로 받을 수 있으나, ref는 원시타입(int, string)도 매개변수로 받을 수 있습니다.
자세한 것은 나중에 한번 다뤄보겠습니다.
기본적으로 저는 ref를 자주 쓰게 될것같네요.
setup() 에서의 lifecycle hook(라이프사이클 훅)
vue3에서의 setup 라이프사이클 훅은 아래와 같이 사용할 수 있습니다.
setup (props) {
onMounted(getUserRepositories) // on `mounted` call `getUserRepositories`
onUnmounted(() => console.log("component onUnmounted"));
onUpdated(){
console.log("component onUpdated"));
}
return {
//...
}
}
사용가능한 라이프사이클 훅은 다음과 같습니다.
- onBeforeMount -언마운트 전에 호출
- onMounted -컴포넌트가 마운트 될 때 호출.
- onBeforeUpdate -반응 형 데이터가 변경 될 때와 다시 렌더링하기 전에 호출.
- onUpdated - 렌더링 후 호출
- onBeforeUnmount -Vue 인스턴스가 언마운트 전에 호출됩니다.
- onUnmounted -인스턴스가 언마운트 된 후 호출됩.
- onActivated -연결 유지 구성 요소가 활성화되면 호출.
- onDeactivated -연결 유지 구성 요소가 비활성화 될 때 호출.
- onErrorCaptured -하위 구성 요소에서 오류가 캡처 될 때 호출.
- onRenderTracke d - 화면을 다시 그리기 위한 리액티브 디펜던시가 처음으로 감지되었을 때. 디버깅하기 위한 용도.
- onRenderTriggered - 첫 번째 렌더링이 일어났을 때. 어떤 이유로 화면이 다시 그려진건지 디버깅하기 위한 용도.
vue3 이전 기존의 option API 와 비교하면 다음과 같습니다.
좌측이 option API 이고, 우측이 이번에 도입된 composition API에서의 라이프사이클 훅입니다.
- beforeCreate -> setup()을 사용하도록 한다.
- created -> setup() 을 사용하도록 한다.
- beforeMount -> onBeforeMount
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforeUnmount -> onBeforeUnmount
- unmounted -> onUnmounted
- errorCaptured -> onErrorCaptured
- renderTracked -> onRenderTracked
- renderTriggered -> onRenderTriggered
- activated -> onActivated
- deactivated -> onDeactivated
정리& lt;/B>
composition API 를 도입하기 위한 스킬 또는 키워드들이 더 있지만 내용이 길어져서 여기까지 소개해보겠습니다.
compotision API 를 도입하면 아래와 같이 관심사를 좀 더 한군데로 쉽게 모아 코드작성이 가능합니다.
다음에 기회가 된다면 composition API 에 대해 좀 더 심도있게 다뤄보겠습니다.
import { toRefs } from 'vue'
import useUserRepositories from '@/composables/useUserRepositories'
import useRepositoryNameSearch from '@/composables/useRepositoryNameSearch'
import useRepositoryFilters from '@/composables/useRepositoryFilters'
export default {
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props: {
user: {
type: String,
required: true
}
},
setup(props) {
const { user } = toRefs(props)
// 기존의 1부분
const { repositories, getUserRepositories } = useUserRepositories(user)
// 기존의 2 부분
const {
searchQuery,
repositoriesMatchingSearchQuery
} = useRepositoryNameSearch(repositories)
//기존의 3부분
const {
filters,
updateFilters,
filteredRepositories
} = useRepositoryFilters(repositoriesMatchingSearchQuery)
return {
repositories: filteredRepositories,
getUserRepositories,
searchQuery,
filters,
updateFilters
}
}
}
총평
처음에는 composition API 라는 새로운 개념/용어가 도입되고 vue2와도 코드 작성법이 좀 달라져서 이게 뭔가 싶었습니다.
하지만 논리적 관심사를 최대한 한군데로 모으기 위해 노력한 것임을 명심하고 코드를 작성하면 자연스럽게 체득이 될것이라 봅니다.
코드를 더 유지보수하기 쉽게 고민하다보면 자연스럽게 지켜지게 되는것은 아닐까 싶습니다.
composition API가 뭔가해서 함수들이 추가되고 그 함수사용법들을 새로 익혀야만 하는줄 알았는데,
논리적 관심사를 한군데로 모으자는 일종의 패러다임인것으로 느껴졌습니다.
vue.js 3.0 composition api, vue3 composition api, vuejs 3 composition api,vue.js 3.0 컴포지션 api, vue3 컴포지션 api, vuejs 3 컴포지션 api,뷰3 컴포지션 api,
댓글