0Pricing
DevOps Bootcamp · 강의

awk 배열과 그룹화를 활용한 집계

필드 값을 키로 사용하는 연관 배열로 합계, 개수 및 그룹별 요약을 계산합니다.

awk 배열과 그룹화를 활용한 집계은(는) CoddyKit의 무료 DevOps Bootcamp 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 DevOps Bootcamp 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. DevOps Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.

awk 연관 배열이란 무엇인가요?

awk에서 연관 배열은 키에 모든 문자열이나 숫자를 사용할 수 있는 키-값 저장소입니다. 대부분의 언어에서 사용하는 인덱스 배열과 달리 awk 배열은 내부적으로 해시 맵으로 구현되어 있어, 필드 값별로 데이터를 그룹화하고 집계하는 데 적합합니다.

  • 암시적으로 선언합니다. arr[key] = value처럼 대입하기만 하면 됩니다.
  • 키는 기본적으로 문자열입니다(숫자는 문자열로 변환됩니다).
  • 크기 제한이 없습니다. 필요한 만큼 awk가 배열을 확장합니다.
  • 한 번의 순회로 합계, 개수, 그룹별 집계를 계산하는 데 적합합니다.

증가시키기 전에 키를 초기화할 필요가 없습니다. awk는 설정되지 않은 키를 자동으로 0 또는 빈 문자열로 처리합니다.

그룹별 줄 개수 세기

가장 일반적인 집계 패턴은 필드에 나타나는 각 고유 값의 횟수를 세는 것입니다. 필드 $1(또는 다른 필드)을 배열 키로 사용하고, 일치하는 각 행에서 카운터를 증가시키면 됩니다.

END 블록은 모든 입력을 처리한 후 실행되므로, 누적된 결과를 출력할 위치로 사용합니다.

count[$1]++

처리가 끝나면 count에는 $1의 각 고유 값에 해당하는 전체 줄 수가 저장됩니다.

#!/usr/bin/env bash
# Count how many log entries exist per HTTP status code
# Input format: <ip> <date> <method> <path> <status> <bytes>
printf '10.0.0.1 2024-01-01 GET /index 200 512
10.0.0.2 2024-01-01 POST /api 404 128
10.0.0.3 2024-01-01 GET /img 200 2048
10.0.0.4 2024-01-01 GET /api 500 64
10.0.0.5 2024-01-01 DELETE /api 404 32
' | awk '
{
    count[$5]++
}
END {
    for (status in count)
        print status, count[status]
}'

그룹별 숫자 필드 합산

개수 세기는 집계의 한 형태일 뿐입니다. 다른 필드로 그룹을 나눈 뒤 숫자 필드의 합계를 구하려면, 그룹 필드를 키로 하는 배열에 숫자 값을 누적합니다.

패턴은 다음과 같습니다.

  • 키 = 그룹화 기준 필드(예: 사용자 이름을 나타내는 $1)
  • 값 = 숫자 필드의 현재까지의 합계(예: 바이트를 나타내는 $2)

이렇게 하면 정렬이나 사전 처리 없이 awk를 한 번만 실행하여 전체 그룹별 합계를 계산할 수 있습니다.

#!/usr/bin/env bash
# Sum bytes transferred per user from an access log
printf 'alice 1024
bob 512
alice 2048
charlie 256
bob 768
alice 128
' | awk '
{
    bytes[$1] += $2
}
END {
    for (user in bytes)
        printf "%-10s %d bytes\n", user, bytes[user]
}'

한 번의 순회로 개수와 합계 함께 계산하기

awk에서는 여러 배열을 동시에 유지할 수 있으므로, 파일을 한 번 훑는 동안 각 그룹의 개수와 합계(따라서 평균도)를 계산할 수 있습니다. 이는 파이프라인을 두 번 실행하는 것보다 훨씬 효율적입니다.

  • count[key]++ — 발생 횟수를 추적합니다.
  • total[key] += $N — 현재까지의 합계를 추적합니다.
  • END에서 total[k] / count[k]를 계산하면 그룹별 평균을 구할 수 있습니다.
#!/usr/bin/env bash
# Compute per-department headcount and average salary
printf 'Engineering Alice 95000
Engineering Bob 88000
Marketing Carol 72000
Marketing Dave 68000
Engineering Eve 102000
Marketing Frank 75000
' | awk '
{
    dept  = $1
    sal   = $3
    count[dept]++
    total[dept] += sal
}
END {
    printf "%-15s %5s %10s\n", "Department", "Count", "Avg Salary"
    for (d in count)
        printf "%-15s %5d %10.0f\n", d, count[d], total[d]/count[d]
}'

2차원 그룹화를 위한 다중 필드 키

여러 필드를 구분자와 연결하여 복합 키를 만들 수 있습니다. 이렇게 하면 별도의 문법 없이 2차원 그룹화를 수행할 수 있습니다.

데이터에 나타날 수 없는 구분자를 선택하세요(예: SUBSEP, awk에 내장된 레코드 구분자 \034, 또는 리터럴 파이프 문자 |).

  • 복합 키: arr[$1 SUBSEP $2] 또는 arr[$1"|"$2]
  • 출력할 때 키를 다시 분리하기: split(key, parts, "|")
