서버 API의 성능을 최적화하는 것은 사용자 경험을 향상시키고 서버 부하를 줄이는 데 매우 중요합니다.
캐싱은 성능을 개선하는 강력한 방법 중 하나로, HTTP 캐시 헤더와 Redis와 같은 인메모리 데이터 저장소를 통해 구현할 수 있습니다.
이 블로그 포스트에서는 Dart를 사용하여 캐싱을 통한 성능 최적화를 어떻게 구현할 수 있는지 초보자도 이해할 수 있도록 설명하겠습니다.
1. 캐싱의 기본 개념
캐싱은 데이터를 임시 저장소에 보관하여 자주 요청되는 데이터에 대한 응답 속도를 높이는 기술입니다.
서버에서 데이터베이스에 접근하거나 복잡한 연산을 수행하는 대신, 이미 저장된 데이터를 빠르게 제공함으로써 응답 시간을 줄입니다.
2. HTTP 캐시 헤더
HTTP 캐시 헤더를 사용하면 웹 브라우저와 캐시 서버가 응답을 저장하고 재사용할 수 있도록 할 수 있습니다. 주요 HTTP 캐시 헤더는 다음과 같습니다.
- Cache-Control: 캐시 동작을 제어합니다. 예를 들어, Cache-Control: max-age=3600은 응답을 1시간 동안 캐시하도록 지시합니다.
- Expires: 응답의 만료 시간을 지정합니다. 예: Expires: Wed, 21 Sep 2024 16:00:00 GMT.
- ETag: 리소스의 버전을 식별하는 태그입니다. 클라이언트는 ETag를 사용하여 서버에 리소스가 변경되었는지 확인할 수 있습니다.
- Last-Modified: 리소스의 마지막 수정 시간을 지정합니다.
3. HTTP 캐시 헤더 설정하기
Dart와 shelf를 사용하여 HTTP 캐시 헤더를 설정하는 방법을 살펴보겠습니다. 먼저, shelf 패키지를 설치하고 기본 서버를 설정합니다.
3.1. 기본 서버 설정
pubspec.yaml 파일에 shelf 패키지를 추가합니다.
dependencies:
shelf: ^1.4.0
패키지를 설치합니다.
dart pub get
bin/server.dart 파일을 생성하고 아래 코드를 입력합니다.
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
void main() async {
final handler = const Pipeline()
.addMiddleware(_cacheMiddleware)
.addHandler(_handler);
final server = await io.serve(handler, 'localhost', 8080);
print('서버가 http://${server.address.host}:${server.port}에서 실행 중입니다.');
}
Response _handler(Request request) {
return Response.ok(
'안녕하세요, 캐싱 테스트!',
headers: {
'Cache-Control': 'public, max-age=3600',
'Expires': DateTime.now().add(Duration(hours: 1)).toUtc().toIso8601String(),
},
);
}
Middleware _cacheMiddleware = (Handler innerHandler) {
return (Request request) async {
final response = await innerHandler(request);
if (response.statusCode == 200) {
return response.change(headers: {
'Cache-Control': 'public, max-age=3600',
'Expires': DateTime.now().add(Duration(hours: 1)).toUtc().toIso8601String(),
});
}
return response;
};
};
이 코드는 HTTP 응답에 Cache-Control 및 Expires 헤더를 추가하여 1시간 동안 캐시하도록 설정합니다.
4. Redis를 사용한 캐싱
Redis는 인메모리 데이터베이스로, 캐싱을 위한 빠르고 효율적인 저장소를 제공합니다. Dart에서 Redis를 사용하기 위해 redis 패키지를 사용할 수 있습니다.
4.1. Redis 패키지 추가
pubspec.yaml 파일에 redis 패키지를 추가합니다.
dependencies:
redis: ^2.1.1
패키지를 설치합니다.
dart pub get
4.2. Redis 캐싱 구현
bin/redis_cache.dart 파일을 생성하고 아래 코드를 입력합니다.
import 'package:redis/redis.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
Future<void> main() async {
final redis = RedisConnection();
final command = await redis.connect('localhost', 6379);
final db = command.asCommands;
final handler = const Pipeline()
.addMiddleware(_cacheMiddleware(db))
.addHandler(_handler(db));
final server = await io.serve(handler, 'localhost', 8080);
print('서버가 http://${server.address.host}:${server.port}에서 실행 중입니다.');
}
Future<Response> _handler(Commands db) async {
final cacheKey = 'my_data_key';
final cachedData = await db.get(cacheKey);
if (cachedData != null) {
return Response.ok(cachedData, headers: {'Content-Type': 'text/plain'});
}
final data = '안녕하세요, Redis 캐싱 테스트!';
await db.set(cacheKey, data, expires: Duration(minutes: 10));
return Response.ok(data, headers: {'Content-Type': 'text/plain'});
}
Middleware _cacheMiddleware(Commands db) {
return (Handler innerHandler) {
return (Request request) async {
final response = await innerHandler(request);
if (response.statusCode == 200) {
final cacheKey = 'my_data_key';
await db.set(cacheKey, response.readAsString(), expires: Duration(minutes: 10));
}
return response;
};
};
}
이 코드는 Redis를 사용하여 데이터를 캐시하고, 캐시된 데이터가 있을 경우 Redis에서 데이터를 가져오고, 없을 경우 새 데이터를 생성하여 Redis에 저장합니다.
5. 성능 최적화 팁
- 캐시 전략 설정: 데이터를 자주 변경하지 않는 경우에는 더 긴 캐시 만료 시간을 설정하고, 자주 변경되는 데이터는 짧은 만료 시간을 설정합니다.
- 압축 사용: 데이터를 전송하기 전에 압축하여 네트워크 대역폭을 줄입니다.
- 캐시 무효화: 데이터가 업데이트될 때는 캐시를 무효화하고, 새 데이터를 저장하도록 합니다.
이 블로그 포스트에서는 Dart를 사용하여 서버 API의 성능을 최적화하기 위한 HTTP 캐시 헤더와 Redis 캐싱의 구현 방법을 소개했습니다.
캐싱을 통해 응답 속도를 개선하고 서버 부하를 줄일 수 있으며, 적절한 캐시 전략을 통해 성능을 더욱 향상시킬 수 있습니다.
이러한 기법을 활용하여 더 나은 사용자 경험을 제공해 보세요!
구독!! 공감과 댓글은 저에게 큰 힘이 됩니다.
Starting Google Play App Distribution! "Tester Share" for Recruiting 20 Testers for a Closed Test.
'Dart > Dart Server' 카테고리의 다른 글
[고급] Dart 서버 마이크로서비스 아키텍처 / 마이크로서비스 개념과 Dart의 적용 가능성 (3) | 2024.09.14 |
---|---|
[고급] Dart 서버 API 고급 설계 및 최적화/ 페이징 및 필터링을 통한 대량 데이터 처리 최적화 (1) | 2024.09.13 |
[고급] Dart 서버 API 고급 설계 및 최적화/ API 버저닝 전략과 구현 방법 (0) | 2024.09.13 |
[중급] Dart 서버 인증 및 보안/ Dart 서버 보안 모범 사례 (HTTPS 설정, 입력 검증, SQL 인젝션 방지 등) (1) | 2024.09.12 |
[중급] Dart 서버 인증 및 보안/ OAuth 2.0을 활용한 외부 서비스 인증 연동 (0) | 2024.09.12 |