[2026] Complete Guide to Image Formats | JPEG·PNG·GIF·WebP·AVIF·SVG Comparison
이 글의 핵심
Comprehensive guide to image formats used in web and apps: JPEG, PNG, GIF, WebP, AVIF, SVG. Learn compression methods, transparency, animation support, optimal use cases, and conversion techniques.
What is an Image Format?
An image format is a file type that defines how digital images are stored and transmitted. Each format differs in compression method, color depth, transparency support, and animation capabilities. Choosing the right format for your use case is crucial for optimal performance and quality.
Major Image Format Comparison
1. JPEG (Joint Photographic Experts Group)
Characteristics
- Compression: Lossy Compression
- Transparency: Not supported
- Animation: Not supported
- Color Depth: 24-bit (16.7 million colors)
- File Extensions:
.jpg,.jpeg
Compression Principle
JPEG uses DCT (Discrete Cosine Transform) and quantization. 아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
graph LR
A[Original Image] --> B["Color Space\nRGB → YCbCr"]
B --> C[8x8 Block Division]
C --> D[DCT Transform]
D --> E["Quantization\nRemove High Freq"]
E --> F[Huffman Encoding]
F --> G[JPEG File]
Advantages
- Small file size, efficient for web transmission
- Ideal for photos and complex color gradients
- Universal platform support
Disadvantages
- Quality loss from lossy compression
- No transparency support
- Artifacts on text and sharp edges
Optimal Use Cases
- Photographs, landscapes, portraits
- Complex colors and gradients
- Web images where file size matters
Practical Examples
JPEG Compression in Node.js 다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
async function compressJPEG(inputPath, outputPath, quality = 80) {
await sharp(inputPath)
.jpeg({
quality: quality,
progressive: true, // Progressive JPEG
mozjpeg: true // mozjpeg optimization
})
.toFile(outputPath);
console.log(`✅ JPEG compression complete: ${outputPath}`);
}
// Usage example
compressJPEG('photo.png', 'photo.jpg', 85);
Reading JPEG Metadata in Python 다음은 python를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 함수를 통해 로직을 구현합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
from PIL import Image
from PIL.ExifTags import TAGS
def read_jpeg_metadata(image_path):
img = Image.open(image_path)
# Extract EXIF data
exif_data = img._getexif()
if exif_data:
metadata = {}
for tag_id, value in exif_data.items():
tag = TAGS.get(tag_id, tag_id)
metadata[tag] = value
print(f"Camera: {metadata.get('Model', 'N/A')}")
print(f"Date: {metadata.get('DateTime', 'N/A')}")
print(f"ISO: {metadata.get('ISOSpeedRatings', 'N/A')}")
print(f"Resolution: {img.size}")
return metadata
# Usage example
read_jpeg_metadata('photo.jpg')
2. PNG (Portable Network Graphics)
Characteristics
- Compression: Lossless Compression
- Transparency: Alpha channel support (8-bit transparency)
- Animation: Not supported (except APNG)
- Color Depth: 24-bit (RGB) or 32-bit (RGBA)
- File Extensions:
.png
Compression Principle
PNG uses the DEFLATE algorithm (LZ77 + Huffman). 아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
graph LR
A[Original Image] --> B["Filtering\nNone/Sub/Up/Average/Paeth"]
B --> C["LZ77 Compression\nRemove Duplicates"]
C --> D[Huffman Encoding]
D --> E[PNG File]
Advantages
- Lossless compression maintains original quality
- Transparency support (alpha channel)
- Ideal for text, logos, and icons
- Preserves sharp edges
Disadvantages
- Larger file size than JPEG
- Inefficient for photographs
- No animation support (except APNG)
Optimal Use Cases
- Logos, icons, UI elements
- Images requiring transparent backgrounds
- Screenshots, diagrams
- Images with text
Practical Examples
PNG Optimization in Node.js 다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
async function optimizePNG(inputPath, outputPath) {
await sharp(inputPath)
.png({
compressionLevel: 9, // Maximum compression (0-9)
palette: true, // Palette mode (≤256 colors)
quality: 100, // Lossless
effort: 10 // Maximum effort (1-10)
})
.toFile(outputPath);
const inputStats = await sharp(inputPath).metadata();
const outputStats = await sharp(outputPath).metadata();
console.log(`✅ PNG optimization complete`);
console.log(` Size reduction: ${inputStats.size} → ${outputStats.size} bytes`);
}
// Usage example
optimizePNG('logo.png', 'logo-optimized.png');
Creating Transparent PNG 다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
async function createTransparentPNG(width, height, outputPath) {
await sharp({
create: {
width: width,
height: height,
channels: 4,
background: { r: 0, g: 0, b: 0, alpha: 0 } // Fully transparent
}
})
.png()
.toFile(outputPath);
console.log(`✅ Transparent PNG created: ${width}x${height}`);
}
// Usage example
createTransparentPNG(800, 600, 'transparent.png');
3. GIF (Graphics Interchange Format)
Characteristics
- Compression: Lossless compression (LZW)
- Transparency: 1-bit transparency (fully transparent or opaque)
- Animation: Supported
- Color Depth: 8-bit (256 colors)
- File Extensions:
.gif
Compression Principle
아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
graph LR
A[Original Image] --> B["Color Palette\nReduce to 256 colors"]
B --> C[LZW Compression]
C --> D["Frame Combination\nAnimation"]
D --> E[GIF File]
Advantages
- Animation support
- Simple transparency support
- Wide browser compatibility
- Suitable for small icons and simple animations
Disadvantages
- 256-color limitation, unsuitable for photos
- No semi-transparency (only fully transparent or opaque)
- Large file size for animations
- Poor compression efficiency
Optimal Use Cases
- Simple animations (loading spinners, emoticons)
- Pixel art
- Small icons (≤256 colors)
Practical Examples
Creating Animated GIF in Node.js 다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const GIFEncoder = require('gifencoder');
const { createCanvas } = require('canvas');
const fs = require('fs');
function createAnimatedGIF(outputPath, width = 200, height = 200) {
const encoder = new GIFEncoder(width, height);
const stream = fs.createWriteStream(outputPath);
encoder.createReadStream().pipe(stream);
encoder.start();
encoder.setRepeat(0); // 0 = infinite loop
encoder.setDelay(100); // Frame delay (ms)
encoder.setQuality(10); // 1-20, lower = better quality
const canvas = createCanvas(width, height);
const ctx = canvas.getContext('2d');
// Generate 10 frames
for (let i = 0; i < 10; i++) {
ctx.fillStyle = `hsl(${i * 36}, 100%, 50%)`;
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = 'white';
ctx.font = '30px Arial';
ctx.fillText(`Frame ${i + 1}`, 50, 100);
encoder.addFrame(ctx);
}
encoder.finish();
console.log(`✅ GIF created: ${outputPath}`);
}
// Usage example
createAnimatedGIF('animation.gif');
4. WebP
Characteristics
- Compression: Both lossy and lossless supported
- Transparency: Alpha channel support (8-bit)
- Animation: Supported
- Color Depth: 24-bit (RGB) or 32-bit (RGBA)
- File Extensions:
.webp - Browser Support: Chrome, Firefox, Edge, Safari 14+ (96%+)
Compression Principle
WebP applies VP8/VP9 video codec technology to images. 아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
graph LR
A[Original Image] --> B{Compression Mode}
B -->|Lossy| C["VP8 Intra Frame\nPrediction + DCT"]
B -->|Lossless| D["LZ77 + Huffman\n+ Predictive Coding"]
C --> E[WebP File]
D --> E
Advantages
- 25-35% smaller file size than JPEG
- 26% smaller lossless compression than PNG
- Supports both transparency and animation
- Choice between lossy/lossless
Disadvantages
- Longer encoding time than JPEG
- Limited support in older browsers (IE, Safari 13-)
- Limited support in image editing tools
Optimal Use Cases
- All website images (photos, logos, icons)
- Photos requiring transparent backgrounds
- Animations (GIF replacement)
Practical Examples
WebP Conversion in Node.js 다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
async function convertToWebP(inputPath, outputPath, options = {}) {
const { quality = 80, lossless = false } = options;
const info = await sharp(inputPath)
.webp({
quality: lossless ? 100 : quality,
lossless: lossless,
nearLossless: false,
smartSubsample: true, // Optimize chroma subsampling
effort: 6 // Compression effort (0-6)
})
.toFile(outputPath);
console.log(`✅ WebP conversion complete`);
console.log(` Size: ${info.size} bytes`);
console.log(` Resolution: ${info.width}x${info.height}`);
return info;
}
// Usage examples
convertToWebP('photo.jpg', 'photo.webp', { quality: 85 });
convertToWebP('logo.png', 'logo.webp', { lossless: true });
WebP Fallback in HTML 아래 코드는 html를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
<picture>
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg" alt="Description" loading="lazy">
</picture>
5. AVIF (AV1 Image File Format)
Characteristics
- Compression: Both lossy and lossless (AV1 codec-based)
- Transparency: Alpha channel support
- Animation: Supported
- Color Depth: 8-bit, 10-bit, 12-bit HDR support
- File Extensions:
.avif - Browser Support: Chrome 85+, Firefox 93+, Safari 16+ (~80%)
Compression Principle
AVIF uses intra-frame compression from the latest AV1 video codec. 아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
graph LR
A[Original Image] --> B["AV1 Intra Frame\nPredictive Coding"]
B --> C["Transform\nDCT/ADST"]
C --> D[Quantization]
D --> E[Entropy Coding]
E --> F[AVIF File]
Advantages
- 50% smaller file size than WebP
- Up to 10x compression efficiency vs JPEG
- HDR support (10-bit, 12-bit color depth)
- Supports transparency and animation
Disadvantages
- Very long encoding time (5-10x slower than WebP)
- Limited browser support (~80%)
- High CPU decoding load
Optimal Use Cases
- Modern websites with high-quality images
- HDR content
- When file size is critical
Practical Examples
AVIF Conversion in Node.js 다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
async function convertToAVIF(inputPath, outputPath, quality = 60) {
const info = await sharp(inputPath)
.avif({
quality: quality,
effort: 9, // Compression effort (0-9)
chromaSubsampling: '4:2:0' // Chroma subsampling
})
.toFile(outputPath);
console.log(`✅ AVIF conversion complete`);
console.log(` Size: ${info.size} bytes`);
return info;
}
// Usage example
convertToAVIF('photo.jpg', 'photo.avif', 65);
AVIF Fallback in HTML 아래 코드는 html를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg" alt="Description" loading="lazy">
</picture>
6. SVG (Scalable Vector Graphics)
Characteristics
- Compression: Vector-based (XML text)
- Transparency: Supported
- Animation: Supported via CSS/JavaScript
- Color Depth: Unlimited
- File Extensions:
.svg - Scaling: No quality loss
SVG Structure
아래 코드는 xml를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200">
<!-- Circle -->
<circle cx="100" cy="100" r="80" fill="#3b82f6" />
<!-- Rectangle -->
<rect x="50" y="50" width="100" height="100" fill="none" stroke="#ef4444" stroke-width="4" />
<!-- Text -->
<text x="100" y="110" text-anchor="middle" font-size="24" fill="white">SVG</text>
</svg>
Advantages
- No quality loss when scaled (vector)
- Small file size (for simple shapes)
- Manipulable with CSS and JavaScript
- Animation and interaction support
- Searchable text (XML-based)
Disadvantages
- Large file size for complex images
- Unsuitable for photographs
- Rendering performance issues (complex paths)
Optimal Use Cases
- Logos, icons
- Graphs, charts, diagrams
- Illustrations
- Responsive design (resolution-independent)
Practical Examples
SVG Optimization (SVGO) 다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const { optimize } = require('svgo');
const fs = require('fs');
function optimizeSVG(inputPath, outputPath) {
const svgString = fs.readFileSync(inputPath, 'utf8');
const result = optimize(svgString, {
multipass: true,
plugins: [
'preset-default',
'removeDoctype',
'removeComments',
'removeMetadata',
'removeUselessDefs',
'cleanupIds',
'minifyStyles',
'convertPathData'
]
});
fs.writeFileSync(outputPath, result.data);
console.log(`✅ SVG optimization complete`);
console.log(` Original: ${svgString.length} bytes`);
console.log(` Optimized: ${result.data.length} bytes`);
console.log(` Reduction: ${((1 - result.data.length / svgString.length) * 100).toFixed(1)}%`);
}
// Usage example
optimizeSVG('icon.svg', 'icon-optimized.svg');
Interactive SVG Animation 다음은 html를 활용한 상세한 구현 코드입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
<svg id="animated-circle" width="200" height="200" viewBox="0 0 200 200">
<circle id="circle" cx="100" cy="100" r="50" fill="#3b82f6" />
</svg>
<script>
const circle = document.getElementById('circle');
let radius = 50;
let growing = true;
setInterval(() => {
if (growing) {
radius += 2;
if (radius >= 80) growing = false;
} else {
radius -= 2;
if (radius <= 50) growing = true;
}
circle.setAttribute('r', radius);
}, 50);
</script>
7. BMP (Bitmap)
Characteristics
- Compression: Mostly uncompressed
- Transparency: Supported in some versions
- Animation: Not supported
- Color Depth: 1, 4, 8, 16, 24, 32-bit
- File Extensions:
.bmp
Advantages
- Simple structure, fast processing
- No quality loss (uncompressed)
Disadvantages
- Very large file size
- Rarely used on the web
- No compression support
Optimal Use Cases
- Windows system internal images
- Intermediate format for image processing
- Legacy applications
8. TIFF (Tagged Image File Format)
Characteristics
- Compression: Uncompressed or lossless (LZW, ZIP)
- Transparency: Alpha channel support
- Animation: Not supported
- Color Depth: 8, 16, 32-bit (HDR support)
- File Extensions:
.tiff,.tif
Advantages
- Very high quality (professional use)
- Various color depth support
- Rich metadata (EXIF, IPTC)
- Multiple layer support
Disadvantages
- Very large file size
- Not supported by web browsers
- Slow processing
Optimal Use Cases
- Professional photo editing
- Print images
- Medical imaging, satellite imagery
- Archival purposes
9. HEIF/HEIC (High Efficiency Image Format)
Characteristics
- Compression: HEVC (H.265) codec-based
- Transparency: Alpha channel support
- Animation: Supported
- Color Depth: 8, 10, 12-bit HDR support
- File Extensions:
.heif,.heic - Browser Support: Safari (iOS/macOS), limited elsewhere
Advantages
- 50% smaller file size than JPEG
- HDR support
- Multiple images in one file
- Rich metadata
Disadvantages
- Limited web browser support
- Licensing issues (HEVC patents)
- Conversion tools required
Optimal Use Cases
- iOS/macOS photo storage
- Mobile app internal images
- HDR photography
Format Comparison Table
| Format | Compression | Transparency | Animation | Colors | File Size | Browser Support | Best For |
|---|---|---|---|---|---|---|---|
| JPEG | Lossy | ✗ | ✗ | 16.7M | Small | 100% | Photos |
| PNG | Lossless | ✓ (8-bit) | ✗ | 16.7M | Medium | 100% | Logos, Icons |
| GIF | Lossless | ✓ (1-bit) | ✓ | 256 | Large | 100% | Simple Animations |
| WebP | Lossy/Lossless | ✓ (8-bit) | ✓ | 16.7M | Very Small | 96% | All Web |
| AVIF | Lossy/Lossless | ✓ (8-bit) | ✓ | HDR | Smallest | 80% | Modern Web |
| SVG | Vector | ✓ | ✓ | Unlimited | Small | 100% | Logos, Icons |
| BMP | Uncompressed | Partial | ✗ | 16.7M | Very Large | Limited | System Internal |
| TIFF | Lossless | ✓ | ✗ | HDR | Very Large | ✗ | Professional |
| HEIF | Lossy | ✓ | ✓ | HDR | Very Small | Limited | iOS/macOS |
Compression Efficiency Comparison
File size comparison when converting the same photo to various formats: 아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// 실행 예제
graph TD
A["Original BMP\n5.76 MB"] --> B["JPEG Quality 90\n450 KB"]
A --> C["PNG Lossless\n2.1 MB"]
A --> D["WebP Quality 90\n320 KB"]
A --> E["AVIF Quality 60\n180 KB"]
style A fill:#ef4444
style E fill:#22c55e
Real Benchmark (1920x1080 photo)
| Format | File Size | Quality | Encoding Time |
|---|---|---|---|
| BMP | 5.76 MB | 100% | 0.1s |
| PNG | 2.10 MB | 100% | 0.5s |
| JPEG (Quality 90) | 450 KB | 95% | 0.2s |
| WebP (Quality 90) | 320 KB | 95% | 1.2s |
| AVIF (Quality 60) | 180 KB | 95% | 8.5s |
Format Selection Guide
Photos
아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
graph TD
A{Photo Image} --> B{Transparent Background?}
B -->|Yes| C[WebP or AVIF]
B -->|No| D{Modern Browsers Only?}
D -->|Yes| E[AVIF > WebP > JPEG]
D -->|No| F[WebP + JPEG Fallback]
Recommended Order:
- AVIF (modern browsers)
- WebP (modern browsers)
- JPEG (fallback)
Logos/Icons
아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
graph TD
A{Logo/Icon} --> B{Vector Possible?}
B -->|Yes| C[SVG First]
B -->|No| D{Transparent Background?}
D -->|Yes| E[PNG or WebP]
D -->|No| F[JPEG or WebP]
Recommended Order:
- SVG (if vector possible)
- WebP (lossless)
- PNG (fallback)
Animations
아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
graph TD
A{Animation} --> B{Color Count}
B -->|≤256 colors| C[GIF]
B -->|Full Color| D{File Size Important?}
D -->|Yes| E[WebP or AVIF]
D -->|No| F[GIF or APNG]
Recommended Order:
- WebP (animated)
- AVIF (animated)
- GIF (fallback)
Practical Optimization Strategies
1. Responsive Images
다음은 html를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
<picture>
<!-- Modern browsers: AVIF -->
<source
srcset="image-400.avif 400w, image-800.avif 800w, image-1200.avif 1200w"
type="image/avif"
sizes="(max-width: 640px) 400px, (max-width: 1024px) 800px, 1200px">
<!-- Modern browsers: WebP -->
<source
srcset="image-400.webp 400w, image-800.webp 800w, image-1200.webp 1200w"
type="image/webp"
sizes="(max-width: 640px) 400px, (max-width: 1024px) 800px, 1200px">
<!-- Fallback: JPEG -->
<img
srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
sizes="(max-width: 640px) 400px, (max-width: 1024px) 800px, 1200px"
src="image-800.jpg"
alt="Description"
loading="lazy"
decoding="async">
</picture>
2. Automated Conversion Pipeline
다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
const fs = require('fs').promises;
const path = require('path');
async function convertImagePipeline(inputPath, outputDir) {
const basename = path.basename(inputPath, path.extname(inputPath));
const sizes = [400, 800, 1200];
for (const size of sizes) {
const resized = sharp(inputPath).resize(size, null, {
withoutEnlargement: true,
fit: 'inside'
});
// AVIF
await resized.clone()
.avif({ quality: 65, effort: 6 })
.toFile(path.join(outputDir, `${basename}-${size}.avif`));
// WebP
await resized.clone()
.webp({ quality: 85, effort: 6 })
.toFile(path.join(outputDir, `${basename}-${size}.webp`));
// JPEG (fallback)
await resized.clone()
.jpeg({ quality: 85, progressive: true, mozjpeg: true })
.toFile(path.join(outputDir, `${basename}-${size}.jpg`));
console.log(`✅ ${size}px conversion complete`);
}
}
// Usage example
convertImagePipeline('photo.jpg', './dist/images');
3. Lazy Loading
다음은 html를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
<!-- Native Lazy Loading -->
<img src="image.jpg" alt="Description" loading="lazy" decoding="async">
<!-- Intersection Observer API -->
<img data-src="image.jpg" alt="Description" class="lazy-image">
<script>
const lazyImages = document.querySelectorAll('.lazy-image');
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy-image');
observer.unobserve(img);
}
});
}, {
rootMargin: '50px' // Load 50px before viewport
});
lazyImages.forEach(img => imageObserver.observe(img));
</script>
Format Conversion Tools
1. Sharp (Node.js)
npm install sharp
다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
// Convert to various formats
async function convertImage(input, format, options = {}) {
const formats = {
jpeg: () => sharp(input).jpeg(options),
png: () => sharp(input).png(options),
webp: () => sharp(input).webp(options),
avif: () => sharp(input).avif(options),
gif: () => sharp(input).gif(options),
tiff: () => sharp(input).tiff(options)
};
if (!formats[format]) {
throw new Error(`Unsupported format: ${format}`);
}
const output = input.replace(/\.[^.]+$/, `.${format}`);
await formats[format]().toFile(output);
console.log(`✅ ${format.toUpperCase()} conversion complete: ${output}`);
}
// Usage example
convertImage('photo.png', 'webp', { quality: 85 });
2. ImageMagick (CLI)
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# Convert to JPEG
magick input.png -quality 85 output.jpg
# Convert to WebP
magick input.jpg -quality 85 output.webp
# Resize + Convert
magick input.jpg -resize 800x600 -quality 85 output.webp
# Batch conversion
magick mogrify -format webp -quality 85 *.jpg
3. Squoosh (Web-based)
Batch conversion using Google’s Squoosh CLI: 아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
npm install -g @squoosh/cli
# WebP conversion
squoosh-cli --webp auto *.jpg
# AVIF conversion
squoosh-cli --avif auto *.jpg
# Multiple formats simultaneously
squoosh-cli --webp auto --avif auto *.jpg
Web Performance Optimization
1. Content-Type Header Configuration
다음은 nginx를 활용한 상세한 구현 코드입니다. 에러 처리를 통해 안정성을 확보합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# Nginx configuration
location ~* \.(jpg|jpeg|png|gif|webp|avif|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary "Accept";
}
# Serve WebP to supporting browsers
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
location ~* \.(jpg|jpeg|png)$ {
add_header Vary Accept;
try_files $uri$webp_suffix $uri =404;
}
2. CDN Auto-Optimization
Cloudflare Polish 다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Cloudflare Workers image optimization
export default {
async fetch(request) {
const url = new URL(request.url);
// Check if image request
if (/\.(jpg|jpeg|png|gif)$/i.test(url.pathname)) {
const accept = request.headers.get('Accept') || ';
// AVIF-supporting browsers
if (accept.includes('image/avif')) {
url.pathname = url.pathname.replace(/\.(jpg|jpeg|png)$/i, '.avif');
}
// WebP-supporting browsers
else if (accept.includes('image/webp')) {
url.pathname = url.pathname.replace(/\.(jpg|jpeg|png)$/i, '.webp');
}
return fetch(url);
}
return fetch(request);
}
};
3. Progressive Loading
Creating Progressive JPEG 아래 코드는 javascript를 사용한 구현 예제입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
async function createProgressiveJPEG(inputPath, outputPath) {
await sharp(inputPath)
.jpeg({
quality: 85,
progressive: true // Progressive scan
})
.toFile(outputPath);
console.log('✅ Progressive JPEG created');
}
Blur Placeholder (LQIP) 다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
async function generateLQIP(inputPath) {
// Generate low-quality small image
const lqip = await sharp(inputPath)
.resize(20, 20, { fit: 'inside' })
.blur(1)
.jpeg({ quality: 50 })
.toBuffer();
// Base64 encoding
const base64 = `data:image/jpeg;base64,${lqip.toString('base64')}`;
return base64;
}
// Use in HTML
const lqip = await generateLQIP('photo.jpg');
다음은 html를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
<img
src="data:image/jpeg;base64,/9j/4AAQ..."
data-src="photo.jpg"
class="lazy-blur"
alt="Description">
<style>
.lazy-blur {
filter: blur(10px);
transition: filter 0.3s;
}
.lazy-blur.loaded {
filter: blur(0);
}
</style>
Image Metadata
Reading/Writing EXIF Data
다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const ExifReader = require('exifreader');
const fs = require('fs');
async function readEXIF(imagePath) {
const buffer = fs.readFileSync(imagePath);
const tags = ExifReader.load(buffer);
console.log('Camera:', tags.Model?.description);
console.log('Date:', tags.DateTime?.description);
console.log('ISO:', tags.ISOSpeedRatings?.description);
console.log('Aperture:', tags.FNumber?.description);
console.log('Shutter Speed:', tags.ExposureTime?.description);
console.log('GPS:', tags.GPSLatitude?.description, tags.GPSLongitude?.description);
return tags;
}
// Remove EXIF (privacy protection)
async function removeEXIF(inputPath, outputPath) {
await sharp(inputPath)
.rotate() // Apply EXIF Orientation
.withMetadata({ exif: {} }) // Remove EXIF
.toFile(outputPath);
console.log('✅ EXIF removed');
}
Color Spaces
sRGB vs Adobe RGB vs Display P3
아래 코드는 javascript를 사용한 구현 예제입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
async function convertColorSpace(inputPath, outputPath, colorSpace = 'srgb') {
await sharp(inputPath)
.toColorspace(colorSpace) // 'srgb', 'rgb16', 'cmyk', 'lab', 'b-w'
.jpeg({ quality: 90 })
.toFile(outputPath);
console.log(`✅ ${colorSpace.toUpperCase()} color space conversion complete`);
}
// For web: sRGB recommended
convertColorSpace('photo-adobergb.jpg', 'photo-srgb.jpg', 'srgb');
Color Space Comparison
| Color Space | Gamut Range | Use Case |
|---|---|---|
| sRGB | Standard (narrowest) | Web, monitor standard |
| Adobe RGB | Wide (135% of sRGB) | Professional photo, print |
| Display P3 | Wide (125% of sRGB) | Apple devices, HDR |
| ProPhoto RGB | Very Wide | Professional editing, RAW |
Image Optimization Checklist
For Websites
- Format Selection: AVIF > WebP > JPEG/PNG
- Resolution: 2x actual display size (Retina support)
- Compression: Quality 80-85 (JPEG/WebP), 60-65 (AVIF)
- Lazy Loading: Add
loading="lazy"attribute - Remove EXIF: Privacy protection and size reduction
- Progressive: Use progressive JPEG
- CDN: Use image CDN (Cloudflare, Imgix, Cloudinary)
- Caching: Set appropriate Cache-Control headers
For Mobile Apps
- Format Selection: WebP or HEIF (iOS)
- Resolution: Provide 1x, 2x, 3x versions
- Compression: Quality 75-80
- Downsampling: Prevent unnecessary high resolution
- Caching: Memory and disk cache strategy
Advanced Techniques
1. Adaptive Images
다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Adjust image quality based on network speed
async function getAdaptiveImage(imagePath, connection) {
const effectiveType = connection.effectiveType; // '4g', '3g', '2g', 'slow-2g'
let quality;
switch (effectiveType) {
case '4g': quality = 85; break;
case '3g': quality = 70; break;
case '2g': quality = 50; break;
default: quality = 40;
}
return sharp(imagePath)
.webp({ quality })
.toBuffer();
}
// Client-side usage
if ('connection' in navigator) {
const connection = navigator.connection;
console.log('Network type:', connection.effectiveType);
// Send network info to server
fetch('/api/image?path=photo.jpg&network=' + connection.effectiveType);
}
2. Image Sprites
다음은 css를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
/* Combine multiple icons into one image */
.icon {
background-image: url('sprite.png');
background-repeat: no-repeat;
display: inline-block;
}
.icon-home {
width: 32px;
height: 32px;
background-position: 0 0;
}
.icon-search {
width: 32px;
height: 32px;
background-position: -32px 0;
}
.icon-user {
width: 32px;
height: 32px;
background-position: -64px 0;
}
3. Image CDN Usage
Cloudflare Images 아래 코드는 html를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
<!-- Original -->
<img src="https://imagedelivery.net/account-id/image-id/public">
<!-- Resize + Format conversion -->
<img src="https://imagedelivery.net/account-id/image-id/w=800,format=auto">
<!-- Quality adjustment -->
<img src="https://imagedelivery.net/account-id/image-id/w=800,q=85,format=webp">
Imgix 아래 코드는 html를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
<!-- Auto format selection -->
<img src="https://example.imgix.net/photo.jpg?auto=format,compress">
<!-- Resize + Crop -->
<img src="https://example.imgix.net/photo.jpg?w=800&h=600&fit=crop&auto=format">
<!-- DPR (Device Pixel Ratio) support -->
<img src="https://example.imgix.net/photo.jpg?w=400&dpr=2&auto=format">
Browser Support Detection
Detecting Format Support in JavaScript
다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
async function checkImageFormatSupport() {
const formats = ['webp', 'avif', 'jxl'];
const support = {};
for (const format of formats) {
const testImage = {
webp: 'data:image/webp;base64,UklGRiQAAABXRUJQVlA4IBgAAAAwAQCdASoBAAEAAwA0JaQAA3AA/vuUAAA=',
avif: 'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQ==',
jxl: 'data:image/jxl;base64,/woIELASCAgQAFwASxLFgkWAHL0xbgBY74aP4A=='
};
try {
const img = new Image();
const loaded = await new Promise((resolve) => {
img.onload = () => resolve(true);
img.onerror = () => resolve(false);
img.src = testImage[format];
});
support[format] = loaded && img.width === 1 && img.height === 1;
} catch {
support[format] = false;
}
}
console.log('Image format support:', support);
return support;
}
// Usage example
checkImageFormatSupport().then(support => {
if (support.avif) {
console.log('✅ AVIF supported');
} else if (support.webp) {
console.log('✅ WebP supported');
} else {
console.log('⚠️ Only JPEG/PNG supported');
}
});
Format Support Detection in CSS
다음은 css를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
/* WebP-supporting browsers */
.hero {
background-image: url('hero.jpg');
}
@supports (background-image: url('hero.webp')) {
.hero {
background-image: url('hero.webp');
}
}
/* AVIF-supporting browsers */
@supports (background-image: url('hero.avif')) {
.hero {
background-image: url('hero.avif');
}
}
Real-World Project Examples
Next.js Image Optimization
다음은 jsx를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
import Image from 'next/image';
export default function OptimizedImage() {
return (
<Image
src="/photo.jpg"
alt="Description"
width={800}
height={600}
quality={85}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
loading="lazy"
// Next.js automatically converts to WebP/AVIF
/>
);
}
Astro Image Optimization
다음은 astro를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
import { Image } from 'astro:assets';
---
import heroImage from '../assets/hero.jpg';
<Image
src={heroImage}
alt="Description"
width={800}
height={600}
format="webp"
quality={85}
loading="lazy"
/>
<!-- Or provide multiple formats -->
<picture>
<source srcset={heroImage.src + '?format=avif'} type="image/avif">
<source srcset={heroImage.src + '?format=webp'} type="image/webp">
<img src={heroImage.src} alt="Description" loading="lazy">
</picture>
Image Compression Quality Guide
Recommended Quality Settings
| Use Case | JPEG | WebP | AVIF | Description |
|---|---|---|---|---|
| Thumbnails | 60-70 | 55-65 | 45-55 | Small size, quality loss acceptable |
| General Photos | 80-85 | 75-80 | 60-65 | Balanced quality and size |
| High-Quality Photos | 90-95 | 85-90 | 70-75 | Quality priority |
| 95-100 | 95-100 | 80-90 | Maximum quality |
File Size vs Quality Trade-off
다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
async function qualityComparison(inputPath) {
const qualities = [50, 60, 70, 80, 90, 100];
console.log('File size by quality:\n');
for (const quality of qualities) {
const jpegInfo = await sharp(inputPath)
.jpeg({ quality })
.toBuffer({ resolveWithObject: true });
const webpInfo = await sharp(inputPath)
.webp({ quality })
.toBuffer({ resolveWithObject: true });
const avifInfo = await sharp(inputPath)
.avif({ quality: Math.floor(quality * 0.75) }) // AVIF works well with lower quality
.toBuffer({ resolveWithObject: true });
console.log(`Quality ${quality}:`);
console.log(` JPEG: ${(jpegInfo.info.size / 1024).toFixed(1)} KB`);
console.log(` WebP: ${(webpInfo.info.size / 1024).toFixed(1)} KB`);
console.log(` AVIF: ${(avifInfo.info.size / 1024).toFixed(1)} KB`);
}
}
// Usage example
qualityComparison('photo.jpg');
Special Image Formats
1. ICO (Icon)
Windows icon format that stores multiple resolutions in one file. 다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
const toIco = require('to-ico');
async function createFavicon(inputPath, outputPath) {
const sizes = [16, 32, 48, 64, 128, 256];
const buffers = [];
for (const size of sizes) {
const buffer = await sharp(inputPath)
.resize(size, size)
.png()
.toBuffer();
buffers.push(buffer);
}
const ico = await toIco(buffers);
fs.writeFileSync(outputPath, ico);
console.log('✅ Favicon created');
}
// Usage example
createFavicon('logo.png', 'favicon.ico');
2. APNG (Animated PNG)
Animated extension of PNG format. 아래 코드는 javascript를 사용한 구현 예제입니다. 함수를 통해 로직을 구현합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const UPNG = require('upng-js');
const fs = require('fs');
function createAPNG(frames, delays, outputPath) {
// frames: Array of PNG buffers
// delays: Array of delays in ms
const apng = UPNG.encode(frames, 800, 600, 0, delays);
fs.writeFileSync(outputPath, Buffer.from(apng));
console.log('✅ APNG created');
}
3. JPEG XL (JXL)
Next-generation image format providing 60% smaller size than JPEG. 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# JPEG XL conversion (cjxl tool)
cjxl input.jpg output.jxl --quality 85
# JPEG XL decoding
djxl input.jxl output.jpg
Browser Support: Currently limited (Chrome 91-109 with flag, later removed)
Automated Image Format Conversion
Build Pipeline Integration
다음은 javascript를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 비동기 처리를 통해 효율적으로 작업을 수행합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// scripts/optimize-images.mjs
import sharp from 'sharp';
import { glob } from 'glob';
import path from 'path';
import fs from 'fs/promises';
async function optimizeImages() {
const images = await glob('src/assets/**/*.{jpg,jpeg,png}');
console.log(`🖼️ Optimizing ${images.length} images...\n`);
for (const imagePath of images) {
const dir = path.dirname(imagePath);
const basename = path.basename(imagePath, path.extname(imagePath));
const outputDir = dir.replace('src/assets', 'public/optimized');
await fs.mkdir(outputDir, { recursive: true });
const sizes = [400, 800, 1200];
for (const size of sizes) {
const resized = sharp(imagePath).resize(size, null, {
withoutEnlargement: true,
fit: 'inside'
});
// AVIF
await resized.clone()
.avif({ quality: 65, effort: 4 })
.toFile(path.join(outputDir, `${basename}-${size}.avif`));
// WebP
await resized.clone()
.webp({ quality: 85, effort: 4 })
.toFile(path.join(outputDir, `${basename}-${size}.webp`));
// JPEG
await resized.clone()
.jpeg({ quality: 85, progressive: true, mozjpeg: true })
.toFile(path.join(outputDir, `${basename}-${size}.jpg`));
}
console.log(`✅ ${basename} optimized`);
}
console.log(`\n✅ All images optimized`);
}
optimizeImages();
Add Script to package.json 아래 코드는 json를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
{
"scripts": {
"optimize:images": "node scripts/optimize-images.mjs",
"prebuild": "npm run optimize:images"
}
}
Performance Monitoring
Measuring Image Loading Performance
다음은 javascript를 활용한 상세한 구현 코드입니다. 함수를 통해 로직을 구현합니다, 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Measure image loading time with Performance API
function measureImagePerformance() {
const images = document.querySelectorAll('img');
images.forEach((img, index) => {
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
entries.forEach(entry => {
if (entry.name.includes(img.src)) {
console.log(`Image ${index + 1}:`);
console.log(` URL: ${entry.name}`);
console.log(` Size: ${(entry.transferSize / 1024).toFixed(2)} KB`);
console.log(` Load Time: ${entry.duration.toFixed(2)} ms`);
}
});
});
observer.observe({ entryTypes: ['resource'] });
});
}
// Execute after DOM load
window.addEventListener('load', measureImagePerformance);
Lighthouse Image Optimization Score
다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Image optimization audit script
async function auditImages() {
const images = document.querySelectorAll('img');
const issues = [];
for (const img of images) {
// 1. Check appropriate size
const naturalWidth = img.naturalWidth;
const displayWidth = img.clientWidth;
if (naturalWidth > displayWidth * 2) {
issues.push({
src: img.src,
issue: 'Image too large',
suggestion: `Resize to ${displayWidth * 2}px recommended`
});
}
// 2. Check modern format usage
if (img.src.match(/\.(jpg|jpeg|png)$/i)) {
issues.push({
src: img.src,
issue: 'Legacy format used',
suggestion: 'Convert to WebP or AVIF recommended'
});
}
// 3. Check lazy loading
if (!img.loading || img.loading !== 'lazy') {
issues.push({
src: img.src,
issue: 'Lazy loading not used',
suggestion: 'Add loading="lazy" attribute recommended'
});
}
}
console.table(issues);
return issues;
}
// Usage example
auditImages();
Troubleshooting
Issue 1: WebP Not Displaying in Safari
Cause: Safari 13 and below don’t support WebP Solution: 다음은 간단한 html 코드 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
<picture>
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Description">
</picture>
Issue 2: AVIF Encoding Too Slow
Cause: AVIF has high compression efficiency but long encoding time Solution: 아래 코드는 javascript를 사용한 구현 예제입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 조건문으로 분기 처리를 수행합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// Lower effort value for faster encoding
await sharp(input)
.avif({
quality: 65,
effort: 4 // Default 4-6 (0-9, lower = faster)
})
.toFile(output);
// Or convert only during build and cache
Issue 3: PNG Transparency Displays as Black
Cause: Transparency lost when converting to JPEG Solution: 아래 코드는 javascript를 사용한 구현 예제입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// Replace transparency with white background
await sharp('logo.png')
.flatten({ background: { r: 255, g: 255, b: 255 } })
.jpeg({ quality: 85 })
.toFile('logo.jpg');
// Or use WebP if transparency needed
await sharp('logo.png')
.webp({ quality: 85, lossless: false })
.toFile('logo.webp');
Issue 4: Images Appear Blurry
Cause: Not optimized for Retina displays Solution: 아래 코드는 html를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
<!-- Provide high-resolution images with srcset -->
<img
src="image-800.jpg"
srcset="image-800.jpg 1x, image-1600.jpg 2x, image-2400.jpg 3x"
alt="Description">
Security Considerations
1. Removing EXIF Data
EXIF data can contain personal information like GPS location, capture time, and camera model. 다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
async function stripMetadata(inputPath, outputPath) {
await sharp(inputPath)
.rotate() // Apply EXIF Orientation
.withMetadata({
exif: {}, // Remove EXIF
icc: {}, // Remove ICC profile
iptc: {}, // Remove IPTC
xmp: {} // Remove XMP
})
.toFile(outputPath);
console.log('✅ Metadata removed');
}
2. Image Upload Validation
다음은 javascript를 활용한 상세한 구현 코드입니다. 비동기 처리를 통해 효율적으로 작업을 수행합니다, 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
const sharp = require('sharp');
const fileType = require('file-type');
async function validateImageUpload(buffer, allowedFormats = ['jpeg', 'png', 'webp']) {
try {
// 1. Check file type (magic number-based)
const type = await fileType.fromBuffer(buffer);
if (!type || !allowedFormats.includes(type.ext)) {
throw new Error(`Disallowed format: ${type?.ext || 'unknown'}`);
}
// 2. Check image metadata
const metadata = await sharp(buffer).metadata();
// 3. Check size limits
const maxWidth = 4000;
const maxHeight = 4000;
if (metadata.width > maxWidth || metadata.height > maxHeight) {
throw new Error(`Image size exceeded: ${metadata.width}x${metadata.height}`);
}
// 4. File size limit (10MB)
if (buffer.length > 10 * 1024 * 1024) {
throw new Error(`File size exceeded: ${(buffer.length / 1024 / 1024).toFixed(2)} MB`);
}
console.log('✅ Image validation passed');
return true;
} catch (error) {
console.error('❌ Image validation failed:', error.message);
return false;
}
}
// Usage in Express.js
app.post('/upload', upload.single('image'), async (req, res) => {
const isValid = await validateImageUpload(req.file.buffer);
if (!isValid) {
return res.status(400).json({ error: 'Invalid image' });
}
// Continue processing...
});
Practical Tips
1. Format Selection Flowchart
다음은 mermaid를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
graph TD
A[Image Type?] --> B{Photo?}
B -->|Yes| C{Transparent Background?}
C -->|Yes| D[WebP or AVIF]
C -->|No| E{Modern Browsers Only?}
E -->|Yes| F[AVIF > WebP > JPEG]
E -->|No| G[WebP + JPEG Fallback]
B -->|No| H{Vector Possible?}
H -->|Yes| I[SVG]
H -->|No| J{Animation?}
J -->|Yes| K[WebP > GIF]
J -->|No| L{Transparent Background?}
L -->|Yes| M[PNG or WebP]
L -->|No| N[JPEG or WebP]
2. File Size Targets
| Image Type | Target Size | Maximum Size |
|---|---|---|
| Hero Image | < 100 KB | < 200 KB |
| Thumbnail | < 20 KB | < 50 KB |
| Logo | < 10 KB | < 30 KB |
| Icon | < 5 KB | < 10 KB |
| Background Image | < 150 KB | < 300 KB |
3. Image Optimization Checklist
Development Phase
- Store original images in high quality (lossless)
- Build automated conversion pipeline
- Generate multiple resolutions (400px, 800px, 1200px)
- Create AVIF, WebP, JPEG trio Deployment Phase
- Use CDN (Cloudflare, Imgix, Cloudinary)
- Use HTTP/2 or HTTP/3 (multiplexing)
- Set appropriate Cache-Control headers
- Enable Brotli compression (SVG) Monitoring
- Check Lighthouse score (target 90+)
- Measure Core Web Vitals (LCP < 2.5s)
- Track image loading times
- Monitor file sizes
Conclusion
Image format selection significantly impacts web performance. Actively use modern formats (AVIF, WebP) while always providing fallbacks for legacy browsers. Building an automated build pipeline improves both developer and user experience. Key Takeaways:
- Photos: AVIF > WebP > JPEG
- Logos/Icons: SVG > WebP (lossless) > PNG
- Animations: WebP > APNG > GIF
- Always Provide Fallback: Use
<picture>tag - Automate: Build conversion pipeline