본문 바로가기
카테고리 없음

document.getElementsByClassName 보다 ref 쓰는 이유

by 안전관리자kim 2022. 10. 5.
반응형

리액트에서는 DOM 요소에 접근하기 위해 주로 ref를 씁니다. document.getElementsByClassName 등을 쓰는 게 아니라 ref를 쓰는 이유는 무엇일까요?

 

DOM

먼저 DOM 은 Document Object Model라는 뜻으로 html 문서 태그들에 JS 로 접근 할 수 있는 객체 모델을 말한다.

 

예를 들어 onclick 함수로 input 태그를 비활성화하려고 한다. 그렇다면 예제를 가져와서 이해해보면 편하다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title> 문서객체 모델(DOM)</title >
<script type= "text/javascript">
    window.onload = function(){
       //1. 문서 객체 생성
       var header = document.createElement('h2'); 
       var textNode = document.createTextNode('Hello DOM');

       //2. 노드(요소/텍스트)를 연결.
       header.appendChild(textNode);

       //3. body 문서 객체에 header 문서 객체를 추가.
       document.body.appendChild(header);
    };
</script>
</head>
<body>
   <h1 id ="header_1" name= "" >HEADER-1 </h1 >
   <div >
      <h1 id = "header_2">HEADER-2</h1 >
   </div >
   <hr >
   <h1 id = "clock"></h1>
</body>
</html>

위의 HTML 예제에서 document.createElement('h2') 라는 DOM 모델을 사용해 h2 태그를 생성했다.

그 후 document.createText('Hello DOM') 라는 DOM 모델을 사용하여 “Hello DOM”이라는 텍스트 노드를 생성해 주었다.

그 밑에 h2 태그를 생성한 노드에, 텍스트 노드를 연결하는 header.appendChild(textNode)

그리고 body 태그 안에 header 문서 객체를 추가하기 위해 document.body.appendChild(header) 을 사용한다.

 

이처럼 자바스크립트 내에서 html 객체에 접근할 수 있는 객체모델을 DOM 이라고 한다.

그렇다면 ref 는 무엇이고, 왜 react는 DOM < ref 일까..?

우리가 이전에 VanillaJS에서 JQuery를 사용하여 쉽게 html에 간섭할 때, 이용한 것이 바로 id 이다.

그 시절 우리는 html 태그 내에 건들이고 싶은 태그 내에 id 값을 부여했고, JQuery에서 그 id값을 지정하여 원하는 모션을 취하였다.

 

이제 저무는 해인 JQuery의 편리함을 react도 아는가 본지, 비슷한 원리의 ref 라는 것을 만들어 직접 DOM에 직접 접근할 수 있게 되었다…!

 

먼저 ref 는 우선적으로 state로만 해결할 수 없고, DOM을 반드시 직접 건드려야 할 때 사용된다.

 

대표적으로 ref는 어떻게 쓰이는 걸까?

  • 함수형 컴포넌트그리고 div.box 요소에 ref={personInfo} 값을 부여하여 dom 요소로 조작이 가능해진다
  • useRef 라는 hook을 사용하여 ref를 활용, 이 예시에서는 const personInfo = useRef() 을 통해 personInfo에 ref 객체를 반환한다.
const TestComponent = (props) => {

    const {id, nickName} = props;
    const personInfo = useRef();

    // 영역을 png로 저장하는 함수
    const onClick = function () {
        domtoimage.toPng(personInfo.current) // ref를 부여한 요소에 .current로 접근
        .then(function (blob) {
          window.saveAs(blob, 'user-card.png');
        })
    };

    return (
        <>
            <div className="box" ref={personInfo}> {/*div.box 요소에 ref 부여함*/}
                <p> {id} - {nickName} 테스트 영역 </p>
            </div>
            <button onClick={onClick}>저장</button>
        </>
    );
}

클래스형 컴포넌트

  • ref 를 달고자 하는 요소에, ref 라는 콜백 함수를 props 로 전달해 주면 된다.
  • 즉 ref 가 파라미터가 되고, 그 파라미터로 컴포넌트 멤버 변수로 설정한다.
<input
  ref={(ref) => {
    this.input = ref;
  }}
/>

그런데 꼭 콜백함수에서만 사용가능한 것이 아니라 components 에서도 가능하다.

이 방법은 컴포넌트 내부의 DOM 요소를 컴포넌트 외부에서 사용해야 할 때 활용하게 된다.

 

<MyComponent
  ref={(ref) => {
    this.myComponent = ref;
  }}
/>
여기서 document 속성이랑 ref의 가장 큰 차이점은 ref는 컴포넌트 라이프 사이클 내에서 유지가 되며, 변경이 가능한 변수이자, 값이 가변할 때, 렌더링 되지 않는다.
즉 ref를 더 적재적소에 잘 활용하는 이유는 dom 요소에 접근하여 컴포넌트 전체 렌더링과는 관계 없는 작업을 할 때 유용하게 사용되기 때문이다.

 

728x90
반응형