React.Native

[React] Props는 통신용이 아니다 : Props 진짜 이해하기

De-v-signer 2024. 11. 15. 00:09
728x90

리액트를 다루면서 처음에 많이 헷갈렸고, 지금도 종종 막히는 부분이 속성(Props) 관련 내용인데, 그리 어렵지 않은 것 같으면서도 막상 뭔가 만들 때에는 의도한대로 작동하지 않아 당황하게 만드는 요인이기 때문이다. 이번 포스팅에서는 이 속성에 대해 완벽히 살펴봄으로써 올바르게 사용해보고자 한다.

일단 속성(Props; Properties) 자체는 웹에서 쓰던 형태와 동일하다. 웹에서는 문서의 엘리먼트(Element)의 구체적인 속성을 정의할 때 속성을 활용하는데, 예를 들어

<a href="linkTo://">LINK</a>

위의 예시에서 하이퍼링크 참조(href; hyper reference)가 a 엘리먼트의 속성에 해당한다. 속성은 문서의 마크업 태그 자체가 가지고 있는 성질이며, 해당 성질을 정의해줌으로써 엘리먼트가 그 성질을 갖도록 한다.

리액트에서는 엘리먼트가 컴포넌트(Component)에 대응하는데, 리액트에서 컴포넌트는 정의 가능한 일종의 함수 또는 클래스형 객체(Object) 이기 때문에 웹 문서에서처럼 어떤 정해진 속성을 따르는 경우도 많지만 다수의 경우 직접 만든 속성 값을 사용하게 된다. 이 때 속성의 역할은 함수 또는 클래스 객체의 인자(parameter), 인수(argument)와 같이 동작한다.

예를 들어 

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

위의 Welcome이라는 함수는 props라는 인자를 갖는데, 이는 Welcome이라는 컴포넌트의 속성이 된다. 즉 이를 사용할 때

function App() {
  return (
    <div>
      <Welcome name="Sara" />
    </div>
  );
}

위와 같이 Welcome이라는 컴포넌트의 name 속성을 Sara로 입력하면 이는 Welcome이라는 함수의 인수처럼 동작하여

<div>
	<h1>Hello, Sara.</h1>
</div>

위의 결과를 출력하게 된다는 의미이다.

그런데 실제로 우리가 리액트에서 Props를 쓸 때에는 이런 식으로 명시된 속성을 사용하기보다는 부모 컴포넌트에서 자식 컴포넌트로 어떤 데이터를 통신하기 위해서 더 많이 사용한다. 위의 예시도 'Welcome이라는 컴포넌트에 속성을 부여했다'고도 말할 수 있지만 'App 컴포넌트에서 Welcome 컴포넌트로 name 데이터를 전달했다'고도 이야기할 수 있는데, 속성이 정의된 컴포넌트는 그 데이터를 컴포넌트 내부에서 확인할 수 있게 되기 때문에 결과적으로 부모 컴포넌트로부터 자식 컴포넌트가 데이터를 상속받는 기능을 할 수 있게 된다.

이러한 점이 과장 오인되어 Props가 부모로부터 자식에게 값을 전달하기 위한 통신 방식처럼 여겨지는 경우가 있는데, property 라는 단어 자체에서 보여지듯이 어디까지나 property의 본 기능은 컴포넌트의 '속성'을 정의하는 것이라고 보는 게 옳다고 본다. 다만 이 속성을 정의하는 과정에서 컴포넌트의 부모에서 정의한 속성 값을 받아서 쓰게 되는데, '이를 이용하면 하향식 데이터 통신에도 이용할 수 있다'로 봐야 첫 머리에 이야기한 '의도대로 동작하지 않는' 경우를 줄일 수 있을 것이라 생각된다.

속성이 인수/인자처럼 사용된다고 했지만 엄밀히 말해 완전히 같은 것은 아닌데, 엘리먼트와 컴포넌트의 대응 관계에서 속성과 인수가 대응하는 관계가 되긴 했지만 어디까지나 속성은 속성이고, 인수는 인수여야 하기 때문이다. 대표적으로 차이가 생기는 것이 속성의 '순수성' 부분인데, 승계받은 속성은 참조값일 뿐, 조작이 불가능하다. 즉,

const MyComponent = (props) => {
	props.name = 'Override Name'; // Not Available
    return {
    <div>
    	<h3>props.name</h3>
    </div>
    }
}

위와 같이 전달받은 props를 다른 값으로 가공하려 하면 안 된다는 것이다. props는 어디까지나 해당 컴포넌트에 주어진 속성이기 때문에 변경할 수 없다. 즉, 읽기 전용(read-only)이다.

'잉크'에 '검정색' 속성을 주어 '검정색 잉크'로 정의했다면, 그 속성은 바꿀 수 없다는 것과 같다. 이는 컴포넌트의 정체를 의미하는 것과도 같아서 이미 결합되어 하나의 객체를 이루고 있다고 보아야 하며, 따라서 속성을 바꾼다는 것은 그 컴포넌트의 정체 자체를 부정한다는 것이나 다름없기 때문이다.

이는 인자/인수의 사용과도 차이를 갖는데, 함수의 인자/인수는 함수를 호출하기 위한 조건일 뿐 호출이 이뤄진 이후에는 어떠한 가공도 가능하다. 비슷해보이지만 그 출발점과 용도가 다르기 때문에 용어도 분화하고 세부적인 부분에서 차이를 보이는 것이다.

그렇다면 Props의 주요한 기능으로 인식되는 부모-자식 컴포넌트 간의 데이터 교환이라는 측면에서 어떠한 개념이 존재하고 어떠한 방법이 옳은가에 대한 의문이 생기는데, 이러한 점은 좀 더 깊이 다뤄보면서 다시 잡아볼 필요가 있어 보인다.

 

반응형