대시보드

대시보드 설계

프리셋과 AI 위젯으로 충분하지 않을 때 CloudWatch 대시보드를 사용하면 CloudWatch 자체 지표 선택기, 지표 수학, 임계값을 활용해 큰 화면에서 지표를 선택하고, CloudFormation 또는 Terraform으로 관리할 수 있습니다.

2026년 10월 19일 업데이트

대시보드를 사용하는 이유

CloudPeek을 사용하는 데 대시보드가 꼭 필요하지는 않습니다. 프리셋과 AI 위젯은 대시보드 없이 작동합니다. 대시보드는 감시할 지표를 정확히 고르고 싶을 때 유용합니다. 직접 만든 사용자 지정 지표, 특정 리소스, 지표 수학, 임계값, 직접 고른 경보 등이 그렇습니다. 올바른 네임스페이스와 차원을 찾고, 지표 수학을 작성하고, 임계값을 설정하는 일은 키보드와 큰 화면에서 훨씬 쉬우며, CloudWatch에는 이미 이를 위한 도구가 있습니다.

그러면 CloudWatch 대시보드는 감시할 항목의 목록일 뿐입니다.

  • 각 위젯은 고정할 수 있는 단위입니다. 위젯은 하나 이상의 지표를 묶습니다. 인스턴스 3개의 CPU를 선 차트 하나에, 가장 큰 비용 5개를 막대 차트 하나에, 두 지표로 계산한 오류율을 숫자 하나에 담을 수 있습니다.
  • 각 대시보드는 함께 묶이는 위젯의 모음입니다. 서비스마다 하나, 지출용 하나, 온콜 담당용 하나. 원하는 만큼 여러 대시보드와 계정에서 고정할 수 있습니다.
  • 대시보드는 일반 JSON이므로 CloudFormation, Terraform, AWS CDK 등 문자열을 작성할 수 있는 모든 도구로 정의하고, 감시하는 서비스와 함께 배포할 수 있습니다.

이미 대시보드가 있나요? 바로 고정하세요. 또는 한눈에 보고 싶은 위젯만 담은 휴대폰 전용 작은 대시보드를 만드세요.

AWS 콘솔에서 설계

  1. CloudWatch 콘솔을 열고 대시보드 › 대시보드 생성을 선택한 다음 이름을 지정하세요.
  2. 위젯 유형을 선택하세요. 선, 누적 영역, 숫자, 게이지, 막대, 파이, 표, 텍스트 또는 경보 상태 중에서 선택할 수 있으며, 모두 CloudPeek에서 작동합니다(위젯 참조 페이지 참조).
  3. 찾아보기 탭에서 ApplicationELB나 직접 만든 네임스페이스 등 네임스페이스를 고른 다음, 이 위젯에 표시할 지표를 선택하세요.
  4. 그래프로 표시된 지표 탭에서 각 지표의 통계, 기간, 레이블을 설정하세요. 오류율 같은 표현식을 만들려면 수학 추가를 선택하고, 그래프에 표시하지 않을 입력 지표는 선택을 해제하세요.
  5. 옵션 탭에서 임계값에 대한 수평 주석을 추가하고 Y축 한도를 설정하세요. 게이지에는 최소값과 최대값이 모두 필요합니다.
  6. 위젯 생성을 선택하고 짧은 제목을 지정한 다음 대시보드를 저장하세요.

CloudPeek에서 대시보드를 열면 모든 위젯이 홈 화면에 표시될 모습 그대로 그려집니다. 원하는 위젯을 고정하거나 위젯 만들기 › 대시보드에서로 추가하세요(위젯 만들기 참조).

휴대폰에서 읽기 쉽게 만들기

홈 화면의 위젯은 너비가 몇 센티미터에 불과합니다. 몇 가지 습관만 들이면 훨씬 읽기 쉬워집니다.

  • 위젯 하나에 질문 하나. “API가 정상인가요?”라는 질문은 선 8개가 그려진 그래프 하나보다 오류율 숫자와 지연 시간 게이지로 보는 편이 더 읽기 쉽습니다.
  • 그래프당 시리즈는 적게. 중형 및 대형 위젯의 범례에는 시리즈가 최대 4개까지 표시되고, 나머지는 “외 N개”로 표시됩니다. 소형 위젯에는 범례가 아예 없습니다.
  • 짧은 제목. iPhone 및 iPad에서 잠금 화면의 인라인 위젯은 제목을 약 18자, 원형 위젯은 약 8자까지 표시합니다.
  • 한눈에 알아보기 쉬운 표시 방식 선택. "sparkline": true 설정을 사용한 숫자는 최신 값과 추세를, 게이지는 설정한 범위 안에서의 값을 보여 주고, 막대 차트는 항목의 순위를 보여 줍니다. 각 유형의 모양을 참조하세요.
  • 관심 있는 범위 설정. 위젯 자체의 start는 대시보드의 값보다 우선하며, 둘 다 없으면 CloudPeek은 지난 3시간을 표시합니다. 모든 위젯에는 표시하는 시간 범위가 나와 있습니다.
  • ID보다 레이블. 지표에 label을 지정하면 범례에 “app/checkout-api/50dc6c495c0c9188” 대신 “Checkout API”가 표시됩니다. ${PROP('Dim.ServiceName')} 같은 동적 레이블은 각 시리즈의 이름을 차원 값으로 지정합니다.