#!/usr/bin/env bash
# Count requests grouped by HTTP method AND status code
printf 'GET 200
POST 201
GET 404
GET 200
DELETE 204
POST 201
GET 404
POST 500
' | awk '
{
    key = $1 "|" $2
    count[key]++
}
END {
    printf "%-8s %-6s %s\n", "Method", "Status", "Count"
    for (k in count) {
        split(k, parts, "|")
        printf "%-8s %-6s %d\n", parts[1], parts[2], count[k]
    }
}'

그룹별 최솟값과 최댓값 추적

연관 배열을 사용하면 그룹별 최솟값과 최댓값을 쉽게 추적할 수 있습니다. 핵심은 특수 조건 !(key in arr)을 사용하여 각 키가 처음 나타날 때만 초기화하는 것입니다.

  • !(key in min_arr)은 키가 처음 발견되었을 때 참입니다.
  • 초기화한 후에는 표준 미만/초과 비교를 사용하여 비교하고 값을 덮어씁니다.

이 패턴을 사용하면 최솟값을 잘못된 0으로 만드는 문제를 피할 수 있습니다.

#!/usr/bin/env bash
# Find min and max response time per endpoint
printf '/api/users 120
/api/orders 340
/api/users 98
/api/orders 512
/api/users 210
/api/orders 280
/health 5
/health 7
' | awk '
{
    ep  = $1
    rt  = $2
    if (!(ep in mn)) { mn[ep] = rt; mx[ep] = rt }
    if (rt < mn[ep]) mn[ep] = rt
    if (rt > mx[ep]) mx[ep] = rt
}
END {
    printf "%-15s %6s %6s\n", "Endpoint", "Min", "Max"
    for (ep in mn)
        printf "%-15s %6d %6d\n", ep, mn[ep], mx[ep]
}'

빈도 분포 — 상위 N개 그룹

실무에서 흔히 수행하는 작업 중 하나는 가장 자주 나타나는 상위 N개 값을 찾는 것입니다. awk로 개수를 센 다음 sort와 head를 파이프로 연결하여 순위를 매기고 필요한 부분만 추출합니다.

이 파이프라인 패턴은 셸 프로그래밍에서 관용적으로 사용됩니다.

  1. awk가 배열에 발생 횟수를 세고, END에서 count key를 출력합니다.
  2. sort -rn이 숫자를 내림차순으로 정렬합니다.
  3. head -n 5가 상위 5개만 남깁니다.

집계는 awk에 맡기고 정렬은 sort에 위임하는 방식은 Unix 철학을 따릅니다.

#!/usr/bin/env bash
# Top 3 most active IP addresses from an access log
printf '192.168.1.10 GET /index
10.0.0.5 POST /api
192.168.1.10 GET /css
172.16.0.3 GET /index
10.0.0.5 GET /api
192.168.1.10 DELETE /api
172.16.0.3 POST /login
10.0.0.5 GET /index
10.0.0.5 POST /logout
' | awk '{count[$1]++} END {for (ip in count) print count[ip], ip}' \
  | sort -rn \
  | head -n 3

여러 파일 집계에 NR과 FNR 사용하기

여러 파일을 처리할 때 awk에 내장된 NR(읽은 전체 레코드 수)과 FNR(현재 파일에서 읽은 레코드 수)를 사용하면 FILENAME으로 각 레코드가 어느 파일에서 왔는지 표시할 수 있습니다.

  • FILENAME — 현재 읽고 있는 파일의 이름
  • FNR == 1 — 각 새 파일의 시작에서 실행됩니다(헤더를 건너뛸 때 유용합니다).

이를 통해 awk를 한 번 호출하는 것만으로 전체 로그 파일 디렉터리에서 파일별 그룹 집계를 수행할 수 있습니다.

awk 배열의 정렬된 출력 출력하기

awk의 for (key in array) 반복문은 순서를 보장하지 않습니다. 일관된 출력을 얻으려면 awk의 END 출력 결과를 sort로 파이프에 연결하거나, 값을 수집한 뒤 asorti / asort 함수로 awk 내부에서 정렬하세요(GNU awk에서만 지원).

플랫폼 간 스크립트에서 이식성이 필요한 경우에는 일반적으로 셸 파이프라인 방식을 선호합니다.

  • sort -k1,1 — 첫 번째 필드(그룹 키)를 알파벳순으로 정렬합니다.
  • sort -k2,2rn — 두 번째 필드(개수/합계)를 숫자 기준 내림차순으로 정렬합니다.
#!/usr/bin/env bash
# Bytes per user, sorted alphabetically by username
printf 'zara 800
alice 1500
bob 300
alice 200
zara 400
bob 1100
' | awk '
{
    total[$1] += $2
}
END {
    for (u in total)
        print u, total[u]
}' | sort -k1,1

배열 키 삭제 및 상태 초기화

