Step 4. 텍스트 처리 — 로그에서 바늘 찾기
Level 0 — 컴퓨터 조작과 구조의 이해 | 난이도 ★★☆☆☆ | 예상 소요 시간 2~3시간
전제: Step 3 완료 (파이프). 윈도우 파워쉘에서 진행합니다.
- 준비물: 윈도우 PC, 파워쉘.
- 안전: 오늘도 읽기와 연습 파일 만들기뿐이라 안전합니다. 연습 파일은 직접 만들어 씁니다 — 50줄짜리 가짜 로그를 만들고 그 안에서 수사 연습을 합니다.
- 주의: 한글이 깨지는 사건을 만날 수 있습니다. 당황하지 마세요 — 오늘 그 원인(인코딩)까지 정복합니다.
오늘의 주인공은 "로그"입니다. 컴퓨터 세계의 모든 것은 기록을 남깁니다 — 로그인 성공/실패, 프로그램 오류, 접속 기록. 그리고 그 기록은 전부 텍스트 파일입니다. 사고 조사는 "ERROR가 든 줄만 보여 줘" 한 줄로 시작해서, 몇만 줄이 몇십 줄로 줄어들며 이야기가 보이기 시작합니다. 오늘 배우는 "텍스트에서 원하는 줄 뽑기"는 보안 분석의 알파이자 오메가입니다.
1. 학습 목표
이 챕터를 끝내면 다음을 할 수 있습니다:
Get-Content로 파일을 읽고, 긴 파일은 앞부분만 슬쩍 본다Select-String으로 원하는 단어가 든 줄만 골라낸다- 결과 건수를 세고, 결과를 새 파일로 저장해 "조사 문서"를 만든다
파일명:줄번호:내용형식으로 여러 파일을 한꺼번에 수사한다- 한글 깨짐의 원인(인코딩 불일치)을 설명하고
-Encoding으로 대응한다
2. 배경 지식 — 오늘의 도구와 개념
오늘의 도구 한눈에 보기
| 구분 | 내용 |
|---|---|
| 언어·환경 | 파워쉘 5.1, 텍스트 파일(로그) 처리 |
| 오늘의 명령어 | Get-Content(읽기), Select-String(검색), Measure-Object(개수), Out-File(저장) |
| 오늘의 옵션 | -TotalCount(앞부분만), -Path/-Pattern(검색 대상/패턴), -Encoding(인코딩 지정) |
| 필요한 개념 | 텍스트 파일 = 줄의 나열, 인코딩(글자↔숫자 변환표), 패턴 안의 |(또는) |
오늘 배우는 명령들을 사건 현장의 언어로 번역하면 이렇습니다: Select-String은 "수만 줄의 로그에서 수상한 줄만 낚는" 침해 조사의 1번 공구, Measure-Object는 "새벽 2~4시에 실패 로그인 300건" 같은 문장을 만드는 도구, Out-File -Encoding utf8은 "증거를 깨지지 않게 보관하는" 장치입니다. 보안 담당자의 일상은 거창한 해킹 도구보다, 오늘 같은 명령들로 로그와 씨름하는 시간이 훨씬 깁니다.
2-1. 텍스트 파일의 구조 — "줄"이 단위다
텍스트 파일은 안을 열어 보면 결국 줄(line)의 나열입니다. 그리고 오늘 배우는 도구들은 전부 "줄 단위"로 일합니다:
Get-Content: 파일을 줄들의 목록으로 읽어 온다 (한 줄 = 객체 하나)Select-String: 각 줄을 검사해서 조건에 맞는 줄만 골라낸다
Step 3에서 "목록 → 필터"를 배웠죠? 텍스트 처리도 정확히 같은 사고입니다. 재료가 프로세스에서 "줄"로 바뀌었을 뿐입니다.
2-2. 인코딩 — 글자를 숫자로 바꾸는 변환표
컴퓨터는 글자를 저장할 수 없습니다. 숫자만 저장할 수 있죠. 그래서 "글자 ↔ 숫자" 변환표가 필요하고, 그 표가 인코딩입니다.
문제는 이 표가 여러 종류라는 겁니다:
| 인코딩 | 특징 |
|---|---|
| UTF-8 | 현재 세계 표준. 한글/영문/이모지 전부 표현 |
| UTF-16 | 윈도우 내부에서 자주 쓰는 방식 |
| EUC-KR / CP949 | 옛날 한국 윈도우 표준 |
한글이 깨지는 이유의 90%: 파일은 A표(예: UTF-8)로 숫자화해서 저장했는데, 읽는 프로그램이 B표(예: CP949)로 해석하는 경우입니다. 같은 숫자인데 다른 표로 읽으니 글자가 괴상해지는 겁니다. 암호를 열쇠가 다른 자물쇠로 여는 것과 같습니다.
해결책: 읽을 때 "이 표로 읽어라"를 명시하는 것. 오늘 실습합니다.
3. 따라 하기
3-1. 수사 현장 준비 — 가짜 로그 만들기
연습장을 만들고 가짜 로그를 준비합니다. Step 2에서 배운 명령들입니다:
cd $HOME
New-Item -ItemType Directory textlab
cd textlab
이제 50줄짜리 로그를 만듭니다. 메모장으로 해도 되지만, 우리는 CLI 연습 중이니 파워쉘로 만듭니다. 아래를 통째로 복사해서 파워쉘에 붙여넣으세요 (여러 줄이 한 번에 실행됩니다):
1..50 | ForEach-Object {
$m = "{0:D2}" -f $_
if ($_ % 7 -eq 0) { Add-Content log.txt "2026-09-08 02:$m ERROR failed login: admin from 10.9.9.9" }
elseif ($_ % 5 -eq 0) { Add-Content log.txt "2026-09-08 03:$m WARNING disk usage high" }
else { Add-Content log.txt "2026-09-08 04:$m INFO normal operation" }
}
지금 이 문법을 이해할 필요는 전혀 없습니다 (Step 8에서 배웁니다). "7번째 줄마다 ERROR, (7의 배수가 아닌) 5번째 줄마다 WARNING, 나머지는 INFO를 넣은 50줄 파일"이라는 것만 알면 됩니다.
확인:
Get-Content log.txt -TotalCount 8
2026-09-08 04:01 INFO normal operation
2026-09-08 04:02 INFO normal operation
2026-09-08 04:03 INFO normal operation
2026-09-08 04:04 INFO normal operation
2026-09-08 03:05 WARNING disk usage high
2026-09-08 04:06 INFO normal operation
2026-09-08 02:07 ERROR failed login: admin from 10.9.9.9
2026-09-08 04:08 INFO normal operation
-TotalCount 8— "전부 말고 앞 8줄만." 긴 파일을 슬쩍 볼 때 쓰는 옵션입니다.
3-2. 전체 읽기와 문제 상황 — Get-Content
전부 읽어 봅시다:
Get-Content log.txt
50줄이 와르르 지나갑니다. 지금이야 50줄이지만, 실제 로그는 5만 줄입니다. "전체를 눈으로 읽는다"는 선택지에 없다는 걸 체감하세요. 그래서 다음 기계가 필요합니다.
3-3. 수사 개시 — Select-String
Get-Content log.txt | Select-String "error"
2026-09-08 02:07 ERROR failed login: admin from 10.9.9.9
2026-09-08 02:14 ERROR failed login: admin from 10.9.9.9
...
"error"가 들어간 줄만 골라졌습니다. Step 3의 Where-Object와 같은 역할인데, 텍스트 검색 전용이라 더 간단합니다.
잠깐 — 방금 전 "ERROR"(대문자)로 저장했는데 왜 "error"(소문자)로 검색해서 걸렸을까요? Select-String은 기본적으로 대소문자를 구분하지 않습니다. (구분하고 싶으면 -CaseSensitive 옵션.)
더 짧게도 됩니다 — Select-String은 파일 경로를 직접 받을 수 있습니다:
Select-String -Path log.txt -Pattern "error"
-Path— 검색할 파일-Pattern— 찾을 글자/패턴
3-4. 몇 건이나? — 세어 보기
공격 규모를 파악할 때 개수가 중요합니다:
Select-String -Path log.txt -Pattern "error" | Measure-Object
Count : 7
7의 배수 줄에 ERROR가 들어갔으니 7건입니다. "ERROR가 7건" — Step 3에서 배운 Measure-Object가 여기서도 그대로 쓰입니다. 조립 사고, 기억하시죠?
예측해 보기:
Select-String -Path log.txt -Pattern "WARNING"은 몇 줄이 나올까요? 예측하고 실행해 보세요.
(정답: 9줄. 5의 배수는 10개(5,10,…,50)지만, 35는 7의 배수라 ERROR 칸으로 빠졌습니다. 생성 규칙을 떠올리며 확인해 보세요 — 이런 "조건이 겹치면 어떻게 되지?"를 의심하는 게 분석가의 감각입니다.)
3-5. 증거 남기기 — Out-File
뽑아낸 결과를 파일로 저장합니다. 보고서의 원료입니다:
Select-String -Path log.txt -Pattern "error" | Out-File errors.txt
Get-Content errors.txt
2026-09-08 02:07 ERROR failed login: admin from 10.9.9.9
...
화면 대신 errors.txt에 기록됐고, 다시 읽어 확인했습니다. 이 흐름:
검색(Select-String) → 저장(Out-File) → 검증(Get-Content)
이게 "조사 결과를 문서로 남기는" 기본 워크플로우입니다. 실제 침해 대응 보고서도 이 구조의 확장판입니다.
3-6. 한글 깨짐 사건 — 인코딩 실험
이번엔 일부러 사건을 만들어 봅시다. 한글이 든 파일을 만들고:
Set-Content korean.txt "비밀번호 초기화 필요"
Get-Content korean.txt
대부분의 경우 정상으로 보입니다. (파워쉘이 같은 표로 쓰고 읽었으니까요.) 그런데 이 파일을 다른 프로그램에서 열거나, 인터넷에서 받은 파일을 열 때 깨짐이 생깁니다 — 쓴 표와 읽는 표가 달라서입니다 (2-2 복습).
읽기 표를 명시하는 방법:
Get-Content korean.txt -Encoding UTF8
-Encoding UTF8 — "UTF-8 표로 읽어라." 실무 습관은 이렇습니다:
남이 만든 텍스트 파일의 한글이 깨지면, 인코딩을 바꿔 다시 읽는다. (
-Encoding UTF8,-Encoding Default등을 번갈아 시도)
저장할 때도 표를 정할 수 있습니다. UTF-8은 세계 표준이니 앞으로 이렇게 쓰는 습관을 추천합니다:
... | Out-File result.txt -Encoding utf8
3-7. 여러 파일을 한꺼번에 수사
Select-String의 진짜 강력함은 여기 있습니다:
Select-String -Path *.txt -Pattern "error"
이 폴더의 모든 .txt 파일에서 "error"를 찾습니다. 결과에는 어느 파일의 몇 번째 줄인지까지 표시됩니다 (실측):
errors.txt:1:2026-09-08 02:07 ERROR failed login: admin from 10.9.9.9
log.txt:7:2026-09-08 02:07 ERROR failed login: admin from 10.9.9.9
log.txt:14:2026-09-08 02:14 ERROR failed login: admin from 10.9.9.9
...
읽는 법: 파일명:줄번호:내용. 이 기능 덕분에 수백 개 로그 파일을 한 방에 수사할 수 있습니다.
4. 미션과 연습문제
미션 — 로그 분석관의 하루
사건: "우리 서버 로그에서 수상한 활동을 찾아 보고서로 제출하라"는 지시를 받았습니다. textlab 폴더에서 진행하세요.
log.txt에서 "WARNING"이 든 줄만 뽑아warnings.txt로 저장하세요.- "ERROR"와 "WARNING"을 합쳐서 총 몇 건인지 계산하세요. (힌트: 패턴을
"ERROR|WARNING"처럼 쓰면 한 번에 검색됩니다 — 패턴 안의|는 "또는"이라는 뜻. 쳐 보세요!) - 두 종류를 합친 결과를
incidents.txt로 저장하세요. (UTF-8 인코딩 지정 습관!) - 보고서 검증:
Get-Content incidents.txt -TotalCount 3으로 앞 3줄이 잘 저장됐는지 확인하세요. - 생각해 보기: 만약 실제 서버 로그가 10만 줄이라면, 오늘 배운 명령 중 어떤 것부터 치겠습니까? 순서를 말로 정리해 보세요.
연습문제
문제 1. log.txt에서 "INFO"가 든 줄은 총 몇 줄일까요? (50줄 중 ERROR 7줄, WARNING 9줄)
문제 2. Select-String -Path log.txt -Pattern "ERROR|WARNING"의 결과 건수는? 패턴 안의 |는 무슨 뜻인가요?
문제 3. 인터넷에서 받은 한글 텍스트 파일을 열었더니 비?번호처럼 깨져 보입니다. 원인과 처방 한 가지를 말하세요.
문제 4. Select-String -Path *.txt -Pattern "error"의 결과에서 log.txt:7:2026-09-08...은 어떻게 읽나요?
5. 모범 답안과 완료 기준
미션 해설
# 1
Select-String -Path log.txt -Pattern "WARNING" | Out-File warnings.txt -Encoding utf8
# 2 — Count : 16 (ERROR 7 + WARNING 9)
Select-String -Path log.txt -Pattern "ERROR|WARNING" | Measure-Object
# 3
Select-String -Path log.txt -Pattern "ERROR|WARNING" | Out-File incidents.txt -Encoding utf8
# 4
Get-Content incidents.txt -TotalCount 3
5번 생각해 보기의 모범 답: "전체를 읽지 않는다"가 출발점입니다. ① Get-Content -TotalCount로 형식부터 파악하고, ② Select-String으로 의심 패턴("failed", "ERROR")을 좁히고, ③ Measure-Object로 규모를 재고, ④ 결과를 Out-File로 남깁니다. 좁히기 → 세기 → 기록하기, 이 순서가 10만 줄에서도 똑같이 작동합니다.
연습문제 해답
문제 1 해답. 50 − 7 − 9 = 34줄입니다. 명령으로 확인: Select-String -Path log.txt -Pattern "INFO" | Measure-Object → Count 34.
문제 2 해답. 16건 (ERROR 7 + WARNING 9). 패턴 안의 |는 "또는(or)"이라는 뜻의 정규표현식 기호입니다 — "ERROR 또는 WARNING이 든 줄"을 한 번에 검색합니다.
문제 3 해답. 원인: 파일을 저장한 인코딩(표)과 읽는 프로그램의 인코딩이 다른 것입니다. 처방: 읽을 때 표를 명시합니다 — Get-Content 파일 -Encoding UTF8처럼 -Encoding 값을 바꿔 가며 정상으로 읽히는 표를 찾습니다.
문제 4 해답. 파일명:줄번호:내용 — "log.txt 파일의 7번째 줄에서 찾았고, 그 줄의 내용은 이렇다"라는 뜻입니다. 여러 파일을 동시 수사할 때 어느 파일의 어디인지가 바로 보이는 것이 이 형식의 힘입니다.
완료 기준 체크리스트
- [ ]
Get-Content로 파일을 읽고-TotalCount로 앞부분만 볼 수 있다 - [ ]
Select-String으로 특정 단어가 든 줄만 골라낼 수 있다 - [ ]
파일명:줄번호:내용형식을 읽을 수 있다 - [ ]
Measure-Object로 건수를 셀 수 있다 - [ ] 결과를
Out-File로 저장하고 검증할 수 있다 - [ ] 한글 깨짐의 원인(인코딩 불일치)과 대응(
-Encoding)을 안다 - [ ] 미션 1~5를 완료했다
6. 흔한 실수와 해결
벽 1. 한글이 □□ 또는 이상한 글자로 깨져 나온다
인코딩 불일치입니다. 파일을 만든 표와 읽는 표가 다릅니다. Get-Content 파일 -Encoding UTF8 또는 -Encoding Default를 번갈아 시도해 보세요. 어느 한쪽에서 정상으로 읽히면, 그 파일의 인코딩을 알아낸 겁니다. (이 시행착오 자체가 실무입니다.)
벽 2. Select-String 결과가 내가 저장한 결과 파일까지 포함한다
검색 대상 폴더에 이전에 저장한 결과 파일(errors.txt 등)이 있으면, 그 파일도 다시 검색 대상이 되어 결과가 부풀려집니다 (3-7의 출력에서 errors.txt가 같이 잡힌 게 바로 그것입니다). 수사 결과는 되도록 다른 폴더에 저장하는 습관을 들이세요.
벽 3. Out-File로 저장했는데 한글이 깨진다
Out-File도 인코딩 기본값이 환경에 따라 다릅니다. Out-File 파일 -Encoding utf8을 습관화하면 대부분 해결됩니다.
벽 4. 찾는 단어가 분명 있는데 안 걸린다
① 철자 확인, ② -CaseSensitive를 붙였다면 대소문자까지 같아야 합니다 (error ≠ ERROR), ③ 파일 인코딩이 특수해서 검색이 실패하는 경우 — -Encoding을 지정해 읽은 뒤 파이프로 넘기세요: Get-Content 파일 -Encoding UTF8 | Select-String "단어".
벽 5. 결과가 너무 길어서 처음이 잘렸다
| Out-File로 저장하고 파일로 보거나, Step 3의 부품을 조합하세요: ... | Select-Object -First 20. 결과가 길수록 "자르기" 습관이 빛납니다.
7. 정리
오늘 배운 명령어
| 명령 | 하는 일 | 예 |
|---|---|---|
Get-Content |
파일 읽기 | Get-Content log.txt -TotalCount 10 |
Select-String |
패턴 든 줄 골라내기 | Select-String -Path log.txt -Pattern "error" |
Measure-Object |
개수 세기 | ... | Measure-Object |
Out-File |
결과를 파일로 저장 | ... | Out-File result.txt -Encoding utf8 |
핵심 개념
| 개념 | 한 줄 요약 |
|---|---|
| 텍스트 파일 = 줄의 나열 | 도구들은 "줄 단위"로 일한다 |
| 인코딩 | 글자↔숫자 변환표. 한글 깨짐 = 표 불일치 |
-Encoding |
읽기/쓰기 표 명시 (UTF-8 습관화) |
| 결과 형식 | 파일명:줄번호:내용 — 수사의 단서 |
명령어보다 중요한 감각
"전체를 읽지 마라. 골라낼 조건을 먼저 정하라." 10만 줄의 로그도 "실패한 로그인만", "그 IP에서 온 것만"으로 좁히면 이야기가 됩니다. 그리고 결과는 반드시 파일로 남겨라 — 조사는 기록될 때 비로소 보고서가 됩니다.
알아두면 좋은 것 두 가지: Select-String의 -Pattern 자리는 사실 정규표현식(regex)이라는 패턴 언어를 받습니다 — Level 1에서 정식으로 배우는 텍스트 처리의 끝판왕입니다. 그리고 이 기술은 리눅스에서도 거의 그대로 씁니다. 이름만 grep으로 바뀔 뿐, "패턴으로 줄을 낚는다"는 사고방식은 모든 운영체제에서 통하는 만국 공용어입니다.
전부 체크되면 Step 4 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.