예시: API 상태 대시보드

Application Load Balancer용 위젯 3개입니다. 오류율은 숫자로, p99 지연 시간은 게이지로, 요청 수와 오류 수는 선 차트로 표시합니다. CloudPeek에서는 다음과 같이 보입니다.

오류율은 숨겨진 지표 2개로 계산하며, 5xx 선은 오른쪽에 별도의 눈금이 있습니다.
api-health.json다운로드
{
  "start": "-PT3H",
  "widgets": [
    {
      "type": "metric",
      "x": 0,
      "y": 0,
      "width": 6,
      "height": 6,
      "properties": {
        "title": "5xx error rate",
        "view": "singleValue",
        "region": "us-east-1",
        "period": 300,
        "sparkline": true,
        "metrics": [
          [ { "expression": "100 * FILL(m2, 0) / m1", "label": "Errors (%)", "id": "e1" } ],
          [ "AWS/ApplicationELB", "RequestCount", "LoadBalancer", "app/checkout-api/50dc6c495c0c9188", { "stat": "Sum", "id": "m1", "visible": false } ],
          [ ".", "HTTPCode_Target_5XX_Count", ".", ".", { "stat": "Sum", "id": "m2", "visible": false } ]
        ]
      }
    },
    {
      "type": "metric",
      "x": 6,
      "y": 0,
      "width": 6,
      "height": 6,
      "properties": {
        "title": "Latency p99",
        "view": "gauge",
        "region": "us-east-1",
        "stat": "p99",
        "period": 300,
        "yAxis": { "left": { "min": 0, "max": 2 } },
        "metrics": [
          [ "AWS/ApplicationELB", "TargetResponseTime", "LoadBalancer", "app/checkout-api/50dc6c495c0c9188", { "label": "p99 (s)" } ]
        ]
      }
    },
    {
      "type": "metric",
      "x": 12,
      "y": 0,
      "width": 12,
      "height": 6,
      "properties": {
        "title": "Requests and errors",
        "view": "timeSeries",
        "region": "us-east-1",
        "stat": "Sum",
        "period": 300,
        "metrics": [
          [ "AWS/ApplicationELB", "RequestCount", "LoadBalancer", "app/checkout-api/50dc6c495c0c9188", { "label": "Requests" } ],
          [ ".", "HTTPCode_Target_5XX_Count", ".", ".", { "label": "5xx", "yAxis": "right", "color": "#d62728" } ]
        ]
      }
    }
  ]
}
  • 오류율: 표현식 100 * FILL(m2, 0) / m1은 5xx 응답 수를 요청 수로 나눕니다. FILL은 오류가 없는 기간을 빈칸으로 두지 않고 0으로 계산합니다. 두 입력 모두 "visible": false로 설정되어 있으므로 비율만 표시됩니다.
  • 지연 시간: 게이지는 Y축의 min과 max를 범위로 사용합니다(여기서는 0~2초). 이 값이 없으면 CloudPeek은 0~100으로 간주합니다.
  • 요청 및 오류: "yAxis": "right"는 5xx 수에 별도의 눈금을 부여하므로, 몇 건 안 되는 오류가 수천 건의 요청에 묻혀 평평해지지 않습니다. "."은 바로 위 행의 같은 위치에 있는 값을 반복합니다.
  • app/checkout-api/50dc6c495c0c9188을 로드 밸런서 ARN에서 loadbalancer/ 뒤에 오는 이름으로 바꾸거나, 아래와 같이 CloudFormation 또는 Terraform이 채우도록 하세요.

코드로 관리

원하는 모습이 될 때까지 콘솔에서 대시보드를 설계한 다음, 작업 › 소스 보기/편집에서 JSON을 복사하여 인프라 코드에 넣으세요. 그러면 대시보드가 모니터링하는 서비스와 함께 검토, 버전 관리, 배포되며, 배포하는 모든 계정과 리전에서 동일하게 유지됩니다.

