Google Cloud 잘 설계된 프레임워크의 지속 가능성 요소 원칙은 에너지 소비와 서버 부하를 최소화하는 소프트웨어를 작성하기 위한 권장사항을 제공합니다.
원칙 개요
권장사항에 따라 클라우드 애플리케이션을 빌드하면 클라우드 인프라 리소스(AI, 컴퓨팅, 스토리지, 네트워크)에서 사용하는 에너지를 최적화할 수 있습니다. 또한 데이터 센터의 물 요구량과 최종 사용자 기기가 애플리케이션에 액세스할 때 소비하는 에너지를 줄이는 데도 도움이 됩니다.
에너지 효율적인 소프트웨어를 빌드하려면 설계 및 개발부터 배포, 유지관리, 보관에 이르기까지 소프트웨어 수명 주기 전반에 걸쳐 지속 가능성 고려사항을 통합해야 합니다. AI를 사용하여 클라우드 워크로드의 환경 영향을 최소화하는 소프트웨어를 빌드하는 방법에 관한 자세한 안내는 Google Cloud eBook, 지속 가능한 소프트웨어 빌드를 참고하세요.
권장사항
이 섹션의 권장사항은 다음 중점사항으로 그룹화됩니다.
- 계산 작업 최소화: 중복 로직을 없애고 불필요한 계산이나 기능 부풀림을 방지하는 간결하고 집중된 코드를 사용하세요.
- 효율적인 알고리즘 및 데이터 구조 사용: CPU 부하를 줄이고 메모리 사용량을 최소화하는 시간 효율적이고 메모리 효율적인 알고리즘을 선택합니다.
- 컴퓨팅 및 데이터 작업 최적화: CPU, 메모리, 디스크 I/O, 네트워크 등 사용 가능한 모든 리소스를 효율적으로 사용한다는 목표로 개발합니다. 예를 들어 사용 중인 루프를 이벤트 기반 논리로 대체하면 불필요한 폴링을 방지할 수 있습니다.
- 프런트엔드 최적화 구현: 최종 사용자 기기에서 소비하는 전력을 줄이려면 이미지 및 애셋에 최소화, 압축, 지연 로딩과 같은 전략을 사용하세요.
계산 작업 최소화
에너지 효율적인 소프트웨어를 작성하려면 애플리케이션에서 실행하는 총 컴퓨팅 작업량을 최소화해야 합니다. 불필요한 명령어, 중복 루프, 추가 기능은 에너지, 시간, 리소스를 소비합니다. 다음 권장사항을 사용하여 최소한의 계산을 실행하는 소프트웨어를 빌드하세요.
간결하고 집중적인 코드 작성
필요한 결과를 달성하는 데 필수적인 최소한의 코드를 작성하려면 다음 방법을 사용하세요.
- 중복 로직 및 기능 부풀림 제거: 필수 기능만 실행하는 코드를 작성합니다. 계산 오버헤드와 복잡성을 높이지만 사용자에게 측정 가능한 가치를 제공하지 않는 기능은 피하세요.
- 리팩터링: 시간이 지남에 따라 에너지 효율을 개선하려면 애플리케이션을 정기적으로 감사하여 사용하지 않는 기능을 파악하세요. 적절한 조치를 취하여 이러한 기능을 삭제하거나 리팩터링하세요.
- 불필요한 작업 방지: 결과가 필요할 때까지 값을 계산하거나 작업을 실행하지 마세요. 애플리케이션의 종속 구성요소에 출력이 필요할 때까지 계산을 지연하는 지연 평가와 같은 기법을 사용합니다.
- 코드 가독성 및 재사용 가능성 우선순위 지정: 가독성이 높고 재사용 가능한 코드를 작성합니다. 이 접근 방식은 중복을 최소화하고 반복 금지 (DRY) 원칙을 따르므로 소프트웨어 개발 및 유지관리에서 발생하는 탄소 배출량을 줄이는 데 도움이 될 수 있습니다.
백엔드 캐싱 사용
백엔드 캐싱을 사용하면 애플리케이션이 동일한 작업을 반복적으로 실행하지 않습니다. 캐시 적중률이 높으면 요청당 에너지 소비가 거의 선형으로 감소합니다. 백엔드 캐싱을 구현하려면 다음 기법을 사용하세요.
- 자주 사용하는 데이터 캐시: 자주 액세스하는 데이터를 임시 고성능 스토리지 위치에 저장합니다. 예를 들어 Memorystore와 같은 인메모리 캐싱 서비스를 사용합니다. 애플리케이션이 캐시에서 데이터를 가져오면 데이터베이스 쿼리 및 디스크 I/O 작업의 양이 줄어듭니다. 따라서 백엔드의 데이터베이스와 서버의 부하가 줄어듭니다.
- API 응답 캐시: 중복되고 비용이 많이 드는 네트워크 호출을 방지하려면 자주 발생하는 API 요청의 결과를 캐시하세요.
- 인메모리 캐싱 우선순위 지정: 느린 디스크 I/O 작업과 복잡한 데이터베이스 쿼리를 없애려면 고속 메모리 (RAM)에 데이터를 저장하세요.
- 적절한 캐시 쓰기 전략 선택:
- writethrough 전략은 데이터가 캐시와 영구 저장소에 동기적으로 기록되도록 합니다. 이 전략은 캐시 적중 가능성을 높이므로 영구 저장소에서 에너지 집약적인 읽기 요청을 더 적게 받습니다.
- 쓰기 백 (쓰기 지연) 전략은 쓰기 중심 애플리케이션의 성능을 향상합니다. 데이터는 먼저 캐시에 기록되고 데이터베이스는 나중에 비동기적으로 업데이트됩니다. 이 전략은 느린 데이터베이스의 즉각적인 쓰기 부하를 줄입니다.
- 스마트 제거 정책 사용: 캐시를 간결하고 효율적으로 유지합니다. 비활성 데이터나 유용성이 낮은 데이터를 삭제하고 자주 요청되는 데이터에 사용할 수 있는 공간을 최대화하려면 TTL (수명), LRU (가장 최근에 사용되지 않음), LFU (가장 자주 사용되지 않음)와 같은 정책을 사용하세요.
효율적인 알고리즘 및 데이터 구조 사용
선택한 알고리즘과 데이터 구조에 따라 소프트웨어의 원시 계산 복잡성이 결정됩니다. 적절한 알고리즘과 데이터 구조를 선택하면 작업을 완료하는 데 필요한 CPU 사이클 수와 메모리 작업 수를 최소화할 수 있습니다. CPU 사이클과 메모리 작업이 적을수록 에너지 소비가 줄어듭니다.
최적의 시간 복잡도를 위한 알고리즘 선택
필요한 결과를 가장 짧은 시간에 달성하는 알고리즘에 우선순위를 둡니다. 이 접근 방식은 리소스 사용 기간을 줄이는 데 도움이 됩니다. 리소스 사용량을 최적화하는 알고리즘을 선택하려면 다음 방법을 사용하세요.
- 복잡성 감소에 집중: 복잡성을 평가하려면 런타임 측정항목을 넘어 알고리즘의 이론적 복잡성을 고려하세요. 예를 들어 버블 정렬과 비교할 때 병합 정렬은 대규모 데이터 세트의 계산 부하와 에너지 소비를 크게 줄입니다.
- 중복 작업 방지: 선택한 프로그래밍 언어 또는 프레임워크에서 최적화된 내장 함수를 사용합니다. 이러한 함수는 C 또는 C++와 같은 하위 수준의 에너지 효율적인 언어로 구현되는 경우가 많으므로 맞춤 코딩된 함수에 비해 기본 하드웨어에 더 최적화되어 있습니다.
효율성을 위해 데이터 구조 선택
선택한 데이터 구조에 따라 데이터를 검색, 삽입 또는 처리할 수 있는 속도가 결정됩니다. 이 속도는 CPU 및 메모리 사용량에 영향을 미칩니다. 효율적인 데이터 구조를 선택하려면 다음 방법을 사용하세요.
- 검색 및 검색에 최적화: 항목이 있는지 확인하거나 특정 값을 검색하는 것과 같은 일반적인 작업의 경우 속도에 최적화된 데이터 구조를 사용하는 것이 좋습니다. 예를 들어 해시 맵이나 해시 집합을 사용하면 거의 일정한 시간 조회가 가능하므로 배열을 선형으로 검색하는 것보다 에너지 효율적인 접근 방식입니다.
- 메모리 사용량 최소화: 효율적인 데이터 구조는 애플리케이션의 전체 메모리 사용량을 줄이는 데 도움이 됩니다. 메모리 액세스 및 관리가 줄어들어 전력 소비가 낮아집니다. 또한 메모리 프로필이 더 간소화되어 프로세스를 더 효율적으로 실행할 수 있으므로 리소스 업그레이드를 연기할 수 있습니다.
- 특수 구조 사용: 특정 문제에 맞게 설계된 데이터 구조를 사용합니다. 예를 들어 빠른 문자열 접두사 검색에는 트라이 데이터 구조를 사용하고, 가장 높거나 낮은 값에만 효율적으로 액세스해야 하는 경우에는 우선순위 대기열을 사용합니다.
컴퓨팅 및 데이터 작업 최적화
소프트웨어를 개발할 때는 전체 기술 스택에서 효율적이고 비례적인 리소스 사용에 집중하세요. CPU, 메모리, 디스크, 네트워크를 제한된 공유 리소스로 취급합니다. 효율적인 리소스 사용이 비용과 에너지 소비의 실질적인 감소로 이어진다는 점을 인식합니다.
CPU 사용률 및 유휴 시간 최적화
의미 있는 작업을 실행하지 않고 CPU가 활성 상태에서 에너지를 소비하는 시간을 최소화하려면 다음 방법을 사용하세요.
- 폴링보다 이벤트 기반 로직 선호: 리소스 집약적인 비지 루프 또는 지속적인 확인 (폴링)을 이벤트 기반 로직으로 대체합니다. 이벤트 기반 아키텍처는 애플리케이션의 구성요소가 관련 이벤트에 의해 트리거될 때만 작동하도록 합니다. 이 접근 방식을 사용하면 리소스 집약적인 폴링이 필요 없는 주문형 처리가 가능합니다.
- 일정한 고주파수 방지: CPU가 항상 최고 주파수로 작동하도록 강제하지 않는 코드를 작성합니다. 에너지 소비를 최소화하려면 유휴 상태인 시스템이 저전력 상태나 절전 모드로 전환될 수 있어야 합니다.
- 비동기 처리 사용: 유휴 대기 시간 동안 스레드가 잠기지 않도록 하려면 비동기 처리를 사용하세요. 이 접근 방식을 사용하면 리소스가 확보되고 전반적인 리소스 사용률이 높아집니다.
메모리 및 디스크 I/O 효율적으로 관리
메모리 및 디스크 사용량이 비효율적이면 불필요한 처리가 발생하고 전력 소비가 증가합니다. 메모리와 I/O를 효율적으로 관리하려면 다음 기법을 사용하세요.
- 엄격한 메모리 관리: 사용하지 않는 메모리 리소스를 적극적으로 해제하는 조치를 취합니다. 필요 이상으로 오랫동안 메모리에 큰 객체를 보유하지 마세요. 이 접근 방식을 사용하면 성능 병목 현상이 방지되고 메모리 액세스에 소비되는 전력이 줄어듭니다.
- 디스크 I/O 최적화: 영구 저장소 리소스와의 애플리케이션 읽기 및 쓰기 상호작용 빈도를 줄입니다. 예를 들어 중간 메모리 버퍼를 사용하여 데이터를 저장합니다. 고정된 간격으로 또는 버퍼가 특정 크기에 도달할 때 데이터를 영구 저장소에 씁니다.
- 일괄 작업: 빈번한 소규모 디스크 작업을 규모가 큰 소수의 일괄 작업으로 통합합니다. 일괄 작업은 많은 개별 소규모 트랜잭션보다 에너지를 적게 소비합니다.
- 압축 사용: 적절한 데이터 압축 기법을 적용하여 디스크에 쓰거나 디스크에서 읽는 데이터 양을 줄입니다. 예를 들어 Cloud Storage에 저장하는 데이터를 압축하려면 압축 해제 트랜스코딩을 사용하면 됩니다.
네트워크 트래픽 최소화
데이터 전송 작업 중에 네트워크 리소스가 상당한 에너지를 소비합니다. 네트워크 통신을 최적화하려면 다음 기법을 사용하세요.
- 페이로드 크기 최소화: 요청에 필요한 데이터만 전송하도록 API와 애플리케이션을 설계합니다. 필드가 몇 개만 필요한 경우 큰 JSON 또는 XML 구조를 가져오거나 반환하지 마세요. 반환되는 데이터 구조가 간결해야 합니다.
- 왕복 줄이기: 사용자 작업을 완료하는 데 필요한 네트워크 왕복 수를 줄이려면 더 스마트한 프로토콜을 사용하세요. 예를 들어 HTTP/1.1보다 HTTP/3을 선호하고, REST보다 GraphQL을 선택하고, 바이너리 프로토콜을 사용하고, API 호출을 통합합니다. 네트워크 호출 볼륨을 줄이면 서버와 최종 사용자 기기의 에너지 소비량이 모두 줄어듭니다.
프런트엔드 최적화 구현
프런트엔드 최적화는 최종 사용자가 다운로드하고 처리해야 하는 데이터를 최소화하여 최종 사용자 기기의 리소스 부하를 줄이는 데 도움이 됩니다.
코드 및 애셋 최소화
최종 사용자가 더 작고 효율적으로 구조화된 리소스를 다운로드하고 처리해야 하는 경우 기기에서 소비하는 전력이 줄어듭니다. 최종 사용자 기기의 다운로드 볼륨과 처리 부하를 최소화하려면 다음 기법을 사용하세요.
- 최소화 및 압축: JavaScript, CSS, HTML 파일의 경우 적절한 최소화 도구를 사용하여 공백 및 주석과 같은 불필요한 문자를 삭제합니다. 이미지와 같은 파일이 압축되고 최적화되었는지 확인합니다. CI/CD 파이프라인을 사용하여 웹 애셋의 최소화 및 압축을 자동화할 수 있습니다.
- 지연 로드: 이미지, 동영상, 중요하지 않은 애셋은 웹페이지의 뷰포트로 스크롤되는 등 실제로 필요할 때만 로드합니다. 이 접근 방식을 사용하면 초기 데이터 전송량과 최종 사용자 기기의 처리 부하가 줄어듭니다.
- 더 작은 JavaScript 번들: 최신 모듈 번들러와 트리 셰이킹과 같은 기법을 사용하여 JavaScript 번들에서 사용하지 않는 코드를 삭제합니다. 이 접근 방식을 사용하면 더 빨리 로드되고 서버 리소스를 더 적게 사용하는 파일이 생성됩니다.
- 브라우저 캐싱: HTTP 캐싱 헤더를 사용하여 사용자의 브라우저가 정적 애셋을 로컬에 저장하도록 지시합니다. 브라우저 캐싱은 후속 방문 시 반복적인 다운로드와 불필요한 네트워크 트래픽을 방지하는 데 도움이 됩니다.
경량 사용자 환경 (UX) 우선순위 지정
사용자 인터페이스의 디자인은 프런트엔드 콘텐츠를 렌더링하는 계산 복잡성에 큰 영향을 미칠 수 있습니다. 경량 UX를 제공하는 프런트엔드 인터페이스를 빌드하려면 다음 기법을 사용하세요.
- 효율적인 렌더링: 리소스 집약적이고 빈번한 문서 객체 모델 (DOM) 조작을 피하세요. 렌더링 복잡성을 최소화하고 불필요한 재렌더링을 없애는 코드를 작성합니다.
- 경량 설계 패턴: 적절한 경우 정적 사이트 또는 프로그레시브 웹 앱 (PWA)을 선호합니다. 이러한 사이트와 앱은 로드 속도가 더 빠르고 서버 리소스가 적게 필요합니다.
- 접근성 및 성능: 반응형이고 로드 속도가 빠른 사이트는 지속 가능하고 접근성이 뛰어난 경우가 많습니다. 최적화된 깔끔한 디자인은 콘텐츠가 렌더링될 때 소비되는 리소스를 줄여줍니다. 성능과 속도에 최적화된 웹사이트는 수익을 높이는 데 도움이 될 수 있습니다. Deloitte와 Google의 연구인 밀리초가 백만 달러를 만든다에 따르면 사이트 속도가 0.1초 (100ms) 개선되면 소매업 사이트의 전환이 8.4% 증가하고 평균 주문 금액이 9.2% 증가합니다.