useId는 고유한 아이디를 만들 때 사용하는 react hook이다.

useId를 import로 불러오고
사용할 변수에 담아 호출해 준다.

그래서 그냥 저렇게 사용하면 문자열 형태의 아이디를 하나 반환해 준다.
useId로 만든 아이디는 인풋 같은 폼 요소에서 접근성에 관련된 속성을 제공할 때 정말 유용하게 사용된다.
예) 인풋 요소에 아이디 속성을 제공할 때

input 요소 하나랑, input에 뭐가 들어가는지 명시해 주는 label을 하나가 있다.
하지만 input과 label의 연관성을 현재 코드상으로 명시해주지 않았다.
그렇기 때문에 input과 label은 서로 연관이 없는 개별적인 요소들이다.

input 요소에 id를 하나 추가해 주고 값으로는 "name"이라고 지정해 보겠다.
그리고 label에 htmlFor라는 속성을 하나 넣어주고, input의 id를 그대로 넣어준다.
이렇게 두 요소를 연결 해주면

브라우저에 있는 input 박스를 직접적으로 클릭하지 않아도
label을 클릭해도 input 박스에 포커스가 자동으로 들어오는 걸 볼 수 있다.
일차적으로 접근성이 좋아졌다고 할 수 있다.
그렇다면 재사용이 가능한 컴포넌트를 만드는 게 좋다.

이렇게 다른 파일에 MyInput컴포넌트를 생성하겠다.

그리고 이렇게 다시 App에서 MyInput컴포넌트를 두개 가져와서 넣어주겠다.

그럼 화면에는 이렇게 두 개의 input을 볼 수 있다.
그러나 이렇게 되면 코드에 문제점이 있다.
두 인풋의 아이디가 더 이상 고유하지 않다는 것이다.

개발자 도구로 확인해 보면 이렇게 두 인풋의 아이디가 name으로 같다는 걸 알 수 있다.
같은 페이지 내 중복된 아이디가 있으면 더 이상 어떤 레이블이 어떤 인풋에 해당하는지 알 수 없게 된다.

분명 아래에 있는 레이블을 클릭했는데 위에 인풋에 포커싱이 들어가는 현상이 생긴다.
이 문제를 해결하려면 각각의 아이디에 고유한 아이디를 부여해 주면 된다.
각각의 학생들을 구분하기 위해 이름표를 달아주는 것과 같다!
여기서 useId를 사용하면 된다!!!
react는 고유한 아이디를 만들어 주는 useId라는 훅을 제공한다!

그럼 이제 App 컴포넌트에서 useId부분을 지워주고
MyInput컴포넌트에서 지정해 주겠다.
useId를 각각의 인풋에 id와 htmlFor속성에 넣어주겠다.

두 개의 input에 각자 고유한 아이디가 생성된 걸 확인할 수 있다.
App컴포넌트에 MyInput컴포넌트를 하나만 남기고
MyInput컴포넌트 안에 label과 input이 여러 개 담아야 하는 상황을 만들어보겠다.

이런 식으로 하나의 컴포넌트 안에 여러 개의 input이 있으면 고유한 아이디도 그만큼 더 필요하게 된다.
useId를 input의 개수만큼 만들어 주면 될까?
물론 그 방식도 작동은 가능하지만, input이 100개 필요하면 useid도 100번 가져와야 하니 꽤 비효율적이라는 생각이 든다.
useId를 딱 한 번만 사용해서 고유한 id를 줄 수 있다.
바로 id뒤에 다른 의미있는 문자열을 붙여주는 것이다.

이렇게 이름이 들어가는 input과 label에 id뒤에 name이 들어가게 하고
두 번째 input에는 id 뒤에 age가 들어가도록 했다.
이렇게 하면 useId를 한 번만 선언해서 고유한 아이디를 많이 만들 수 있다.

확인해 보면 input마다 고유한 아이디를 가지는 걸 알 수 있다.
물론 자바스크립트의 Math.random()을 사용해서 고유한 아이디를 만들 수 있다.
또한 uuid같은 라이브러리를 사용하는 방법도 존재한다.
이렇게 여러 가지 방법이 있는데 왜 굳이 react는 useId를 사용하는 걸까?

useId가 만든 id는 항상 저렇게 쌍점을 포함하고 있다.
저 쌍점은 생각보다 흥미로운 일을 한다.