대시보드를 꼭 코드로 관리할 필요는 없습니다. 콘솔에서 편집한 대시보드도 마찬가지로 CloudPeek이 다음 새로고침 때 반영합니다.

대시보드를 CloudFormation이나 Terraform으로 관리하고 있다면 콘솔은 연습장으로만 사용하세요. 콘솔에서 저장한 변경 사항은 다음 배포 때 덮어써집니다. 콘솔에서 아이디어를 시도해 본 다음 소스를 다시 코드에 복사하세요(작업 › 소스 보기/편집).

JSON을 버전 관리 시스템에 보관하고 put-dashboard로 배포하세요. 콘솔에서 설계한 대시보드를 바탕으로 시작하려면:

Shell
aws cloudwatch get-dashboard \
  --dashboard-name Checkout-API \
  --query DashboardBody --output text > api-health.json

aws cloudwatch put-dashboard \
  --dashboard-name Checkout-API \
  --dashboard-body file://api-health.json

put-dashboard는 대시보드 전체를 교체하므로 파일이 항상 대시보드의 완전한 원본이 됩니다.

AWS::CloudWatch::Dashboard는 JSON을 문자열로 받습니다. !Sub로 감싸면 ID를 붙여 넣는 대신 로드 밸런서의 차원 값처럼 같은 스택의 값을 채워 넣을 수 있습니다.

CloudFormation
  CheckoutApiDashboard:
    Type: AWS::CloudWatch::Dashboard
    Properties:
      DashboardName: Checkout-API
      DashboardBody: !Sub
        - |
          {
            "start": "-PT3H",
            "widgets": [
              {
                "type": "metric", "x": 0, "y": 0, "width": 6, "height": 6,
                "properties": {
                  "title": "5xx error rate",
                  "view": "singleValue",
                  "region": "${AWS::Region}",
                  "period": 300,
                  "sparkline": true,
                  "metrics": [
                    [ { "expression": "100 * FILL(m2, 0) / m1", "label": "Errors (%)", "id": "e1" } ],
                    [ "AWS/ApplicationELB", "RequestCount", "LoadBalancer", "${Alb}", { "stat": "Sum", "id": "m1", "visible": false } ],
                    [ ".", "HTTPCode_Target_5XX_Count", ".", ".", { "stat": "Sum", "id": "m2", "visible": false } ]
                  ]
                }
              },
              {
                "type": "metric", "x": 6, "y": 0, "width": 6, "height": 6,
                "properties": {
                  "title": "Latency p99",
                  "view": "gauge",
                  "region": "${AWS::Region}",
                  "stat": "p99",
                  "period": 300,
                  "yAxis": { "left": { "min": 0, "max": 2 } },
                  "metrics": [
                    [ "AWS/ApplicationELB", "TargetResponseTime", "LoadBalancer", "${Alb}", { "label": "p99 (s)" } ]
                  ]
                }
              },
              {
                "type": "metric", "x": 12, "y": 0, "width": 12, "height": 6,
                "properties": {
                  "title": "Requests and errors",
                  "view": "timeSeries",
                  "region": "${AWS::Region}",
                  "stat": "Sum",
                  "period": 300,
                  "metrics": [
                    [ "AWS/ApplicationELB", "RequestCount", "LoadBalancer", "${Alb}", { "label": "Requests" } ],
                    [ ".", "HTTPCode_Target_5XX_Count", ".", ".", { "label": "5xx", "yAxis": "right", "color": "#d62728" } ]
                  ]
                }
              }
            ]
          }
        - Alb: !GetAtt LoadBalancer.LoadBalancerFullName
  • LoadBalancer는 같은 템플릿에 있는 AWS::ElasticLoadBalancingV2::LoadBalancer이며, 그 LoadBalancerFullName이 바로 CloudWatch의 LoadBalancer 차원에 필요한 값입니다.
  • !Sub 안에서 CloudFormation은 모든 ${…}를 자체 변수로 읽습니다. ${LAST} 같은 CloudWatch 동적 레이블은 ${!LAST}로 작성하세요.
  • 대시보드는 글로벌 리소스이지만 각 위젯은 자체 리전을 지정합니다. ${AWS::Region}은 스택의 리전을 사용합니다.

aws_cloudwatch_dashboard는 JSON을 문자열로 받습니다. HCL로 작성하고 jsonencode로 감싸면 ID를 붙여 넣는 대신 참조, 변수, for 표현식을 사용할 수 있습니다.

