개발자

useRef의 작동방식이 궁금합니다

2022년 10월 13일조회 1,863

useRef를 통해 dom element에 접근하기도 하고, stale closure문제를 해결하는데에도 사용하는데, 실질적으로 어떻게 작동해서 이게 가능한지 궁금합니다.

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 1

인기 답변

손정현님의 프로필 사진

안녕하세요! useRef를 통해 만들어지는 것은 JS의 객체와 유사하다고 보면 됩니다. useRef를 통해 만든 값이 일반 객체와 다른점은, 매 렌더링 시 동일한 객체를 제공하는 것입니다. - useRef<T>(initialValue: T): {current: T} - (참고: https://github.com/facebook/react/blob/fd31724d5d41a4df71af55f710b46562874511f9/packages/react-reconciler/src/ReactInternalTypes.js#L388) - (참고: https://ko.reactjs.org/docs/hooks-reference.html#useref) useRef를 통해 받은 값은 useRef가 사용된 컴포넌트의 라이프사이클 동안 사용할 수 있습니다. JSX에 특정 DOM 컴포넌트에 ref={useRef를 통해 받은 값}을 추가하시게 되면, 컴파일러가 JSX를 컴파일하면서 JS로 변환을 시켜주고 해당 JS를 브라우저가 실행하면서 값을 채워넣어주는 것으로 알고있습니다. (참고: https://ko.reactjs.org/docs/jsx-in-depth.html) stale closure의 경우는 useRef의 값이 항상 같은 객체이고 closure안에서는 이 객체를 "참조"하는 형식이기 때문에, 객체의 current 값이 바뀌면 closure 안에서도 바뀐 current 값을 사용할 수 있습니다. (reference 관련 so 글 참고: https://stackoverflow.com/questions/8318357/javascript-pointer-reference-craziness-can-someone-explain-this) 저도 질문에 답변하려고 여러가지 실험들을 해보았는데요. Functional component로 gist를 한번 만들어보았습니다. 저도 헷갈리는 부분이 있긴하지만 확실히 일반 JS 객체 대신 왜 useRef를 사용해야하는 이유를 알게된 것 같네요. (https://gist.github.com/json9512/ef28abf2429c639ccbdd6b48c7c3efe5) 결론은 useRef의 동작 방식이 가능한 이유는 JS에서 객체를 접근할때 참조 형식으로 접근한다는 점과 useRef를 통해 받은 객체가 항상 동일하다는 점 때문인 것 같습니다. 제가 참고했던 아티클들 첨부할게요. - https://dmitripavlutin.com/react-useref-guide/ - https://www.freecodecamp.org/news/react-under-the-hood/ - https://www.smashingmagazine.com/2020/11/react-useref-hook/ - https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Working_with_Objects#%EA%B0%9D%EC%B2%B4_%EA%B0%9C%EC%9A%94 - https://hewonjeong.github.io/deep-dive-how-do-react-hooks-really-work-ko/

profile picture

익명

작성자

2022년 10월 14일

와 상세한 답변 너무 감사드립니다! 공부하면서 헷갈리는 점들이 많았는데 덕분에 많이 해소되었습니다! 감사합니다:)

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

비슷한 질문 2

Q. react의 setState가 정상동작하지 않아요.

react를 이용해 이것저것 테스트해보고 있는데요. 버튼을 눌렀을 때 state를 1 증가시키는 예제를 해보고 있습니다. const oneCountUp = () => { setCount(count + 1); }; 위처럼 1 증가시키는 함수를 정의해서 onClick에서 위의 함수를 호출하는 방식으로 했습니다. 근데 호기심에 3을 증가시켜보자 하고 oneCountUp을 3번 호출했습니다. 근데 여전히 1만 올라갑니다. 왜 그런걸까요??? import React, { useState } from 'react'; export default function CountTest() { const [count, setCount] = useState(1); const oneCountUp = () => { setCount(count + 1); }; return ( <div> <button onClick={() => { oneCountUp(); oneCountUp(); oneCountUp(); }} > 1 증가 </button> <p>{count}</p> </div> ); }