보통 자바스크립트를 사용해 특정한 돔 요소에 접근할 때 쿼리 셀렉터같은 API를 사용한다.
그럼 저렇게 버튼 태그를 하나 만들고 버튼의 id로 'btn'이렇게 지정했다.
그 후 querySelector를 사용해서 button에 접근하도록 했다.
먼저 button이 렌더링 된 후에 코드를 호출할 수 있도록 useEffect를 하나 넣어주고 버튼 요소에 접근했다.

그럼 버튼 요소에 성공적으로 접근한 걸 확인할 수 있다.
그럼 이번에는 button이 아니라 이전에 만든 input요소에 똑같은 방법으로 접근해 보겠다.

그럼 querySelector에게 id를 넣어주겠다.
!!이렇게 해서 실행하면 에러가 난다!!!
에러가 나는 이유는 : 요소의 id에 쌍점이 포함되어 있으면 querySelector같은 API들이 잘 동작하지 않기 때문이다.
그렇기 때문에 에러가 발생한다.
그렇다면 쌍점이 장점인 이유는 react는 이미 ref라는 속성으로 돔 요소에 접근이 가능하다.
그렇기 때문에, react를 사용한다면 굳이 querySelector같은 API를 사용할 필요가 없는 것이다.
만약에 ref를 사용한다면

ref를 하나 만들어주고 가져오고 싶은 input요소에 속성으로 넣어준 다음에 querySelector를 사용하는 게 아니라 ref.current로 접근하겠다.

그럼 잘 불러오는 걸 확인할 수 있다.
이런 의미에서 useId는 아이디에 쌍점을 넣어줌으로써 우리가 react 개발자로서 조금 더 나은 코드를 작성할 수 있도록 도와준다.
만약 useId가 아니라 Math.random을 사용해서 id를 만들면 컴포넌트가 렌더링 될 때마다 id가 새로운 값으로 변경된다.
왜냐면 컴포넌트가 렌더링 된다는 건 컴포넌트 함수가 호출되고 내부에 있는 변수들은 다시 초기화가 되기 때문이다.
이렇게 id가 계속해서 바뀌면 form요소의 id도 계속해서 바뀌기 때문에 스크린 리더를 사용하는 유저들에게 불편함을 줄 수 있다.
반면 useId로 만들어진 id는 컴포넌트에 렌더링이 발생해도 id가 그대로 유지된다.
그렇기 때문에 폼 요소에 있는 id도 그대로 유지가 된다. ===> 훨씬 안정적
서버 사이드 렌더링: 페이지를 서버에서 렌더링 한 후에 클라이언트로 전달하는 방식
클라이언트에서는 받아온 페이지를 하이드레이션이라는 과정을 통해서 상호 작용이 가능한 페이지로 렌더링을 한다.
서버 사이드 렌더링시 서버에서 렌더링된 결과물고 클라이언트에서 렌더링된 결과물이 일치하지 않아서 문제가 발생하는 경우 생김
서버에서 렌더링된 폼 요소의 id값이 클라이언트에서 렌더링 된 폼 요소의 id값과 일치하지 않을 때 문제 발생
useId를 사용하면 서버, 클라이언트 모두 동일한 안정적인 아이디를 생성해주기 때문에 문제를 방지할 수 있다.
결론부터 말하면 아니다.
useId를 공부하면서 key값으로 적절히 사용할 수 있겠다고 생각했지만 , 적합하지 않다고 한다.
그 이유는
useId는 고유한 id를 생성하지만, 컴포넌트 내에서 고유성을 보장한다.
key는 react가 목록을 렌더링하고 항목을 비교할 때 사용된다.
key는 전역적으로 고유해야 한다.
여러 컴포넌트가 인스턴스가 동일한 useId값을 가질 수 있기에, 목록의 항목들 간의 공유성을 보장하지 못할 가능성이 있다.
key는 요소가 재사용될 수 있도록 보장한다.
useId는 각 렌더링 사이에 동일한 값을 유지하나 목록의 항목들이 변경되거나 재정렬될 때 일관성을 유지하지 못할 수 있다.
key는 react가 컴포넌트의 상태를 올바르게 관리하고 업데이트하는데 중요하다.
useId로 생성된 id는 컴포넌트의 인스턴스가 생성될 때마다 동일하게 유지되기 때문에, 컴포넌트가 동적으로 추가되거나 제거될 때 의도하지 않은 동작이 발생할 수 있다.
이러한 점들 참고로 알아두면 좋겠다!