개인적인 프로젝트를 하다가 다음과 같은 상황에서는 react 는 어떻게 할 수 있을까 다음 상황은 아래와 같다
상황
1
2
3
1. 요소는 input 과 button 이 존재함
2. button 을 클릭할 시 input 의 focus 상태가 되어야 함
그럼 일단 react 로 하기 전에 위와 같은 내용을 바닐라 자바 스크립트로 한번 만들어보자
바닐라 자바스크립트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<head>
</head>
<body>
<input id = "input_id" type = "text">
<button id = "button_id" >input 포커스주기</button>
</body>
<script type="text/javascript">
const input_dom = document.querySelector("#input_id")
const btn_dom = document.querySelector("#button_id");
btn_dom.addEventListener('click' , (e) => {
input_dom.focus();
})
</script>
스크립트만 보면 각각의 id 를 명명하고 버튼에 대한 클릭 이벤트로 input focus 를 주면되는것이다
그럼 이번엔 같은 이벤트를 리액트로 한번 구현을 해보자
React
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import React, { useRef } from "react";
function Hook1(props){
const inputRef = useRef(null);
const btn_onClick = () => {
inputRef.current.focus();
}
return (
<div>
<input ref = {inputRef} type="text"></input>
<button onClick={btn_onClick}>input 포커스주기</button>
</div>
)
}
export default Hook1;
react 는 DOM 태그의 직접적인 접근은 지양하느 편입니다 그럼 이와 같은 상황에서는 useRef 훅을 사용해서 다른 DOM 을 조작하게 됩니다 지금처럼 조작할려는 DOM 에 ref 를 명시해두고 해당 변수를 useRef 로 선언을 해줍니다 그리고 버튼을 클릭할때 inputRef.current.focus();
이렇게 함으로서 DOM 을 직접 접근을 하지 않은 채로 DOM 을 할 수 있습니다
둘의 차이점?
이렇게만 보면 이 둘의 차이점은 크게 효용이 들지 않는다 그래도 이 둘의 차이점을 각각의 언어의 관점으로 한번 보겠습니다
바닐라 자바스크립트
장점
직접적인 접근 - DOM 요소에 개발자가 직접 접근해서 DOM 을 컨트롤합니다
간단한 코드 - 코드만 보면 해당 코드가 무엇을 하는지 바로 알 수 있습니다
단점
직접적인 접근 - 이는 장점이자 단점입니다 여러곳에서 접근시 매 페이지마다 DOM 을 접근할 수 있는 querySelector 가 필요합니다
상태관리의 어려움 - 마찬가지로 여러곳에서 접근할 때 상태에 관한 관리가 어렵습니다
React
장점
- 간접적 접근 - useRef 로 인해서 DOM 요소에 개발자가 직접 접근하지 않아도 됩니다 이는 다른 여러곳에서 참조되어도 DOM 상태에 관한 일괄적인 상태 관리가 됩니다
단점
- 어려운 코드 - 코드만 봐서는 해당 코드가 무엇을 하는지 알 수 없다 어느정도 선지식이 필요함 , React 의 라이프사이클에 대한 이해가 필요함
직접적인 DOM 접근
위에서 계속해서 언급되는 말이 있다 직접적인 DOM 접근 왜 react 에서는 이를 지양하는지 알아볼려고 합니다 예를 들어서 버튼을 클릭해서 클릭수를 보여주는 html 화면을 각각 먼저 만들어보겠습니다
바닐라 자바 스크립트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<head>
</head>
<body>
<h2 id = "h2_id">클릭수 : 0 </h2>
<button id = "button_id" >input 포커스주기</button>
</body>
<script type="text/javascript">
const h2_dom = document.querySelector("#h2_dom");
const btn_dom = document.querySelector("#button_id");
let count = 0;
btn_dom.addEventListener('click' , (e) => {
count += 1;
h2_id.innerText = `클릭수 ${count}`;
})
</script>
마찬가지로 스크립트만 보겠습니다 현재 두개의 DOM 에 접근해서 클릭할때마다 count 를 늘려주고 그 count 를 지정한 DOM 에 렌더링 하고 있습니다 이 코드만 보면 정말 직관적입니다 무엇을 하는지 정확히 알 수 있습니다 다만 문제점은 개발자가 비즈니스 로직 뿐만아니라 이후 화면 렌더링까지 신경을 써야 하는 문제점입니다 현재 코드는 선형적으로 이어져 있습니다
버튼을 클릭 -> count 값 증가 -> 표기해야 할 텍스트 생성 -> 타겟 DOM 에 접근 및 렌더링
즉 개발자가 비즈니스 로직부터 html 렌더링 까지 모든것을 선형적으로 관리하게 됩니다 이는 코드의 역활이 명확하고 누구든지 약간의 시간만 들인다면 충분히 따라갈 수 있는 코드입니다
반면에 react 를 보겠습니다
React
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React, { useRef, useState } from "react";
function Hook2(props){
const [count , setCount] = useState(0);
const btn_onClick = () => {
setCount(previousCount => previousCount + 1)
}
return (
<div>
<h2>클릭수 : {count} </h2>
<button onClick={btn_onClick}>input 포커스주기</button>
</div>
)
}
export default Hook2;
버튼을 클릭 -> count 값 증가
개발자가 해야 하는것은 count 값 증가입니다 이 이후 DOM 렌더링은 react 에게 맡기는 것입니다 위의 직접적인 상태관리와는 다르게 react 는 개발자가 비즈니스 로직만 만들어두면 react 가 해당 DOM 을 적절한 시기에 렌더링을 하기 때문에 개발자는 오로지 비즈니스 로직만 신경을 쓰면됩니다 이 같은 경우는 비선형입니다
UseRef Hook 에 대해서 공부를 하다가 자바 스크립트 와 비교하는 글을 한번 적어보았습니다