Terraform
resource "aws_lb" "checkout" {
  name    = "checkout-api"
  subnets = ["subnet-11111111", "subnet-22222222"]
}

locals {
  alb    = aws_lb.checkout.arn_suffix # the LoadBalancer dimension: app/checkout-api/…
  region = "us-east-1"                # where the load balancer is
}

resource "aws_cloudwatch_dashboard" "checkout_api" {
  dashboard_name = "Checkout-API"
  dashboard_body = jsonencode({
    start = "-PT3H"
    widgets = [
      {
        type = "metric", x = 0, y = 0, width = 6, height = 6
        properties = {
          title     = "5xx error rate"
          view      = "singleValue"
          region    = local.region
          period    = 300
          sparkline = true
          metrics = [
            [{ expression = "100 * FILL(m2, 0) / m1", label = "Errors (%)", id = "e1" }],
            ["AWS/ApplicationELB", "RequestCount", "LoadBalancer", local.alb, { stat = "Sum", id = "m1", visible = false }],
            [".", "HTTPCode_Target_5XX_Count", ".", ".", { stat = "Sum", id = "m2", visible = false }],
          ]
        }
      },
      {
        type = "metric", x = 6, y = 0, width = 6, height = 6
        properties = {
          title  = "Latency p99"
          view   = "gauge"
          region = local.region
          stat   = "p99"
          period = 300
          yAxis  = { left = { min = 0, max = 2 } }
          metrics = [
            ["AWS/ApplicationELB", "TargetResponseTime", "LoadBalancer", local.alb, { label = "p99 (s)" }],
          ]
        }
      },
      {
        type = "metric", x = 12, y = 0, width = 12, height = 6
        properties = {
          title  = "Requests and errors"
          view   = "timeSeries"
          region = local.region
          stat   = "Sum"
          period = 300
          metrics = [
            ["AWS/ApplicationELB", "RequestCount", "LoadBalancer", local.alb, { label = "Requests" }],
            [".", "HTTPCode_Target_5XX_Count", ".", ".", { label = "5xx", yAxis = "right", color = "#d62728" }],
          ]
        }
      },
    ]
  })
}
  • aws_lb의 arn_suffix가 바로 CloudWatch의 LoadBalancer 차원에 필요한 값입니다.
  • Terraform은 문자열 안의 ${…}를 보간으로 읽습니다. ${LAST} 같은 CloudWatch 동적 레이블은 $${LAST}로 작성하세요.
  • JSON을 파일로 보관하고 싶으신가요? dashboard_body = file("api-health.json")도 작동하며, 값을 채워 넣으려면 templatefile()을 사용하면 됩니다.
  • 콘솔에서 만든 대시보드를 Terraform으로 관리하려면 대시보드 이름을 id로 지정한 import 블록을 추가하거나 terraform import aws_cloudwatch_dashboard.checkout_api Checkout-API를 실행하세요.

AWS CDK, Pulumi 등 다른 도구도 같은 방식으로 작동합니다. 대시보드 본문을 설정할 수 있는 도구라면 무엇이든 CloudPeek에 표시할 내용을 정의할 수 있습니다.

변경 사항이 휴대폰에 반영되는 방식

  • 고정된 위젯이 AWS에서 새로고침될 때마다 CloudPeek은 대시보드를 다시 읽으므로, 콘솔에서 저장하거나 코드로 배포한 변경 사항은 다음 새로고침 때 표시됩니다. 바로 확인하려면 위젯의 새로고침 버튼을 탭하세요.
  • 대시보드 위젯을 이동하거나, 크기를 조정하거나, 제목을 바꾸거나, 지표를 변경해도 CloudPeek의 위젯은 해당 대시보드 위젯을 따라갑니다. CloudPeek이 어떤 위젯이었는지 알 수 없으면 마지막으로 찾은 버전을 계속 표시합니다.
  • 위젯 만들기의 미리보기에서 지정한 제목이나 리전, 그리고 CloudPeek의 편집에서 선택한 제목, 리전 또는 시간 범위는 그대로 유지되며, 대시보드의 내용이 무엇이든 그 위에 적용됩니다(위젯 편집하기 참조).
  • 대시보드를 삭제하거나 이름을 바꾸면 위젯은 마지막 데이터를 유지하고 대시보드 삭제됨이라고 표시합니다.
  • 같은 위젯을 다시 추가하면 그 위젯을 표시하던 홈 화면 위젯이 다시 연결됩니다(같은 위젯 다시 추가하기 참조).