Shader(셰이더)는 GPU에서 실행되어 정점, 프래그먼트 또는 계산 작업과 같은 그래픽 데이터를 처리하는 프로그램입니다. CPU의 일반 코드와 달리 셰이더는 수백 개의 코어에서 병렬로 작동하며 각 요소를 독립적으로 처리합니다. Khronos Group(2025년)에 따르면 셰이더는 모바일 게임부터 시스템 애플리케이션의 UI 효과까지 최신 3D 애플리케이션의 100%에서 사용됩니다. 개발자는 GLSL, HLSL, Metal Shading Language 또는 SPIR-V와 같은 전문 언어로 셰이더를 작성합니다.
주요 포인트
Shader(셰이더)는 전문 언어로 작성되어 GPU에서 실행되는 작은 프로그램입니다. 각 셰이더는 정점, 프래그먼트(픽셀) 또는 작업 항목이라는 하나의 데이터 요소를 다른 요소와 독립적으로 처리합니다. GPU의 병렬 처리를 통해 수천 개의 셰이더 인스턴스를 동시에 실행할 수 있습니다.
이 용어는 1980년대 Pixar가 RenderMan에서 표면의 외관을 제어하는 프로그램을 설명하기 위해 도입했습니다. 실시간 셰이더는 프로그래머블 파이프라인을 갖춘 최초의 그래픽 카드인 NVIDIA GeForce 3(2001년)와 함께 등장했습니다. 셰이더 이전에는 그래픽이 색상, 텍스처, 블렌드 모드와 같은 고정 매개변수로 구성되었습니다.
Unity Technologies(2025년)에 따르면 평균적인 모바일 게임은 50~200개의 셰이더를 사용합니다. 각 셰이더는 다양한 플랫폼, 품질 수준 및 조명 구성을 위한 변형(variants)이 있습니다. 변형 수는 프로젝트당 10,000개에 달할 수 있습니다.
셰이더 아키텍처는 입력 데이터(속성, uniform 변수, 텍스처), 프로그램 코드 및 출력 데이터(색상, 위치)로 나뉩니다. Uniform 변수는 셰이더 실행 전에 CPU에서 설정되며 프레임의 모든 요소에 대해 변경되지 않습니다. 속성은 요소별 데이터(정점 좌표, 법선, UV 좌표)입니다.
SIMT(Single Instruction, Multiple Threads)는 GPU에서 셰이더의 실행 모델입니다. 하나의 명령어가 한 번 로드되어 서로 다른 데이터에 대해 수백 개의 스레드에서 실행됩니다. 예를 들어 1000픽셀에 대한 Fragment Shader는 동일한 코드를 가진 1000개의 스레드를 실행하지만 각 스레드는 고유한 UV 좌표와 보간된 속성을 받습니다.
SIMT의 중요한 결과: 셰이더의 분기는 비용이 많이 듭니다. if 블록 내에서 절반의 스레드가 한 분기를 따르고 나머지 절반이 다른 분기를 따르는 경우 GPU는 모든 스레드에 대해 두 분기를 순차적으로 실행합니다. 성능이 50%로 떨어집니다. 셰이더에서 동적 분기를 피하거나 CPU에서 사전 계산을 통해 최소화하세요.
최신 GPU는 그래픽 또는 컴퓨트 파이프라인의 각 단계에 해당하는 여러 유형의 셰이더를 지원합니다. 주요 유형인 버텍스, 프래그먼트, Compute 및 최신 Mesh 셰이더를 살펴보겠습니다.
| 셰이더 유형 | 파이프라인 단계 | 처리 내용 | 언어 |
|---|---|---|---|
| Vertex Shader | 버텍스 | 각 정점 | GLSL, HLSL |
| Fragment Shader | 프래그먼트 | 각 픽셀 | GLSL, HLSL |
| Compute Shader | 컴퓨트 | 임의 데이터 | GLSL, HLSL |
| Geometry Shader | 지오메트리 | 프리미티브 | GLSL, HLSL |
| Tessellation Shader | 테셀레이션 | 패치 | GLSL, HLSL |
| Mesh Shader | Mesh 파이프라인 | Task + Mesh | HLSL, MSL |
Vertex Shader는 지오메트리의 각 정점을 처리합니다: 좌표 변환, 조명 계산, 프래그먼트 셰이더로 데이터 전달. 이는 그래픽 파이프라인의 필수 단계로, 이것 없이는 정점이 화면에 표시되지 않습니다. Vertex Shader는 각 프레임의 각 정점에 대해 호출됩니다.
Fragment Shader(또는 Pixel Shader)는 가장 리소스를 많이 소비하는 단계입니다. 텍스처, 조명 및 재질을 사용하여 각 프래그먼트의 최종 색상을 계산합니다. Fragment Shader는 적용된 모든 텍스처와 효과를 고려하여 지오메트리로 덮인 각 픽셀에 대해 실행됩니다. 이 셰이더의 최적화가 가장 큰 성능 향상을 제공합니다.
Compute Shader는 GPU에서 임의의 계산을 위한 범용 셰이더입니다. 그래픽 셰이더와 달리 지오메트리나 픽셀에 묶이지 않습니다. Compute Shader는 작업 그룹을 통해 임의의 데이터 버퍼로 작업합니다. 물리 시뮬레이션, 입자 시뮬레이션, 후처리 효과 및 신경망 추론에 사용됩니다.
Mesh Shader는 NVIDIA Turing(2018년)과 Metal 3에서 등장한 최신 셰이더 유형입니다. Mesh Shader는 버텍스, 지오메트리 및 테셀레이션 셰이더를 단일 메시 파이프라인으로 대체합니다. Task Shader와 함께 작동합니다: Task Shader는 렌더링할 메시 그룹을 결정하고 Mesh Shader는 실시간으로 지오메트리를 생성합니다.
셰이더는 GPU 머신 코드로 컴파일되는 전문 언어로 작성됩니다. 언어 선택은 플랫폼과 API에 따라 달라집니다. 주요 언어인 GLSL, HLSL, Metal Shading Language 및 중간 형식인 SPIR-V를 살펴보겠습니다.
GLSL은 OpenGL, OpenGL ES 및 WebGL을 위한 셰이더 언어입니다. 구문은 C를 기반으로 하며 벡터 유형(vec2, vec4, mat4)과 내장 함수(texture, normalize, reflect)가 추가되었습니다. GLSL ES는 모바일 장치용으로 정밀도가 제한된 버전입니다(lowp, mediump, highp). Khronos(2025년)에 따르면 GLSL은 크로스 플랫폼 특성 덕분에 가장 널리 사용되는 셰이더 언어입니다.
#version 300 es
precision mediump float;
in vec2 v_texCoord;
uniform sampler2D u_texture;
out vec4 fragColor;
void main() {
fragColor = texture(u_texture, v_texCoord);
}
간단한 프래그먼트 셰이더는 UV 좌표로 텍스처에서 색상을 읽습니다. precision mediump은 GPU에 float에 대해 절반 정밀도를 사용하도록 지시하여 모바일 장치에서 실행 속도를 25~40% 향상시킵니다.
HLSL은 Microsoft의 DirectX용 셰이더 언어입니다. 구문은 C++에 가깝고 클래스, 구조체 및 템플릿을 지원합니다. HLSL은 Windows 애플리케이션에서 사용되며 Shader Model 6.7+부터 Ray Tracing, Mesh Shaders 및 Sampler Feedback을 지원합니다. 모바일 개발에서는 HLSL이 직접 사용되지 않지만 Vulkan용 SPIR-V로 컴파일됩니다.
MSL(Metal Shading Language)은 Apple의 셰이더 언어로 C++14를 기반으로 합니다. GLSL 및 HLSL과 달리 MSL은 애플리케이션과 함께 컴파일되어 장치에서 JIT 컴파일이 필요하지 않습니다. MSL은 포인터, 템플릿 및 C++ 표준 라이브러리를 지원합니다. iPhone, iPad, Mac, Apple TV 등 모든 Apple 장치에서 사용됩니다.
#include <metal_stdlib>
using namespace metal;
struct VertexOut {
float4 position [[position]];
float2 texCoord;
};
fragment float4
myFragment(VertexOut in [[stage_in]],
texture2d<float> tex [[texture(0)]]) {
constexpr sampler s = sampler(filter::linear);
return tex.sample(s, in.texCoord);
}
MSL은 [[position]], [[stage_in]] 및 [[texture(N)]] 속성을 사용하여 리소스를 바인딩합니다. Apple 컴파일러는 레지스터 수와 캐시를 고려하여 현재 GPU에 최적화된 코드를 생성합니다.
SPIR-V는 Vulkan의 표준 중간 바이너리 셰이더 형식입니다. 셰이더는 GLSL 또는 HLSL로 작성되어 SPIR-V로 컴파일된 후 Vulkan 애플리케이션에 로드됩니다. SPIR-V는 특정 언어에 묶이지 않으며 Rust, Python, OpenCL C에서 SPIR-V로의 컴파일러도 존재합니다.
모바일 플랫폼의 셰이더는 데스크톱에 비해 제한이 있습니다: 레지스터가 적고 정밀도가 제한되며 일부 명령어가 지원되지 않습니다. Android(Vulkan/OpenGL ES)와 iOS(Metal)에서 셰이더의 특성을 살펴보겠습니다.
Android는 OpenGL에 GLSL ES를, Vulkan에 SPIR-V를 사용합니다. OpenGL ES 3.2는 기본적으로 mediump의 셰이더를 지원합니다. Vulkan은 glslangValidator를 통해 GLSL에서 SPIR-V로의 명시적 컴파일이 필요합니다. Android에서 셰이더는 문자열 리소스 또는 컴파일된 SPIR-V 파일에서 로드됩니다.
Qualcomm Adreno GPU는 드라이버 수준에서 셰이더를 최적화합니다. 권장 사항: 색상과 UV에는 mediump를, 위치에만 highp를 사용하고 버텍스 셰이더에서 텍스처 샘플링을 피하며 계산을 벡터로 그룹화합니다(4x float 대신 vec4). Qualcomm(2025년)에 따르면 이러한 최적화로 30~50%의 향상을 얻을 수 있습니다.
iOS는 전적으로 Metal Shading Language를 사용합니다. 셰이더는 Xcode를 통해 애플리케이션과 함께 머신 코드로 컴파일됩니다. Metal은 셰이더 프로파일링을 위한 Shader Debugger와 GPU Capture를 제공합니다. Apple GPU(TBDR)에는 early fragment test, memoryless render targets 및 programmable blending과 같은 특정 최적화가 있습니다.
Apple WWDC 2024에 따르면 iOS 셰이더의 경우 float 대신 half를 사용하고 레지스터 압력을 제한하며(최대 64레지스터) 종속 텍스처 샘플링을 피하는 것이 중요합니다. iOS 셰이더는 컴팩트해야 하며 이상적인 크기는 50~100 ALU 명령어입니다.
게임 엔진 Unity와 Unreal Engine은 비주얼 셰이더 편집기(Shader Graph, Material Editor)와 추상 언어(ShaderLab, USF)를 제공합니다. 개발자는 고수준 언어로 셰이더를 작성하고 엔진이 대상 플랫폼용으로 컴파일합니다. Unity는 중간 언어로 HLSL을, Unreal은 USF(Unreal Shader Format)를 사용합니다.
셰이더 최적화는 모바일 장치용 그래픽 개발의 핵심 단계입니다. 잘못 작성된 셰이더는 FPS를 60에서 20으로 떨어뜨릴 수 있습니다. 주요 최적화 규칙과 기술을 살펴보겠습니다.
필요한 최소 정밀도를 사용합니다: 색상과 UV에는 lowp, 법선과 조명에는 mediump, 위치와 행렬에만 highp를 사용합니다. ARM(2025년)에 따르면 Mali GPU에서 mediump 연산은 highp보다 2배 빠릅니다. GLSL ES에서는 precision 한정자를 통해 설정됩니다.
텍스처 샘플링은 셰이더에서 가장 비용이 많이 드는 작업입니다(ALU 명령어의 1~2사이클 대비 10~30사이클). 샘플링 수를 줄이려면 텍스처를 아틀라스로 결합하고 텍스처 대신 uniform 배열에 데이터를 저장하며 미분 명령어를 통해 인접 픽셀의 결과를 캐시합니다.
동적 분기(uniform 변수를 사용한 if문)는 SIMT 파이프라인의 성능을 저하시킵니다. 분기를 수학 함수로 대체합니다: mix(), step(), smoothstep() 및 clamp(). 이러한 함수는 1~2 명령어로 실행되는 반면 분기는 스레드 발산으로 인해 8~16 명령어가 소요될 수 있습니다.
// 나쁨: 셰이더의 동적 분기
if (u_enableLight) {
color *= computeLighting(normal);
}
// 좋음: 수학적 분기 대체
color *= mix(1.0, computeLighting(normal),
float(u_enableLight));
mix()는 두 값 사이에서 선형 보간을 수행합니다. u_enableLight=0이면 1.0을 반환하여 색상이 변경되지 않습니다. u_enableLight=1이면 조명 결과를 반환합니다. 분기 없음 — 모든 스레드가 동일한 코드를 실행합니다.
모바일 개발을 위한 실용적인 셰이더 예제를 살펴보겠습니다 — 단순한 셰이딩부터 절차적 텍스처 생성까지. 각 예제는 특정 기술을 보여줍니다.
퐁 모델은 확산 및 반사 구성 요소를 가진 고전적인 조명 모델입니다. Vertex Shader가 각 정점의 조명을 계산하고 Fragment Shader는 결과를 보간만 합니다(Gouraud 셰이딩). 비용이 낮아 모바일 장치에 적합합니다.
#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec3 a_normal;
uniform mat4 u_mvp;
uniform mat4 u_modelView;
out vec3 v_color;
void main() {
vec3 normal = normalize(mat3(u_modelView) * a_normal);
vec3 lightDir = normalize(vec3(0.0, 1.0, 1.0));
float diff = max(dot(normal, lightDir), 0.0);
v_color = vec3(0.8, 0.2, 0.2) * (0.3 + diff * 0.7);
gl_Position = u_mvp * a_position;
}
셰이더는 확산 조명을 계산합니다: 법선과 광원 방향의 내적. 결과는 주변광(0.3)과 확산광(0.7) 구성 요소와 혼합됩니다. 정점당 10~15 ALU 명령어 — 모바일 GPU에서 60FPS로 100,000 폴리곤에 적합합니다.
절차적 텍스처는 파일에서 로드하지 않고 Fragment Shader에서 생성됩니다. 비디오 메모리를 절약하고 애니메이션을 단순화합니다. 예제 — 셀 크기를 변경할 수 있는 체커보드. 단 몇 개의 ALU 명령어 — GPU에 최소한의 부하를 줍니다.
#version 300 es
precision mediump float;
in vec2 v_uv;
uniform float u_cells;
out vec4 fragColor;
void main() {
vec2 cell = floor(v_uv * u_cells);
float isWhite = mod(cell.x + cell.y, 2.0);
fragColor = mix(vec4(0.1, 0.1, 0.1, 1.0),
vec4(0.9, 0.9, 0.9, 1.0),
isWhite);
}
8개의 ALU 명령어 — 모바일 장치에 이상적인 셰이더입니다. u_cells는 축당 셀 수를 지정합니다. floor와 mod는 저렴한 연산으로 모든 모바일 GPU에서 1사이클에 실행됩니다.
자주 묻는 질문
셰이더는 SIMT 모드로 GPU에서 실행됩니다 — 하나의 명령어가 수백 개의 스레드에서 실행됩니다. C++ 일반 프로그램은 MIMD 모드로 CPU에서 실행됩니다. 셰이더는 파일 시스템, 입출력 및 동적 메모리에 접근할 수 없습니다. 버퍼와 텍스처를 통해 데이터를 받아 위치나 색상을 반환합니다.
GLSL — OpenGL ES와 WebGL용, 크로스 플랫폼. Metal Shading Language — iOS용. HLSL — Unity와 Unreal Engine의 기초. GLSL부터 시작하세요 — 기초 이해는 모든 셰이더 언어에 적용됩니다.
주요 원인: 높은 정밀도(mediump 대신 highp), 과도한 텍스처 샘플링, 동적 분기 및 레지스터 제한 초과. 셰이더 분석에는 RenderDoc 또는 Xcode GPU Frame Debugger를 사용하세요.
Compute Shader는 GPU에서 임의의 계산을 위한 셰이더입니다: 입자 물리, 이미지 처리, 직물 시뮬레이션. Fragment Shader와 달리 픽셀에 묶이지 않고 임의의 버퍼에 쓸 수 있습니다.
네, 비주얼 편집기를 통해 가능합니다: Unity의 Shader Graph, Unreal Engine의 Material Editor 또는 Metal Shader Converter. 이들은 노드 기반 스키마에서 셰이더 코드를 생성합니다. 심층 최적화를 위해서는 셰이더 언어에 대한 이해가 필요합니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.