스트림을 처리하는 도중 집계 상태를 초기화해야 할 때가 있습니다. 예를 들어 로그 파일의 각 구역이 빈 줄이나 특정 표식 값으로 구분되어 있는 경우입니다.

  • delete arr[key] — 단일 항목을 삭제합니다.
  • delete arr — 전체 배열을 초기화합니다(GNU awk).
  • 존재 여부를 (key in arr)로 확인한 후 접근하면 유령 항목이 생성되는 것을 방지할 수 있습니다.

이 기법을 사용하면 awk를 다시 시작하지 않고도 슬라이딩 윈도우 또는 구역별 집계를 수행할 수 있습니다.

#!/usr/bin/env bash
# Sum values within each section delimited by "---"
printf 'alice 100
bob 200
---
alice 50
bob 75
charlie 300
---
' | awk '
/^---/ {
    print "-- Section totals --"
    for (u in total) printf "  %-10s %d\n", u, total[u]
    delete total
    next
}
{
    total[$1] += $2
}'

실전 파이프라인: Nginx 로그 요약

지금까지 배운 내용을 모두 적용해 보겠습니다. 다음은 Nginx 결합 로그 형식에 대해 awk를 한 번만 실행하여 집계하는 운영 환경 수준의 예입니다. 한 번의 순회로 가상 호스트별 요청 개수, 전체 바이트 수, 오류율을 계산합니다.

사용된 핵심 기법은 다음과 같습니다.

  • 복합 키: 필드에서 추출한 vhost
  • 병렬 배열: reqs[], bytes[], errors[]
  • 조건부 누적: 오류 응답만 세기 위한 $9 >= 400
  • END에서 형식을 지정한 printf 표 출력
#!/usr/bin/env bash
# Simulated Nginx combined log: host ip - - [date] "METHOD /path HTTP/1.1" status bytes
printf 'api.example.com 10.0.0.1 - - [01/Jan/2024] "GET /v1" 200 1024
www.example.com 10.0.0.2 - - [01/Jan/2024] "GET /" 200 4096
api.example.com 10.0.0.3 - - [01/Jan/2024] "POST /v1" 500 128
www.example.com 10.0.0.4 - - [01/Jan/2024] "GET /img" 404 64
api.example.com 10.0.0.5 - - [01/Jan/2024] "GET /v1" 200 2048
www.example.com 10.0.0.6 - - [01/Jan/2024] "GET /" 200 4096
api.example.com 10.0.0.7 - - [01/Jan/2024] "DELETE /v1" 403 32
' | awk '
{
    host = $1; status = $9; b = $10
    reqs[host]++
    bytes[host] += b
    if (status + 0 >= 400) errors[host]++
}
END {
    printf "%-20s %6s %10s %6s\n", "Host", "Reqs", "Bytes", "Errors"
    for (h in reqs)
        printf "%-20s %6d %10d %6d\n", h, reqs[h], bytes[h], errors[h]+0
}'

이해도 확인: 최솟값을 올바르게 초기화하기

일반적인 awk 집계 실수에 대한 이해도를 확인해 보세요.

단원 요약: awk 배열을 사용한 집계

awk 내부에서 그룹별 집계를 계산하는 핵심 패턴을 배웠습니다.

  • 개수 세기: count[$key]++ — 각 행에서 증가시키고 END에서 출력합니다.
  • 합산: total[$key] += $N — 그룹별 숫자 필드를 누적합니다.
  • 평균: count[]와 total[]을 모두 유지하고 END에서 나눕니다.
  • 최솟값/최댓값: !(key in arr)을 사용하여 첫 발생 시 초기화한 다음 비교합니다.
  • 복합 키: 필드를 구분자와 연결하여 다차원 그룹화를 수행합니다.
  • 정렬된 출력: 일관된 순서를 위해 awk의 END 출력을 sort로 파이프에 연결합니다.
  • 구역 초기화: delete arr을 사용하여 입력의 논리적 구역 사이에서 상태를 지웁니다.

이러한 패턴을 사용하면 복잡한 데이터베이스 질의나 여러 파이프라인 실행을 하나의 효율적인 awk 호출로 대체할 수 있습니다. 이는 운영 환경의 셸 프로그래밍에 필수적인 기술입니다.

자주 묻는 질문

“awk 배열과 그룹화를 활용한 집계” 강의는 무료인가요?

네 — “awk 배열과 그룹화를 활용한 집계” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 DevOps Bootcamp 강의 전체를 잠금 해제할 수 있습니다. DevOps Bootcamp 강의에는 총 4개의 강의가 포함되어 있습니다.

“awk 배열과 그룹화를 활용한 집계”에서 뭘 배우나요?

필드 값을 키로 사용하는 연관 배열로 합계, 개수 및 그룹별 요약을 계산합니다. 브라우저에서 직접 실행하는 실습 코드로 DevOps Bootcamp을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

DevOps Bootcamp을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 DevOps Bootcamp은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“awk 배열과 그룹화를 활용한 집계” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 DevOps Bootcamp 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 DevOps Bootcamp 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. awk의 레코드, 필드 및 사용자 지정 구분자
  2. 패턴, 범위 및 BEGIN/END 블록
  3. awk 배열과 그룹화를 활용한 집계
  4. awk 함수, printf 서식 지정 및 보고서 생성
← DevOps Bootcamp(으)로 돌아가기