혹시 공식문서의 https://ko.reactjs.org/docs/faq-state.html#why-is-setstate-giving-me-the-wrong-value 이 부분을 보셨나요? 클래스 컴포넌트로 되어있긴한데 매우 유사한 상황인것 같습니다. 'setState 호출은 비동기적으로 이뤄집니다. 따라서 setState 호출 직후 새로운 값이 state 에 반영될 거라고 믿어서는 안 됩니다.' 라고 적혀있습니다. oneCountUp(); oneCountUp(); oneCountUp(); 이렇게 3번 호출 할 때 순차적으로 호출되고 끝나고 호출되고 끝나고가 아닌 비동기로 이루어져서 전부 현재 상태에서 1을 증가시키게 되는것으로 보입니다. 이걸 수정하려면 oneCountUp함수를 수정해야할 것 같아요 setState함수에는 값 말고 함수를 넘겨줄 수 있습니다. 그리고 함수의 첫번째 인자로 직전 state를 가지고 오게 됩니다. 그래서 아래처럼 변경하면 될 것 같네요 const oneCountUp = () => { setCount((beforeCount) => beforeCount + 1); };

이 질문 바로 가기

Q. react 그리드에서 수정된 부분이 있으면 조회버튼을 눌렀을 때 alert창 띄우기 기능 (useState 비동기 질문)

안녕하세요. react 초보 개발자입니다. 자바스크립트도 처음이라 비동기 관련해서 제 의도와는 다르게 작동할 때마다 당황하는 중입니다🤣 쌩초보임을 감안해 너그럽게 댓글 달아주시면 감사하겠습니다 :) 화면 설명 먼저 드리자면 조회 버튼을 누르면 그리드에 데이터가 뜨고, 데이터를 수정한 후에 저장할 수 있는 화면입니다! 제목과 같이 그리드에서 수정된 부분이 있을 경우에, 저장하지 않고 조회버튼을 누르면 '수정중입니다. 조회를 진행하시겠습니까?' 와 같은 alert창을 띄우는 기능을 구현중에 있습니다. 참고로 그리드는 aggrid 사용중입니다. 1. 우선 변경값 존재여부를 확인하는 변수 isChanged 를 useState로 선언해주었습니다. const [isChanged, setIsChanged] = useState<boolean>(false); 2. 그리드에서 수정된 부분이 있나 체크하는 건 onCellValueChanged 함수를 통해 값이 변경되면 isChanged가 true로 바뀌게 했습니다. const onCellValueChanged = (params: any) => { setIsChanged(true); }; 3. 저장로직에는 setIsChanged(false)가 있습니다. 또한 저장이 제대로 끝난 후에 조회로직을 탑니다. const onClickSave = async () => { // (생략) 저장 로직 // 저장 완료 후 setIsChanged(false); onClickSearch(); } 4. 조회로직에는 isChanged의 값을 확인하고, 변경값이 있다면 alert창이 뜨고, 확인을 누르면 조회를 진행합니다. const onClickSearch = async () => { if (isChanged) { // (생략) 메세지 띄우는 로직. alert창에서 확인을 누르면 조회 진행 setIsChanged(false); } // (생략) 조회 로직 } * 문제점 정상적으로 저장을 한 후에 조회로직을 타는데, isChanged가 false로 변경되기전에 조회로직을 타서 alert창이 뜹니다. 이 문제는 어떻게 해결하는 게 좋을까요..?

질문에 대해 정확하게 이해는 못했습니다. 죄송합니다.ㅜㅜ 추측해보면 setState에서 비동기가 문제가 될것 같습니다. setState를 여러번 실행하더라도 비동기로 동작하면서 값이 순서대로 변하지 않아 원하지 않는 로직대로 동작하지 않을 수 있습니다. 관련 내용: https://careerly.co.kr/qnas/865 해당 부분으로 문제를 해결할 수 있으면 좋겠네요.. 아니라면.. 질문을 좀더 상세히 코드도 올려주시면 감사하겠습니다. :)

외 1개 답변 보러 가기

목록으로
키워드로 질문 모아보기

실무, 커리어 고민이 있다면

새로운 질문 올리기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!