2가지 색상의 그라데이션 색상 그라데이션 단계(스텝)를 계산하는 과정은 시작 색상과 끝 색상의 RGB 값(또는 HSL 등) 사이를 균등한 간격으로 보간(Interpolation)하는 선형 보간법(Linear Interpolation) 공식을 사용한다.

선형 보간 공식 (Linear Interpolation)
2개의 색상 사이에 N 만큼 단계를 나눠 그라이데션 색상값을 구하기 위해 선형 보간법을 사용한다.
Color(t) = C1+ t x (C2 - C1)
- sColor : 시작 색상값
- eColor : 끝 색상값
- t : 진행 비율. 0에서 1 사이의 비율 값.
어떻게 적용할까?
수식은 검색하면 잘 나온다. 그런데, 문제는 어떻게 이 공식이 사용되고, 어떻게 구현해야되는지가 진정한 문제다.
흔히, 색상값을 HEX 값으로 다룰 것이다. 귀찮게 괄호열고 닫고 숫자 3개를 사용하진 않을 것이다. RGB
그러나!
선형 보간 공식을 RGB 값에 각각 사용한다.
R(t) = R1 x (1 - t) + R2 x t
G(t) = G1 x (1 - t) + G2 x t
B(t) = B1 x (1 - t) + B2 x t
구현 전략
1. HEX to RGB
2. 진행 비율 계산
3. 값 구하기
1. HEX to RGB
입력값이 RGB 이면 다음단계로 진행하면 되지만, 자주 사용하는 HEX 값을 기준으로 시작해보자.
(1) 2자리씩 채널 분리
HEX 값이나 RGB 값이나 그냥 텍스트 차이지 Red Green Blue 를 표현하는 순서는 똑같다.
| Hex 입력 | Hex - Red | Hex - Green | Hex - Blue | |
| 색상1 | #0ebeff | 0e | be | ff |
| 색상2 | #ff42b3 | ff | 42 | b3 |
(2) 16진수를 10진수로 변환
HEX는 6자리 코드이며, 16진수로 색상을 표현한다. RGB는 0 ~ 255 로된 3개 숫자로 표현한다.
쉽게말하면 16진수 2자리를 10진수 1자리로 변경해야된다.
16진수 한 자리는 16^0, 16^1 자리수를 가지므로, 2자리 16진수는 0부터 255까지의 값을 표현할 수 있다.
Value = (C1 x 16^1) + (C0 x 16^0)
(3) 직접 계산 해보자
- 시작 색상 : #0ebeff
- Red : 0e
- 16^1 자리 0 = 0 x 16 = 0
- 16^0 자리 e = 14 x 1 = 14
- [16진수] 0 + e = [10진수] 0 + 14 = 14
- Green: be
- 16^1 자리 b = 11 x 16 = 176
- 16^0 자리 e = 14 x 1 = 14
- [16진수] b + e = [10진수] 176 + 14 = 190
- Blue: ff
- 16^1 자리 f = 15 x 16 = 240
- 16^0 자리 f = 15 x 1 = 15
- [16진수] f + f = [10진수] 240 + 15 = 255
- #0ebeff = RGB(14, 190, 255)
- Red : 0e
- 끝 색상 : #ff42b3
- Red: ff
- 16^1 자리 f = 15 x 16 = 240
- 16^0 자리 f = 15 x 1 = 15
- [16진수] f + f = [10진수] 240 + 15 = 255
- Green: 42
- 16^1 자리 4 = 4 x 16 = 64
- 16^0 자리 2 = 2 x 1 = 2
- [16진수] 4 + 2 = [10진수] 64 + 2 = 66
- Blue: b3
- 16^1 자리 b = 11 x 16 = 176
- 16^0 자리 3 = 3 x 1 = 3
- [16진수] b + 3 = [10진수] 176 + 3 = 179
- #ff42b3 = RGB(255, 66, 179)
- Red: ff
(4) 소스코드
Hex 값을 RGB 로 변경하는 함수
function hexToRgb(hex: string): { r: number; g: number; b: number } {
// 1. 앞에 붙은 '#' 기호 제거
const cleanHex = hex.replace('#', '');
// 2. 16진수 문자열을 10진수 정수형 숫자로 변환
const bigint = parseInt(cleanHex, 16);
// 3. 비트 연산자로 R, G, B 채널 추출
const r = (bigint >> 16) & 255; // 오른쪽으로 16비트 밀고 하위 8비트 추출
const g = (bigint >> 8) & 255; // 오른쪽으로 8비트 밀고 하위 8비트 추출
const b = bigint & 255; // 하위 8비트 추출
return { r, g, b };
}
원리를 알았으니 반대로도 할 수 있다.
이 함수는 결과값을 다룰 때 사용하면 된다.
RGB값을 HEX값으로 변경하는 함수
// RGB를 HEX 코드로 변환하는 함수
function rgbToHex(r: number, g: number, b: number): string {
const toHex = (c: number) => {
const hex = Math.round(c).toString(16);
return hex.length === 1 ? '0' + hex : hex;
};
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
2. 진행 비율 계산
진행 비율 t 는 0 ~ 1 사이 소수로 표현한다.
진행 비율 연산은 아래처럼 한다.
t = 1 / (Step + 1)
예를들어, 내가 시작색, 끝색 사이에 1단계가 있다면 t = 0.5 이다.
- 1단계 : 0.5
- 2단계 : 0.333, 0.666
- 4단계 : 0.2, 0.4, 0.6, 0.8
for (let i = 0; i <= steps; i++) {
const t = i / steps;
}
3. 그라데이션 단계별 값 구하기
각 단계별로 "t 진행 비율", R, G, B 값들을 구한다.
- 시작 색상 (#0ebeff)
- Red: 0e ➡️ 14
- Green: be ➡️ 190
- Blue: ff ➡️ 255
- 끝 색상 (#ff42b3)
- Red: ff ➡️ 255
- Green: 42 ➡️ 66
- Blue: b3 ➡️ 179
- 채널별 총 변화량 🔺 = End - Start
- 🔺R = 255 - 14 = 241
- 🔺G = 66 - 190 = -124
- 🔺B = 179 - 255 = -76
직접 계산해보자.
(1) Steps = 1 인 경우
- 진행 비율: t = 1/2 = 0.5
- Step 1
- Red : 14 + (0.5 x 241) = 134.5 ➡️ 135 (HEX: 87)
- Green : 190 + (0.5 x -124) = 128 (HEX: 80)
- Blue : 255 + (0.5 x -76) = 217 (HEX: d9)
- 최종 결과
- #0ebeff
- #8780d9
- #ff42b3
(2) Steps = 2 인 경우
- 진행 비율: t = 1/3 = 0.333, 0.666
- Step 1 (t = 1/3 = 0.333)
- Red : 14 + (0.333 x 241) = 94.2 ➡️ 94 (HEX: 5e)
- Green : 190 + (0.333 x -124) = 148.7 ➡️ 149 (HEX: 95)
- Blue : 255 + (0.333 x -76) = 229.6 ➡️ 230 (HEX: e6)
- Step 2 (t = 2/3 = 0.666)
- Red : 14 + (0.666 x 241) = 174.5 ➡️ 175 (HEX: af)
- Green : 190 + (0.666 x -124) = 107.4 ➡️ 107 (HEX: 6b)
- Blue : 255 + (0.666 x -76) = 204.3 ➡️ 204 (HEX: cc)
- 최종 결과
- #0ebeff
- #5e95e6
- #af6bcc
- #ff42b3
루프에서 t 값과 RGB 각각의 값을 선형 보간법으로 계산 후 HEX로 변경하여 반환한다.
// 그라데이션 단계별 색상 배열을 생성하는 함수
export function generateGradientColors(
startHex: string,
endHex: string,
steps: number
): string[] {
const start = hexToRgb(startHex);
const end = hexToRgb(endHex);
const colors: string[] = [];
// steps가 0 이하일 경우 예외 처리
if (steps <= 0) return [startHex, endHex];
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const r = start.r + t * (end.r - start.r);
const g = start.g + t * (end.g - start.g);
const b = start.b + t * (end.b - start.b);
colors.push(rgbToHex(r, g, b));
}
return colors;
}
몰아보기
// HEX를 RGB 객체로 변환하는 함수
function hexToRgb(hex: string): { r: number; g: number; b: number } {
const cleanHex = hex.replace('#', '');
const bigint = parseInt(cleanHex, 16);
const r = (bigint >> 16) & 255;
const g = (bigint >> 8) & 255;
const b = bigint & 255;
return { r, g, b };
}
// RGB를 HEX 코드로 변환하는 함수
function rgbToHex(r: number, g: number, b: number): string {
const toHex = (c: number) => {
const hex = Math.round(c).toString(16);
return hex.length === 1 ? '0' + hex : hex;
};
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
// 그라데이션 단계별 색상 배열을 생성하는 함수
export function generateGradientColors(
startHex: string,
endHex: string,
steps: number
): string[] {
const start = hexToRgb(startHex);
const end = hexToRgb(endHex);
const colors: string[] = [];
// steps가 0 이하일 경우 예외 처리
if (steps <= 0) return [startHex, endHex];
for (let i = 0; i <= steps; i++) {
const t = i / steps;
const r = start.r + t * (end.r - start.r);
const g = start.g + t * (end.g - start.g);
const b = start.b + t * (end.b - start.b);
colors.push(rgbToHex(r, g, b));
}
return colors;
}
'개발' 카테고리의 다른 글
| 윈도우11 venv 파이썬 가상환경 설치 및 사용 방법 (0) | 2026.08.19 |
|---|---|
| 자바 코틀린 그래들 프로젝트 쉽게 생성하기. 부트스트랩 Gradle Project Starter Gradle Initializr (0) | 2026.04.02 |
| 수도 코드/ 의사코드 / Pseudo Code 작성 프로그램 및 에디터 (0) | 2026.03.25 |
| H2 설정 충돌 AUTO_SERVER vs DB_CLOSE_ON_EXIT (0) | 2026.02.19 |
| BaseEntity 구현 전략 (0) | 2026.02.13 |