랜덤처럼 보이지만 일관된 색상 지정 방법 : 태그와 아바타 배경색에 활용하기

2025-03-29

프로젝트를 진행하다 보면 태그나 기본 아바타의 색상을 일관성 있게 보여주는 것이 중요해지는 순간이 있습니다. 특히, 백엔드 API에서 별도로 색상 정보를 내려주지 않는 경우에는 프론트 코드에서 색상을 직접 지정해줘야 하는 상황이 생기죠.

최근 Taskify 프로젝트를 진행하면서 비슷한 상황에 마주하게 되었고, 그 해결 과정과 구현 방법을 공유해 보려고 합니다.

문제 상황

  • API에서는 태그나 아바타의 색상을 별도로 저장하거나 내려주지 않음
  • 랜덤 색상 사용 시, 페이지를 새로 고칠 때마다 색상이 달라져 일관성 부족

해결 아이디어

랜덤처럼 보이지만 예측 가능한 방식을 사용

  • 텍스트(예: 태그 이름, 사용자 이름)의 첫 글자를 기준으로 charCodeAt()으로 얻은 10진수 유니코드 값을 가져옵니다.
  • 색상 배열의 길이로 나눈 나머지를 인덱스로 활용해 색상을 결정합니다.
  • 이 방식은 마치 랜덤처럼 보이지만, 항상 같은 입력값에 대해 같은 색상을 반환합니다.

"리액트" → '리' → 10진수 유니코드 값 47196 → 색상 배열 길이 5로 나눈 나머지
→ 47196 % 5 = 1 → 인덱스 1 → 항상 같은 색상

구현 코드

// 1. 사용할 색상 정의
export type HexColor = `#${string}`;

export const DEFAULT_COLORS = [
  '#7AC555', // 연두
  '#760DDE', // 보라
  '#FFA500', // 주황
  '#76A5EA', // 하늘
  '#E876EA', // 핑크
] as const satisfies HexColor[];

export type DEFAULT_COLOR = (typeof DEFAULT_COLORS)[number];

// 2. 문자열을 기반으로 색상 인덱스 계산
export function getColorByString(value: string, colorArray: readonly string[]) {
  const charCode = value.toLowerCase().charCodeAt(0); // 10진수 유니코드 값
  const index = charCode % colorArray.length;
  return colorArray[index];
}

// 3. 사용 예시
const colorCode = getColorByString('리액트', DEFAULT_COLORS);
// 결과: '#760DDE' (항상 같은 값 반환)

이 방식은 항상 같은 입력에 대해 같은 색상을 부여해 일관성을 유지할 수 있고, 별도 저장 없이 간단한 로직으로 구현할 수 있으며, 색상 배열만 관리하면 되기 때문에 유지보수도 편리합니다.