컴포넌트 간 통신 방식 정리 props emit event bus global store 완벽 가이드
🚀 다양한 컴포넌트 통신 방법을 이해하면 프론트엔드 개발이 훨씬 쉬워집니다
프론트엔드 개발을 하다 보면 화면을 구성하는 여러 컴포넌트들이 서로 정보를 주고받아야 하는 순간이 자주 발생합니다.
버튼을 클릭했을 때 상위 화면에 변화를 주거나, 입력한 데이터를 다른 영역에서 실시간으로 반영해야 하는 경우가 대표적이죠.
이때 어떤 방식으로 데이터를 전달할지가 중요한데, 단순한 구조에서는 props만으로도 충분하지만 규모가 커지면 emit, event bus, global store 같은 방식이 필요합니다.
효율적인 통신 구조를 잡아 두면 프로젝트 유지 보수는 물론 성능과 가독성까지 크게 달라집니다.
이번 글에서는 컴포넌트 간 데이터를 주고받는 다양한 기법을 정리해 보려고 합니다.
실제 개발 상황에서 언제 어떤 방식을 선택해야 하는지도 함께 다룰 예정이라, 입문자부터 현업 개발자까지 모두 참고할 수 있는 가이드가 될 것입니다.
React, Vue, Svelte, Angular 등 어떤 프레임워크를 사용하더라도 개념은 크게 다르지 않기 때문에, 전반적인 이해를 먼저 쌓는 데 큰 도움이 될 겁니다.
📋 목차
🔗 props를 이용한 단방향 데이터 전달
props는 가장 기본적이면서도 널리 사용되는 컴포넌트 간 통신 방식입니다.
상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때 활용되며, 단방향 데이터 흐름을 보장합니다.
이 방식은 데이터의 출처를 명확히 하고 디버깅을 쉽게 만든다는 장점이 있습니다.
예를 들어 부모 컴포넌트에서 자식 컴포넌트로 사용자 이름이나 설정 값을 넘길 때 props를 사용합니다.
이때 자식 컴포넌트는 전달받은 props를 직접 수정할 수 없고, 오직 읽기 전용으로만 활용해야 합니다.
만약 수정이 필요하다면 이벤트를 통해 상위 컴포넌트에 알린 후 상태를 갱신해야 합니다.
📌 props 사용 예시
// 부모 컴포넌트
<ChildComponent userName="홍길동" />
// 자식 컴포넌트
props: {
userName: {
type: String,
required: true
}
}
위 코드처럼 부모에서 `userName`이라는 props를 전달하면, 자식은 이를 받아 화면에 출력하거나 내부 로직에서 활용할 수 있습니다.
이 단순한 구조 덕분에 대부분의 초기 프로젝트에서는 props만으로도 충분히 상태 관리를 이어갈 수 있습니다.
💡 TIP: props는 데이터 흐름을 명확하게 하고 유지보수를 쉽게 하지만, 너무 깊은 컴포넌트 트리에서 다단계로 전달되면 번거로워질 수 있습니다.
🛠️ emit으로 하위 컴포넌트 이벤트 전달
props가 부모에서 자식으로 데이터를 내리는 방법이라면, emit은 자식이 부모에게 신호를 보내는 방식입니다.
즉, 하위 컴포넌트가 특정 동작을 수행했을 때 상위 컴포넌트에 알려서 반응하도록 만드는 구조입니다.
이로써 양방향 통신이 가능해지고, 데이터 갱신 흐름이 자연스럽게 이어집니다.
예를 들어 자식 컴포넌트의 버튼이 클릭되면 부모에게 “클릭 이벤트가 발생했다”라는 사실을 알리고, 부모는 이를 받아 다른 UI 업데이트나 데이터 처리를 실행할 수 있습니다.
이 방식은 Vue, Svelte 같은 프레임워크에서 자주 사용되며 React에서는 props로 콜백 함수를 내려보내는 방식으로 유사하게 구현됩니다.
📌 emit 사용 예시
// 자식 컴포넌트
<button @click="$emit('clicked')">확인</button>
// 부모 컴포넌트
<ChildComponent @clicked="handleClick" />
methods: {
handleClick() {
console.log("자식에서 클릭 이벤트 발생");
}
}
이 구조를 통해 자식은 직접 부모의 데이터를 수정하지 않고, 단순히 이벤트를 발생시켜 부모가 반응할 수 있도록 돕습니다.
덕분에 데이터의 흐름과 책임 분리가 더욱 명확해집니다.
💎 핵심 포인트:
emit은 자식이 부모에게 데이터를 직접 전달하는 것이 아니라, 이벤트를 알리는 방식입니다. 이 때문에 유지보수가 쉽고 예측 가능한 코드 흐름을 유지할 수 있습니다.
⚙️ event bus를 활용한 컴포넌트 간 통신
event bus는 독립된 이벤트 관리 객체를 만들어, 여러 컴포넌트 간의 통신을 가능하게 하는 방식입니다.
특히 상위-하위 관계가 없는 컴포넌트 간에도 데이터를 주고받을 수 있다는 점이 큰 장점입니다.
즉, A 컴포넌트에서 이벤트를 발생시키고, 전혀 다른 위치의 B 컴포넌트가 그 이벤트를 수신하는 구조를 만들 수 있습니다.
Vue 2 시절에는 event bus 패턴이 널리 사용되었으며, React에서도 유사한 방식으로 Node.js의 EventEmitter나 외부 라이브러리를 활용해 구현할 수 있습니다.
규모가 작은 프로젝트에서 빠르게 컴포넌트 간 연결을 만들 때 유용하지만, 규모가 커질 경우 이벤트 흐름이 복잡해져 추적이 어려워질 수 있습니다.
📌 event bus 사용 예시
// eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();
// A 컴포넌트
EventBus.$emit('custom-event', { message: "Hello!" });
// B 컴포넌트
EventBus.$on('custom-event', (data) => {
console.log(data.message);
});
위 예시는 Vue에서 event bus를 활용한 가장 기본적인 패턴입니다.
A 컴포넌트가 이벤트를 발생시키면, B 컴포넌트가 해당 이벤트를 수신하여 동작을 실행합니다.
이처럼 간단한 구조에서는 매우 편리하지만, 관리 포인트가 많아지면 디버깅이 어려워질 수 있습니다.
⚠️ 주의: event bus는 남용할 경우 이벤트 추적이 힘들어져 프로젝트 복잡도가 급격히 증가할 수 있습니다. 장기적으로는 global store 같은 더 체계적인 상태 관리 방식을 고려하는 것이 좋습니다.
🔌 global store 상태 관리의 장점
global store는 프로젝트 전역에서 사용할 수 있는 상태 저장소를 두고, 필요한 컴포넌트들이 해당 저장소에 접근해 데이터를 읽거나 수정하는 방식입니다.
대표적인 예시로는 React의 Redux, Vue의 Vuex, Pinia, Svelte의 Store가 있습니다.
이 방식은 대규모 프로젝트에서 데이터 일관성을 유지하고, 컴포넌트 간 복잡한 의존성을 줄여주는 강력한 도구입니다.
예를 들어 로그인 상태, 사용자 프로필, 쇼핑 카트 데이터처럼 여러 화면에서 동시에 사용되는 값들을 global store에 저장하면, 각 컴포넌트는 동일한 소스에서 데이터를 가져와 사용하게 됩니다.
이를 통해 데이터의 단일 출처(Single Source of Truth)를 보장하고, 버그 발생 가능성을 줄일 수 있습니다.
📌 global store 사용 예시
// Redux 예시
const initialState = { count: 0 };
function counterReducer(state = initialState, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
default:
return state;
}
}
이처럼 전역 상태를 관리하는 도구를 사용하면, 특정 데이터가 어디서 변경되었는지 추적하기 쉽고, 테스트 코드 작성도 수월해집니다.
또한 규모가 커질수록 유지보수에 큰 도움이 됩니다.
- 📌전역에서 공통 데이터를 관리할 수 있다
- 📌데이터 흐름과 변경 내역을 쉽게 추적할 수 있다
- 📌규모가 큰 프로젝트에서도 안정적인 상태 관리를 보장한다
💡 상황에 맞는 통신 방식 선택 가이드
컴포넌트 간 통신 방식은 프로젝트 규모, 데이터 복잡도, 컴포넌트 구조에 따라 달라져야 합니다.
모든 상황에 만능으로 적용되는 방법은 없으며, 상황에 맞게 적절히 선택하는 것이 가장 중요합니다.
각 방식을 잘 이해하고 조합해 활용한다면 훨씬 더 깔끔하고 유지보수하기 좋은 코드를 만들 수 있습니다.
📌 선택 기준 요약
| 방식 | 적합한 상황 |
|---|---|
| props | 단순한 상위-하위 컴포넌트 간 데이터 전달 |
| emit | 자식 → 부모로 이벤트 알림이 필요한 경우 |
| event bus | 관계없는 컴포넌트 간 빠른 통신 |
| global store | 대규모 프로젝트에서 전역 상태 관리 |
위 표처럼 단순한 UI에서는 props와 emit만으로도 충분하지만, 프로젝트가 확장되면 event bus나 global store가 필요합니다.
특히 팀 단위 협업에서는 데이터 흐름이 명확해야 하므로 상태 관리 도구의 도입이 필수에 가깝습니다.
💎 핵심 포인트:
규모가 작은 프로젝트에서는 props와 emit으로도 충분합니다. 하지만 프로젝트가 커질수록 상태 관리 도구를 적극적으로 고려하는 것이 장기적인 유지보수에 유리합니다.
❓ 자주 묻는 질문 (FAQ)
props와 emit만으로 모든 프로젝트를 커버할 수 있나요?
event bus는 요즘에도 자주 사용되나요?
React에서는 emit 같은 기능을 어떻게 구현하나요?
global store를 꼭 사용해야 하나요?
Redux와 Vuex 같은 전역 상태 관리 도구의 차이점은 무엇인가요?
event bus보다 global store가 더 좋은 이유는 무엇인가요?
상태 관리 도구를 도입할 때 성능 저하가 있나요?
초보자가 처음 배우기에 가장 좋은 통신 방식은 무엇인가요?
📌 컴포넌트 통신 방식을 이해하면 개발이 달라집니다
컴포넌트 간 통신은 프론트엔드 개발에서 가장 기본적이면서도 중요한 주제 중 하나입니다.
단순히 props와 emit으로 시작해도 충분하지만, 프로젝트가 커질수록 event bus와 global store 같은 더 체계적인 방법이 필요해집니다.
이번 글에서 다룬 각 방식은 상황에 맞게 적절히 활용해야 하며, 모든 방법을 고루 이해해두면 어떤 프로젝트에서도 안정적이고 확장성 있는 구조를 만들 수 있습니다.
특히 팀 단위 협업이나 장기적으로 유지보수해야 하는 대규모 프로젝트라면, 데이터 흐름이 명확하고 관리가 용이한 통신 구조가 필수적입니다.
앞으로 개발을 진행할 때 본문에서 설명한 가이드를 참고한다면 불필요한 버그를 줄이고, 코드 품질을 높이며, 더 나은 사용자 경험을 제공할 수 있을 것입니다.
🏷️ 관련 태그 : 프론트엔드개발, 컴포넌트통신, props, emit, eventbus, globalstore, Vue, React, 상태관리, 개발가이드