Vue 또는 Svelte 에서 function props 는 anti-pattern 인가?

katanazero·2022년 2월 15일
0

vue

목록 보기
14/15

Vue 또는 Svelte 에서 funtion props 는 anti-pattern 인가?

  • 안티패턴(anti-pattern)은 소프트웨어 공학 분야 용어이며, 실제 많이 사용되는 패턴이지만 비효율적이거나 비생산적인 패턴을 의미

React.js 에서는 부모에서 자식 컴포넌트에게 데이터를 props 로 전달이 가능하다.
props 는 상위 -> 하위로만 데이터가 흐르며, 이를 단방향 데이터 바인딩이라고 부른다.
자식 컴포넌트는 전달받은 function props 를 통해서 부모 컴포넌트에 정의된 어떤 동작을 호출한다.
그저 부모는 어떤 동작에 대한 핸들러를 props 로 전달해주면 된다.

const Child = ({handleOnClick}) => {
  const onClick = () => {
    handleOnClick('test');
  };

	return(
    	<button onClick={onClick}>Child Button</button>
    )
};

function App() {
  const handleOnClick = (msg = '') => {
    console.log('App Component', msg);
  };
  
  return(
  	<div>
    	<Child handleOnClick={handleOnClick}/>
    </div>
  )
}

React 에서 핸들러를 props 로 처리했지만, Vue 와 Svelte 는 조금 다르다.
Vue 에서는 emits 를 사용하며, Svelte 에서는 createEventDispatcher 를 사용한다.

  • Vue
// HelloWorld
<script>
export default {
  props: {
    msg: {type: String, required: true},
  },
  emits: ['click'],
  setup({msg}, { attrs, slots, emit, expose }) {
    console.log(msg);

    const onClick = () => {
      emit('click');
    };

    return {
      onClick,
    }
  }
}
</script>

<template>
  <div class="greetings">
    <h1 class="green">{{ msg }}</h1>
    <button @click="onClick">Test</button>
  </div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';

export default {
  components: {
    HelloWorld
  },
  setup() {

    const handleOnClick = () => {
      console.log('zzz123');
    };

    return {
      handleOnClick
    }
  }
}
</script>

<template>
  <header>
    <img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125"/>
    <div class="wrapper">
      <HelloWorld msg="You did it!" @click="handleOnClick"/>
    </div>
  </header>
</template>

  • Svelte
// Inner
<script>
	import { createEventDispatcher } from 'svelte';
	const dispatch = createEventDispatcher();
	function sayHello() {
		dispatch('message', {
			text: 'Hello!'
		});
	}
</script>
<script>
	import Inner from './Inner.svelte';
	function handleMessage(event) {
		alert(event.detail.text);
	}
</script>

<Inner on:message={handleMessage}/>

핸들러를 다른방식으로 처리를 하고 있지만, function 을 전달해서 바인딩하는 방식도 가능하다.
분명 Vue 와 Svelte 에서는 React 와는 다른 방법을 제공하고는 있지만 안티패턴은 아니라고 생각을 한다.

전략패턴(Strategy Pattern) 관점으로 생각을 하였을 경우에 크게 비효율적이거나 문제를 일으키지는 않기때문이다.
전략패턴은 클라이언트는 다양한 전략 중 하나를 선택해 생성한 후 컨텍스트에 주입한다.

만약 어떤 기능에 대해서 구현을 하는데, 로직이 조금씩 다른 경우가 발생을 한다.(run() 메서드를 구현하는데, 어떤곳에서는 제한을 100에서 둬야하는 경우라던가.. 아니면 제한이 없다던가 등) 그럴때 전략패턴을 사용하면 각각의 로직을 전략에 맞게 교환하여 사용합니다.(행위를 각각의 전략으로 만들어놓고 주입해서 사용)

JS 에서는 직접 함수를 구현 또는 ES6 클래스 구문을 사용하여 구현을 합니다.
이러한 부분으로 보았을때, 전달되는 핸들러는 각 부모 컴포넌트에서 잘 정의된 전략인겁니다.

handleClick 이라는 함수명에 잘 맞게 구현하여 주입해주면 된다.

const childComponent = ({handleClick}) => {
	return(
    	<button onClick={handleClick}>버튼</button>
    )
}

결론은 제공되어지는 방식도 좋은방법이며, 함수를 전달하는 방식이 꼭 안티패턴은 아닙니다.

profile
developer life started : 2016.06.07 ~ 흔한 Front-end 개발자

2개의 댓글

comment-user-thumbnail
2022년 11월 20일

안녕하세요, 퍼스널 코멘트 섹션을 만드는 tweetbase.com 대표 박홍범입니다. 

최근 시드팁스1기에 합격하여 3번째 웹 개발자를 찾고 있습니다. 개발 블로그를 보고 인상깊어 연락드립니다. 관심이 있으시면 a@kylepark.xyz로 연락주세요 : )

1개의 답글