Step 3. 파이프(|) — 명령을 조립하는 사고방식

Step 3. 파이프(|) — 명령을 조립하는 사고방식

Level 0 — 컴퓨터 조작과 구조의 이해 | 난이도 ★★☆☆☆ | 예상 소요 시간 2~3시간

전제: Step 2 완료. 윈도우 파워쉘에서 진행합니다.

  • 준비물: 윈도우 PC, 파워쉘.
  • 안전: 오늘 실험은 전부 "읽기"입니다. 시스템을 바꾸는 명령이 없으니 마음껏 쳐 보세요.
  • 주의: 오늘 나오는 문법 두 개({}$_)가 좀 낯섭니다. 지금 완벽히 이해하려 하지 말고, 통째로 따라 치며 감각부터 익히세요. 왜 그런지는 뒤에서 설명합니다.

오늘은 개념적으로 가장 중요한 날 중 하나입니다. 명령 하나하나는 도구일 뿐이고, 파이프는 그 도구들을 "조립"하는 방법입니다. 보안 조사의 대부분은 "이상하게 오래 도는 프로세스만 골라 줘", "수만 줄 로그에서 실패한 로그인만 뽑아 줘" 같은 문제 — 전부 "목록 → 필터 → 정렬 → 자르기"의 조립입니다. 이 조립 사고가 익숙해지면, 낯선 문제도 같은 뼈대로 풀리기 시작합니다.


1. 학습 목표

이 챕터를 끝내면 다음을 할 수 있습니다:

  • 파이프(|)로 명령의 출력을 다음 명령의 입력으로 넘긴다
  • Sort-Object, Select-Object -First N, Where-Object 세 기계를 조립한다
  • "○○한 것 상위 N개" 형태의 조합 명령을 스스로 설계한다
  • 모르는 명령의 속성(꼬리표)을 Get-Member로 조사한다

2. 배경 지식 — 오늘의 도구와 개념

오늘의 도구 한눈에 보기

