아이디에 고유 값 주기

코래블러·2020년 12월 12일
5

React

목록 보기
1/2
post-custom-banner

위스타그램에서 댓글 추가, 삭제 기능을 구현하다가 보니, id 값을 인덱스처럼 쓰던 것이 문제점이 되어 돌아왔다. 즉, id 값에 고유값을 줘야 했다.

이를 해결할 몇가지 방법을 생각해보았다.

  • 댓글이 추가/삭제 될 때마다 전체 배열을 렌더링시키고, 이때 각각의 id값에 순서대로 인덱스를 부여해준다. 이렇게 하면 id로서의 유니크함, 그리고 인덱스로서의 의미도 동시에 지닌다. (feat. 장현님)

    이 방법은 유효한 방법이긴 하다. 하지만 내 개인적으로 비효율적이라고 생각을 한다. react 의 장점이 두 렌더링 사이에서 변화한 부분은 바꾸고 나머지는 그대로 적용한 다는 것인데, 이렇게 되면 변하지 않는 부분들도 재렌더링 하게 되면서 성능에 악영향을 끼치게 된다는 것이다.

  • id 값에 줄 고유값으로 Math.random() 을 쓰는 법

    : 실제로 써 봤고, 작동도 잘 한다. 사실 렌더할 때 마다 넣지만 않으면 uuid() 쓰는 거랑 별 차이 없는 듯하지만, 어쨌든 고유의 값으로 주기에는 적합하지 않다.

    Math.random()은 암호학적으로 안전한 난수를 제공하지 않으므로, 보안과 관련된 어떤 것에도 이 함수를 사용해서는 안 된다. 그 대신 Web Crypto API의 window.crypto.getRandomValues() 메소드를 이용하여야 한다.

    <출처 : MDN>

    key는 반드시 변하지 않고, 예상 가능하며, 유일해야 합니다. 변하는 key(Math.random()으로 생성된 값 등)를 사용하면 많은 컴포넌트 인스턴스와 DOM 노드를 불필요하게 재생성하여 성능이 나빠지거나 자식 컴포넌트의 state가 유실될 수 있습니다.

    <출처 : React 공식 문서>

    // 나의 경우에는 id 에 Math.random() 으로 난수를 할당하는 거라 문제가 없을 수도 있다. react는 key 값으로 판단을 하기 떄문에. 하지만 react 공식문서가 얘기 하는 요점은 결국 고유 값을 주는 목적으로는 적절하지 않다는 것이다

그럼 도대체 어떻게 짜야 하는가?

2 가지 방법을 생각했다.

1. UUID

  • UUID 란?

    개발주체가 스스로 이름을 짓도록 하되 고유성을 충족할 수 있는 방법이 필요하다. 이를 위하여 탄생한 것이 범용고유식별자(UUID)이며 국제기구에서 표준으로 정하고 있다.

    UUID 표준에 따라 이름을 부여하면 고유성을 완벽하게 보장할 수는 없지만 실제 사용상에서 중복될 가능성이 거의 없다고 인정되기 때문에 많이 사용되고 있다.

    <출처 : https://ko.wikipedia.org/wiki/%EB%B2%94%EC%9A%A9_%EA%B3%A0%EC%9C%A0_%EC%8B%9D%EB%B3%84%EC%9E%90 >

  • 형식

    • 16 옥텟(128비트)의 수로 32개의 16진수로 표현 - 36개의 문자로 이루어짐

    ex) 550e8400-e29b-41d4-a716-446655440000

    Math.random() 이랑 뭐가 다르냐라고 생각할 수 있지만, UUID 는 기원후 3500년 까지는 겹칠 확률이 0에 수렴하기에, 상관 없다. Math.random() 을 사용한 의도로 사용해도 무방

  • 사용법 ( react 에서! )

    1. VScode terminal 에서 다음을 입력

      npm i react-uuid

    2. 파일안에서 uuid import 하기

      import React from "react"

      import uuid from "react-uuid"

      addingComment = (username, text) => {

      this.setState({

      comments: [...this.state.comments, { id: uuid(), username, text }],

      });

      };

2. 마지막 댓글의 id 값에 +1 하기

addingComment = (username, text) => {

const newComments = [...this.state.comments, { id: this.state.comments[comments.length].id + 1 , username, text }];

this.setState({

comments: newComments,

});

};

이 방법이면 추가/삭제시 id 값이 고유하게 할당됨과 동시에, 순서의 의미도 지니게 된다. 댓글의 추가/삭제 기능을 구현할 때에는, 순서의 의미도 살리면 관리하기가 편하기에, 이 방법이 매우 좋다고 생각한다.

profile
언제나 한 발짝만 더...!
post-custom-banner

2개의 댓글

comment-user-thumbnail
2020년 12월 13일

오호 마지막 댓글 id에 + 1 을 하는 건 정말 생각지도 못한 기발한 아이디어네요! ㄴㅇㄱ

답글 달기
comment-user-thumbnail
2021년 10월 25일

https://medium.com/blackrock-engineering/5-common-mistakes-with-keys-in-react-b86e82020052
[2]에서 Math.Random 혹은 UUID 모두를 지양하라 말하고 있고
https://reactjs.org/docs/reconciliation.html
[Reconciliation] 에서는 배열이 reorder 되는 경우에 키값으로 사용하는 것을 지양하라 합니다 ..
아마 id + 1 로 사용하시는 컴포넌트는 reorder 되는 것 같고, 따라서 정확한 키가 아닌 것 같습니다 ..

다른 아이디어가 없을까요?

답글 달기