구분 내용
언어·환경 파워쉘 5.1 — 오늘의 주인공은 파이프(`
오늘의 명령어 Sort-Object(정렬), Select-Object -First N(자르기), Where-Object(필터), Get-Member(속성 조사), Measure-Object(개수)
필요한 개념 객체(object)와 속성(property), $_{} 문법, 비교 연산자 -eq/-gt

공장을 상상해 보세요. 원재료가 컨베이어 벨트 위를 지나가고, 각 공정의 기계가 재료를 받아서 자기 일을 하고 다음 기계로 넘깁니다.

원재료 → [자르기] → [다듬기] → [포장] → 완성품

파워쉘의 파이프(|)가 바로 이 컨베이어 벨트입니다. 왼쪽 명령의 결과물이 벨트를 타고 오른쪽 명령의 재료가 됩니다.

2-1. 파워쉘 파이프의 비밀 — 글자가 아니라 물건이 지나간다

리눅스의 파이프(Step 19에서 배웁니다)는 글자(텍스트)를 넘깁니다. 그래서 "몇 번째 단어만 잘라내기" 같은 눈속임이 필요하죠.

파워쉘은 다릅니다. 벨트 위를 지나가는 게 글자가 아니라 객체(object) — "꼬리표가 달린 물건"입니다. 예를 들어 Get-Process가 넘기는 건 프로세스 하나하나인데, 각각에 이런 꼬리표(속성, property)가 붙어 있습니다:

프로세스 객체 하나
├── Name: "chrome"
├── CPU: 245.3
├── WorkingSet: 892345600
├── Id: 4520
└── ...

그래서 오른쪽 명령은 "글자를 뜯어 맞추기"가 아니라 꼬리표 이름으로 정확히 집어냅니다. Sort-Object CPU는 "CPU라는 꼬리표를 기준으로 정렬해"라는 뜻이고, 화면에 어떻게 보이든 상관없이 정확합니다. 이게 "파워쉘 파이프는 정확하다"는 말의 의미입니다.

2-2. 오늘의 기계(명령) 소개

명령 역할 공장 비유
Sort-Object 속성 기준 속성으로 정렬 줄 세우기 기계
Select-Object -First N 앞에서 N개만 자르기 기계
Where-Object {조건} 조건에 맞는 것만 통과 검수 기계
Get-Member 꼬리표(속성) 목록 보기 설계도 열어보기

2-3. $_ 와 {} — 검수 기계의 사용법

Where-Object만 문법이 특이합니다:

Where-Object {$_.CPU -gt 100}

읽는 법:

  • {} (중괄호): "이 안에 검사 조건이 있습니다"
  • $_ : "벨트 위를 지금 지나가는 이 물건 하나"를 가리키는 대명사
  • $_.CPU : "지나가는 물건의 CPU 꼬리표"
  • -gt : "greater than, ~보다 큰"

통째로 읽으면: "지나가는 각 물건에 대해, CPU가 100보다 큰 것만 통과시켜라."

비교 연산자는 수학 기호 대신 글자를 씁니다:

기호
-eq 같다 (equal)
-ne 다르다 (not equal)
-gt 크다 (greater than)
-lt 작다 (less than)

처음엔 이 문법이 외계어처럼 보입니다. 정상입니다. 오늘은 통째로 외워서 쓰고, 이해는 반복하며 따라오게 두세요 — 실은 이게 문법 습득의 지름길입니다.


3. 따라 하기

3-1. 재료 확인 — Get-Process

Get-Process
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    238      15     5120      18420       0.23   4520   1 ApplicationFrameHost
   2156      89   185412     245800      45.12   8812   1 chrome
...

지금 이 컴퓨터에서 실행 중인 프로그램(프로세스) 목록입니다. 컬럼을 봅시다:

  • ProcessName — 프로그램 이름
  • CPU(s) — 지금까지 쓴 CPU 시간(초)
  • WS(K) — 메모리 사용량
  • Id — 프로세스 번호(PID)

양이 많아서 화면을 가득 채웁니다. 이 재료를 이제 가공해 봅시다.

3-2. 첫 파이프 — 정렬하기

Get-Process | Sort-Object CPU -Descending

같은 목록인데, 이번엔 CPU를 많이 쓴 순서로 나옵니다. 읽는 법:

  • | — "왼쪽 결과를 오른쪽으로 넘겨라"
  • Sort-Object CPU — "CPU 꼬리표 기준으로 정렬해"
  • -Descending — "내림차순(큰 것부터)". 빼면 오름차순(작은 것부터)

잠깐 멈추고 체감하세요: 방금 일어난 일은 "왼쪽 기계가 만든 물건이, 벨트를 타고 오른쪽 기계의 재료가 된 것"입니다. Sort-Object는 Get-Process가 뭔지 몰라도 됩니다 — 벨트 위의 물건을 정렬하는 게 자기 일이니까요.

3-3. 벨트 연장 — 앞의 10개만

정렬은 됐는데 전부 다 나오니 여전히 깁니다. 벨트에 기계를 하나 더 달아 봅니다:

Get-Process | Sort-Object CPU -Descending | Select-Object -First 10
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    614      26    31684      28228  11,861.81  24832   1 cloud-drive-daemon
   1997      97   753512     309468   4,024.48  41684   1 ChatGPT
   2453      64   521032     168260   3,970.92  35616   1 chrome
... (딱 10줄만 나옴)
  • Select-Object -First 10 — "앞에서 10개만 골라라"

이제 읽기 좋습니다. "CPU 상위 10개 프로세스" — 작업 관리자에서 CPU 열 눌러 정렬한 것과 같은 정보를, 명령 한 줄로 얻었습니다. (위 출력은 실제 실행 결과입니다 — 당신 화면의 1위는 다른 프로그램일 수 있습니다.)

예측해 보기: Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 5는 뭘 보여 줄까요? CPU 자리에 WorkingSet이 들어갔습니다. 예측한 뒤 실행해 보세요.
(정답: 메모리를 많이 쓰는 상위 5개 프로세스. 꼬리표 이름만 바꿨을 뿐인데 완전히 다른 질문에 답했습니다 — 이게 조립의 힘입니다.)

3-4. 검수 기계 — Where-Object

이번엔 정렬이 아니라 필터입니다.

Get-Process | Where-Object {$_.CPU -gt 100}

CPU를 100초 넘게 쓴 프로세스만 남습니다. (없으면 아무것도 안 나올 수 있습니다 — 그건 "해당 없음"이라는 정상 결과입니다. 숫자를 50이나 10으로 낮춰 다시 쳐 보세요.)

이 명령은 벨트 위를 지나가는 프로세스 하나하나를 붙잡고 묻습니다: "너 CPU 100 넘어?" — 넘으면 통과, 아니면 폐기.

이번엔 이름으로 골라 봅시다:

Get-Process | Where-Object {$_.ProcessName -eq "powershell"}

이름이 정확히 powershell인 프로세스만 남습니다. (지금 파워쉘이 켜져 있으니 최소 1개는 나와야 정상입니다.)

3-5. 꼬리표가 궁금하면 — Get-Member

"CPU 말고 또 어떤 꼬리표가 있지?" 궁금할 때의 명령:

Get-Process | Get-Member
   TypeName: System.Diagnostics.Process

Name        MemberType    Definition
----        ----------    ----------
...
CPU         Property      double CPU {get;}
Id          Property      int Id {get;}
ProcessName Property      string ProcessName {get;}
WorkingSet  Property      long WorkingSet {get;}
...

Property라고 적힌 것들이 전부 꼬리표 후보입니다. 이 목록을 보고 "아, 이런 속성도 있구나" 하고 다음 조합의 아이디어를 얻으면 됩니다. 모르는 명령의 속성이 궁금할 때 Get-Member — 앞으로 수백 번 쓰게 될 조사 습관입니다.

3-6. 파일에도 같은 생각을 — 응용 조합

파이프는 프로세스 전용이 아닙니다. Get-ChildItem(파일 목록)도 똑같이 벨트에 올릴 수 있습니다:

Get-ChildItem $HOME | Sort-Object Length -Descending | Select-Object -First 5

읽는 법: "내 홈의 파일 목록을 얻어서 → 크기(Length) 큰 순으로 정렬 → 5개만." "내 홈에서 가장 큰 파일 5개는?"이라는 질문에 명령 한 줄로 답했습니다. 디스크 정리할 때 쓰는 실전 조합입니다.

지금까지의 패턴을 정리하면:

(목록 얻기) | (가공: 정렬/필터) | (자르기)

이 뼈대에 재료와 조건만 갈아 끼우면 되는 겁니다.


4. 미션과 연습문제

미션 — 조립 설계사

다음 질문들에 답하는 명령을 스스로 조립해 보세요. 정답은 5번 섹션에 있지만, 먼저 만들어 보고 실행해 본 뒤 비교하세요.

  1. "메모리(WorkingSet)를 500MB(=524288000) 넘게 쓰는 프로세스만 보여 줘"
  2. "이름이 powershell인 프로세스가 지금 몇 개인지 보여 줘" (힌트: 필터 뒤에 | Measure-Object를 붙이면 개수를 세어 줍니다)
  3. "C:\Windows\System32에서 가장 최근에 수정된 파일 3개를 보여 줘" (힌트: 수정 시각 꼬리표는 LastWriteTime)
  4. "프로세스를 이름순(가나다)으로 정렬해서 앞 10개만 보여 줘" (힌트: 이번엔 -Descending이 필요할까요?)

연습문제

문제 1. 파워쉘의 파이프가 리눅스 파이프와 다른 점 하나를 설명하세요.

문제 2. Where-Object {$_.Length -gt 1000000}에서 $_는 무엇을 가리키나요?

문제 3. "내 홈 폴더에서 크기가 0인 파일만 찾아 줘"를 명령으로 조립해 보세요.

문제 4. 어떤 명령의 출력에서 쓸 수 있는 속성(꼬리표) 목록을 알고 싶습니다. 어떤 명령을 뒤에 붙이면 되나요?


5. 모범 답안과 완료 기준

미션 해설

# 1
Get-Process | Where-Object {$_.WorkingSet -gt 524288000}
# 2
Get-Process | Where-Object {$_.ProcessName -eq "powershell"} | Measure-Object
# 3
Get-ChildItem C:\Windows\System32 | Sort-Object LastWriteTime -Descending | Select-Object -First 3
# 4
Get-Process | Sort-Object ProcessName | Select-Object -First 10

몇 개나 맞혔는지보다 중요한 건, 틀린 문제에서 어느 기계를 잘못 골랐는지 복습하는 겁니다.

연습문제 해답

문제 1 해답. 리눅스 파이프는 글자(텍스트)를 넘기지만, 파워쉘 파이프는 객체(속성/꼬리표가 붙은 물건)를 넘깁니다. 그래서 파워쉘은 화면 표시와 무관하게 속성 이름으로 정확하게 정렬·필터할 수 있습니다.

문제 2 해답. 파이프(벨트) 위를 지금 지나가는 항목 하나를 가리키는 대명사입니다. $_.Length는 "지금 지나가는 그 항목의 Length 속성"입니다.

문제 3 해답.

Get-ChildItem $HOME -File | Where-Object {$_.Length -eq 0}

(-File을 빼도 동작하지만, 폴더까지 섞여 나옵니다. 비교는 -eq=가 아닙니다!)

문제 4 해답. | Get-Member를 붙입니다. 예: Get-ChildItem | Get-Member. Property로 표시된 줄들이 정렬·필터에 쓸 수 있는 속성 후보입니다.

완료 기준 체크리스트

  • [ ] 파이프 |가 "왼쪽 결과를 오른쪽 재료로 넘긴다"는 걸 설명할 수 있다
  • [ ] 파워쉘이 글자 대신 "객체(꼬리표 달린 물건)"를 넘긴다는 걸 안다
  • [ ] Get-Process | Sort-Object ... | Select-Object -First N 조합을 만들 수 있다
  • [ ] Where-Object {$_ ... } 껍데기를 외워서 쓸 수 있다
  • [ ] 속성이 궁금할 때 Get-Member를 찾는 습관이 생겼다
  • [ ] 미션 4문제를 스스로 조립해 봤다

6. 흔한 실수와 해결

벽 1. Where-Object가 하나도 통과시키지 않는다 (빈 결과)

원인 후보 셋: ① 조건의 숫자가 너무 크다 — 기준을 낮춰 보세요. ② 속성 이름 오타 — Get-Process | Get-Member로 정확한 철자를 확인. ③ 비교 대상이 글자인데 숫자처럼 비교 (또는 반대). 빈 결과는 고장이 아니라 "해당 없음"일 수 있다는 것도 기억하세요.

벽 2. {} 나 $_ 를 빼먹었다

Where-Object $_.CPU -gt 100처럼 중괄호 없이 치면 오류가 납니다. 이 명령만은 형태가 특이하니, 일단 Where-Object { $_.속성 비교 }라는 껍데기째로 외우세요. 안의 내용만 바꾸는 겁니다.

벽 3. = 를 썼다가 오류 (또는 이상한 결과)

파워쉘에서 =는 "대입"(변수에 넣기)이지 "같다 비교"가 아닙니다. 비교는 -eq, 크기는 -gt/-lt. 수학 기호를 쓰고 싶은 유혹이 오지만, 파워쉘의 전통입니다.

벽 4. 정렬이 숫자가 아니라 글자 순서로 된 것 같다

드물게, 속성이 글자(string)로 저장된 경우 "10"이 "9"보다 앞에 오는 식으로 정렬됩니다. Get-Process의 CPU/WorkingSet은 숫자라 이 문제가 없지만, 나중에 CSV 파일 등을 다룰 때 만나는 함정이니 기억해 두세요.

벽 5. 파이프 다음에 뭘 붙여야 할지 모르겠다

공식처럼 외우세요: "목록 얻고 → 가공하고 → 자른다." 그리고 헷갈리면 한 칸씩 치세요. Get-Process만 쳐 보고, 거기에 | Sort-Object ...를 붙여 보고, 또 | Select-Object ...를 붙여 보는 식으로. 한 칸씩 결과를 눈으로 확인하며 벨트를 늘리는 게 초보의 정석입니다.


7. 정리

오늘의 조립 부품

기계(명령) 역할
Sort-Object 속성 -Descending 정렬 (큰 것부터) Sort-Object CPU -Descending
Select-Object -First N 앞 N개 자르기 Select-Object -First 10
Where-Object {$_.속성 조건} 조건 필터 Where-Object {$_.CPU -gt 100}
Get-Member 속성 목록 조사 Get-Process | Get-Member
Measure-Object 개수 세기 ... | Measure-Object

비교 연산자

-eq(같다) / -ne(다르다) / -gt(크다) / -lt(작다)

만능 뼈대

(목록 얻기) | (정렬 또는 필터) | (자르기)

명령어보다 중요한 감각

"문제를 컨베이어 벨트로 번역하라." "이상한 프로세스 찾아 줘"는 곧 "목록 얻고 → 조건으로 거르고 → 보기 좋게 자른다"입니다. 그리고 한 칸씩 붙여 가며 확인하는 것이 초보의 조립법입니다.

알아두면 좋은 것 하나: Select-Object-First N 말고도 Select-Object ProcessName, CPU처럼 보고 싶은 꼬리표(컬럼)만 골라서 출력하는 재주가 있습니다. Get-Process | Select-Object ProcessName, CPU -First 5를 쳐 보세요 — 보고서 만들 때 쓰는 기술입니다.


전부 체크되면 Step 3 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.