어떤 수업을 찾고 있나요?

예: PowerShell, 네트워크, XSS, Step 138

전체 커리큘럼 둘러보기 →

PowerShell

Step 7. 변수와 자료형 — 이름표 붙은 상자에 담기

Step 7

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

전제: Step 6 완료. Windows PowerShell 5.1 또는 Windows의 PowerShell 7에서 진행합니다. 인터넷 연결은 필요 없습니다. 코드의 영문 출력 라벨은 한글·영문 수업에서 동일하게 사용합니다.

  • 준비물: 윈도우 PC, 파워쉘.
  • 안전: 예제 변수와 배열을 만들고 로컬 서비스 목록을 조회합니다. 파일·서비스 설정을 변경하지 않습니다. 새 실습 세션에서 아래 순서로 진행하세요.
  • 주의: 오늘의 최대 함정을 미리 알려 드립니다. 큰따옴표와 작은따옴표가 파워쉘에서는 다르게 작동합니다. 이 하나 때문에 초보들이 수 시간을 헤맵니다. 여러분은 3-4절에서 정면으로 배우고 넘어갈 겁니다.

오늘부터 "프로그래밍"이 시작됩니다. 하지만 겁먹지 마세요. 오늘 배우는 것은 "값에 이름을 붙여 두고 나중에 다시 꺼내 쓰는" 것 — 일상에서 메모하는 행위와 본질이 같습니다. 오늘의 챕터는 전부 손으로 따라 쳐야 합니다. 코드를 눈으로만 읽으면 절대 몸에 배지 않습니다. 틀려도 됩니다. 오류 메시지도 오늘의 교재입니다.


1. 학습 목표

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

  • 변수에 값을 저장하고 꺼내 쓴다
  • 숫자·문자열·배열의 차이를 구분하고 GetType()으로 자료형을 확인한다
  • 큰따옴표(변수 확장)와 작은따옴표(있는 그대로)의 차이를 설명한다
  • 명령의 결과를 통째로 변수에 담아 개수를 세고 항목을 꺼낸다

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

오늘의 도구 한눈에 보기

구분 내용
언어·환경 Windows PowerShell 5.1 / PowerShell 7 — 변수와 자료형
오늘의 문법 $변수 = 값(저장), $변수(꺼내기), @(...)(배열), $( )(문장 속 끼워 넣기)
오늘의 도구 GetType()(자료형 확인)
필요한 개념 변수와 메모리, 자료형(숫자/문자열/배열), 큰따옴표 vs 작은따옴표

지금까지는 명령을 실행하고 결과를 화면에서 읽었습니다. 변수는 그 결과를 이름에 연결해 나중에 다시 사용할 수 있게 합니다. 예를 들어 “학습 주제 = PowerShell”처럼 값에 이름을 붙이는 것입니다. 숫자·문자열·배열은 저장하는 값의 종류를 구별하는 출발점입니다. 실제 비밀번호나 토큰을 예제에 넣지 말고 아래의 가상 이름을 사용하세요.

2-1. 변수 — 이름표 붙은 상자

변수는 "값을 담는, 이름표가 붙은 상자"입니다.

$name = "Lee"

이 한 줄의 의미: "name이라는 이름표의 상자를 만들고, 그 안에 Lee라는 글자를 넣어라." 나중에 $name이라고 부르면 상자 속 내용이 튀어나옵니다.

변수를 참조할 때 $name처럼 $를 붙입니다. 변수의 이름 자체는 name이며 대소문자를 구분하지 않습니다. $name과 $Name은 같은 변수입니다. $HOME·$Host·$PID 같은 기본 변수 이름을 실습 변수로 재사용하지 마세요.

2-2. 컴퓨터 안에서는 — 메모리

변수는 현재 PowerShell 세션과 범위 안에서 값이나 객체를 참조하는 이름입니다. 새로 연 별도 세션에는 이전에 만든 변수가 자동 전달되지 않습니다. 현재 세션을 종료하면 그 세션의 사용자 변수 상태도 끝납니다. 다만 프로필이나 스크립트가 새 세션에서 값을 다시 만들 수는 있습니다. 변수 값을 지우거나 창을 닫는 것이 디스크·명령 기록·메모리를 안전하게 삭제한다는 뜻은 아닙니다.

(참고: 이 "메모리"라는 단어는 Level 1에서 아주 깊이 다시 만납니다. C 언어와 버퍼 오버플로 공격이 전부 메모리 이야기거든요. 지금은 "변수는 메모리에 저장된다" 한 줄만 기억해 두세요.)

2-3. 자료형 — 상자 속 물건의 종류

상자 안에 뭐가 들었는지에 따라 할 수 있는 일이 다릅니다.

자료형 예시 할 수 있는 일
숫자 (정수) 3, 42 사칙연산
글자 (문자열, string) "Lee", "hello" 붙이기, 자르기, 검색
목록 (배열, array) @("a","b","c") 순서대로 나열, 하나씩 꺼내기

"문자열"은 "문자들이 열(줄)처럼 이어진 것"이라는 뜻의 용어입니다. 글자 데이터라고 생각하시면 됩니다. 따옴표로 감싼 것은 전부 문자열입니다 — "3"도 숫자가 아니라 글자 "3"입니다. 이 차이가 3-3절에서 실제로 문제를 일으킵니다.


3. 따라 하기

3-1. 첫 변수 — 저장하고 꺼내기

$name = "Lee"

아무 일도 안 일어난 것 같죠? 정상입니다. 저장 명령은 조용합니다. 이제 꺼내 봅시다:

$name
Lee

출력 읽는 법: $name이라고만 치면 파워쉘은 "상자 속 내용을 보여 줘"로 알아듣고 내용을 출력합니다.

왜 하는가: 이 "저장 → 꺼내기" 두 동작이 모든 스크립트의 기본 걸음입니다. 변수를 쓰면 같은 값을 백 번 써도 이름표 하나로 관리할 수 있고, 값을 바꿀 때도 한 군데만 고치면 됩니다.

3-2. 숫자 변수 — 계산기 되기

$a = 3
$b = 4
$a + $b
7

출력 읽는 법: 7이 바로 나오면 성공입니다. 상자 두 개 속의 숫자를 꺼내 더한 겁니다.

왜 하는가: 숫자가 변수에 들어가면 계산 결과를 다시 사용할 수 있습니다. 전체 로그 줄 수에서 ERROR 줄 수를 빼면 “ERROR가 아닌 줄 수”입니다. WARNING도 포함될 수 있으므로 곧바로 정상 줄 수라고 부르지는 않습니다.

시험 삼아 $a * $b(곱하기), $a / $b(나누기)도 해 보세요. 파워쉘은 그 자리에서 계산기가 됩니다.

3-3. 숫자와 글자는 다르다 — 자료형의 실체

이번엔 일부러 사고를 쳐 봅시다. 입력:

$x = "3"
$y = "4"
$x + $y

예측해 보기: 결과가 7일까요, 아닐까요?

실제 결과 (실측):

34

7이 아니라 34! 따옴표로 감쌌기 때문에 "3"과 "4"는 숫자가 아니라 글자이고, 글자의 +는 "이어 붙이기"입니다. 이게 자료형이 실제로 결과를 바꾸는 순간입니다.

이 상자들의 정체를 확인해 봅시다:

$x.GetType().Name
String

문자열이라고 컴퓨터가 직접 대답합니다. 아까의 $a로 같은 걸 해 보면 Int32(정수)라고 나옵니다.

왜 하는가: 계산이 예상과 다르면 값과 자료형을 함께 확인합니다. 이 예제의 3은 Int32이지만 숫자에는 Int64·Double·Decimal 등 다른 자료형도 있습니다. $null에는 GetType()을 호출할 수 없습니다.

$a.GetType().Name
(3.5).GetType().Name
([long]3000000000).GetType().Name
[int]$x + [int]$y
3 + "4"
"3" + 4
Int32
Double
Int64
7
7
34

[int]는 정수 변환입니다. 숫자 형태가 아니거나 Int32 범위를 넘는 문자열은 변환에 실패합니다. 혼합 연산에서는 왼쪽 피연산자의 형이 변환 방향에 영향을 주므로 3 + “4”와 “3” + 4의 결과가 다릅니다.

3-4. 오늘의 최대 함정 — 큰따옴표 vs 작은따옴표

문자열 안에서 변수를 쓰고 싶을 때가 있습니다. 두 가지 방법을 나란히 비교해 봅시다. 입력:

"Name: $name"
'Name: $name'

출력:

Name: Lee
Name: $name

출력 읽는 법: 첫 줄(큰따옴표)은 변수가 풀려서 Lee가 들어갔고, 둘째 줄(작은따옴표)은 $name이 글자 그대로 나왔습니다.

왜 이렇게 다른가: 큰따옴표는 "속을 검사해서 변수가 있으면 값으로 바꿔 치운다"(이걸 변수 확장, 영어로 variable expansion이라 합니다). 작은따옴표는 "속을 있는 그대로 취급한다".

언제 뭘 쓰나: 문장 속에 값을 끼워 넣고 싶으면 큰따옴표. $ 기호 자체를 문자로 쓰고 싶으면 작은따옴표. 기본은 큰따옴표로 시작하고, "어? 변수가 안 풀리네?" 하면 따옴표부터 의심하세요.

예측해 보기: 일반 문자열 안의 +는 글자지만 $(...) 안의 식은 계산합니다. 변수 뒤에 콜론이나 다른 문자를 바로 붙일 때는 ${name}처럼 변수 이름의 경계를 지정할 수 있습니다.

"Sum: $a + $b"
"Sum: $($a + $b)"
"${name}: ready"
Sum: 3 + 4
Sum: 7
Lee: ready

3-5. 배열 — 여러 개를 한 상자에

이름 여러 개를 다루고 싶습니다. 상자를 세 개 만들 수도 있지만, 목록 상자 하나가 낫습니다:

$list = @("apple", "banana", "kiwi")

@(...)가 "이건 목록이다"라는 표시입니다. 꺼낼 때는 번호표를 씁니다:

$list[0]
apple

출력 읽는 법: banana가 아니라 apple이 나온 게 포인트입니다. 배열의 인덱스는 0부터 시작합니다. 0번이 첫 번째, 1번이 두 번째입니다. $list[1], $list[2]도 해 보세요.

왜 하는가: 목록은 실전에서 계속 나옵니다 — 로그 파일 목록, 사용자 목록, 서버 목록. 그리고 다음 챕터의 반복문과 만나면 "목록의 모든 항목에 같은 작업"이라는 강력한 패턴이 됩니다.

목록이 몇 개인지 세는 것도 바로 배워 둡시다:

$list.Count
3

.Count는 "개수 세어 줘"입니다. Step 5에서 본 Measure-Object와 역할이 비슷하죠.

3-6. 종합 — 이름 목록 다루기

오늘 배운 것을 모아 봅시다:

$members = @("Kim", "Lee", "Park")
$members.Count
"First member: $($members[0])"
3
First member: Kim

새로운 표기 하나: "$($members[0])" — 큰따옴표 안에서 배열의 한 칸을 넣을 때는 $( )로 한 번 감싸야 합니다. "$members[0]"이라고 그냥 쓰면 실측 결과 이렇게 나옵니다:

Kim Lee Park[0]

파워쉘의 문자열 확장 규칙은 여기서 변수 $members만 먼저 확장하고 [0]을 문자열로 남깁니다. 큰따옴표 안의 인덱싱·속성 접근·계산을 실행하려면 $(...) 안에 넣으세요. 배열이 공백으로 합쳐지는 예시는 기본 $OFS 동작을 전제로 합니다.

왜 하는가: "목록 + 개수 + 문장에 끼워 넣기" 조합은 앞으로 보고서 문장을 자동 생성할 때 표준 패턴이 됩니다. 예: "검사한 파일: $($files.Count)개".

3-7. 실전 감각 — 명령 결과를 변수에 담기

지금까지는 값을 직접 적어 넣었습니다($a = 3). 그런데 변수의 진짜 위력은 명령의 결과를 통째로 저장할 때 나옵니다:

$now = Get-Date
$now
2026-09-10 09:30:00 (illustrative; display varies by locale)

무슨 일이 일어났나: Get-Date가 반환한 DateTime 객체를 $now에 저장했습니다. 표시 형식과 시각은 환경마다 다릅니다. $now를 나중에 다시 읽어도 저장된 시각이 그대로이며, 현재 시각을 얻으려면 Get-Date를 다시 실행합니다.

한 걸음 더 — Step 5에서 배운 명령과 합쳐 봅시다:

$services = @(Get-Service)
$services.Count
310

310은 출력 모양을 설명하는 예시이며 실제 개수는 환경과 조회 시점에 따라 달라집니다. 조회 오류가 있으면 반환된 목록이 불완전할 수 있습니다. 오류가 있었다는 사실을 개수와 함께 기록하세요.

출력 읽는 법: 명령이 반환한 서비스 객체를 @(...)로 감싸 배열로 받습니다. 일반적인 명령 할당은 결과가 0개면 $null, 1개면 단일 객체, 여러 개면 배열이 될 수 있습니다. 결과 개수에 상관없이 배열로 다루려면 @()를 명시합니다. 배열 자체의 Count는 원소 수입니다.

$zero = @(@('one', 'two') | Select-Object -First 0)
$one = @(@('one', 'two') | Select-Object -First 1)
$many = @(@('one', 'two') | Select-Object -First 2)
$zero.Count
$one.Count
$many.Count
$one[0]
0
1
2
one

0개·1개·여러 개 결과를 같은 방식으로 셀 수 있습니다. 서비스 개별 항목은 $services[0]으로 읽되 먼저 Count가 0보다 큰지 확인합니다. 명령 할당은 기본적으로 성공 출력 스트림을 받으며 오류 메시지가 자동으로 원소가 되는 것은 아닙니다.

왜 하는가: 이 패턴 — "결과를 변수에 담고 → 개수를 세고 → 필요한 것을 꺼낸다" — 이 앞으로 모든 분석 스크립트의 뼈대입니다. 로그 파일을 읽어 변수에 담고, 에러만 걸러 다른 변수에 담고, 개수로 판단하는 식입니다. Step 8의 반복문과 만나면 그 모습이 완성됩니다.

예측해 보기: 한 번 저장한 $services를 변경하거나 다시 할당하지 않았다면, 나중에도 그 배열의 Count는 같습니다. 서비스가 시작·중지됐다고 저장한 배열이 자동으로 늘거나 줄지 않습니다. 현재 목록을 보려면 Get-Service를 다시 실행합니다. 객체 참조를 담는 것과 모든 속성을 깊게 복사한 불변 기록을 만드는 것은 다르므로, 비교할 값은 필요한 속성을 따로 수집해 저장합니다.


4. 미션과 연습문제

미션 — 멤버 소개 스크립트

아래 요구사항을 만족하는 5줄 이내의 코드를 직접 작성해 보세요:

  1. 이름 세 개가 든 배열 $team을 만든다 (본인 포함 아무 이름이나)
  2. $team의 개수를 확인한다
  3. 큰따옴표 문자열로 "Our team has N members"를 출력한다 (N은 변수에서 자동으로)
  4. "The team lead is OOO"를 출력한다 (배열의 첫 번째 칸 활용)

연습문제

문제 1. "3" + "4"의 결과와 이유를 설명하세요.

문제 2. "Name: $name"과 'Name: $name'의 출력 차이를 설명하세요.

문제 3. 큰따옴표 안에서 배열의 한 칸을 넣고 싶습니다. "$members[0]"이 아니라 어떻게 써야 하나요?

문제 4. $services = Get-Service를 실행한 뒤 창을 닫고 다시 열었습니다. $services.Count는 어떻게 될까요? 왜 그런가요?


해설과 완료 기준 · 펼치기/접기

5. 모범 답안과 완료 기준

미션 모범 답안

$team = @("Lee", "Kim", "Park")
$team.Count
"Our team has $($team.Count) members"
"The team lead is $($team[0])"

기대 출력:

3
Our team has 3 members
The team lead is Lee

검증하는 법: 4줄의 코드가 내는 출력은 3줄입니다. 첫 출력은 개수 3, 둘째는 Our team has 3 members, 셋째는 The team lead is Lee여야 합니다. 숫자나 첫 이름 대신 Count·[0]이 글자로 붙으면 $(...)를 확인하세요.

심화: 원소가 세 개인 이 배열의 유효한 양수 인덱스는 0·1·2입니다. 기본 엄격 모드 비활성 상태에서 $team[3]은 $null이며 보통 화면에 보이지 않습니다. StrictMode 3.0에서는 범위를 벗어난 인덱스가 오류입니다. 마지막 원소는 $team[-1]로도 읽을 수 있습니다. “없는 칸은 언제나 오류가 아니다”라고 일반화하지 마세요.

연습문제 해답

문제 1 해답. 결과는 34입니다. 따옴표로 감싸면 숫자가 아니라 문자열이 되고, 문자열의 +는 더하기가 아니라 "이어 붙이기"입니다. (숫자로 더하려면 따옴표 없이 3 + 4.)

문제 2 해답. 큰따옴표는 변수 확장 — 속의 $name을 값(예: Name: Lee)으로 바꿔 치웁니다. 작은따옴표는 있는 그대로 — Name: $name이라는 글자 그대로 출력합니다.

문제 3 해답. "$($members[0])" — $( )로 감싸야 합니다. 그냥 쓰면 배열 전체가 풀리고 [0]이 글자로 붙는 이상한 출력이 나옵니다 (3-6절 실측 참조).

문제 4 해답. 추가 초기화가 없는 새 세션에는 $services가 정의되어 있지 않습니다. 기본 엄격 모드 비활성 상태에서 값은 $null처럼 동작하고 $services.Count는 0입니다. 엄격 모드에서는 미정의 변수 접근이 오류가 될 수 있습니다. 이것은 현재 서비스가 0개라는 뜻이 아닙니다. 스크립트 파일을 저장하면 코드를 다시 실행할 수 있지만 현재 변수 상태가 자동 저장되는 것은 아닙니다.

완료 기준 체크리스트

  • [ ] 변수에 값을 저장하고 다시 꺼내 출력할 수 있다
  • [ ] 큰따옴표와 작은따옴표의 차이를 설명할 수 있다
  • [ ] "3" + "4"가 왜 34인지 설명할 수 있다
  • [ ] GetType()으로 변수의 자료형을 확인할 수 있다
  • [ ] 배열을 만들고 번호로 항목을 꺼낼 수 있다 (0부터 센다)
  • [ ] 명령 결과를 변수에 담아 .Count로 셀 수 있다
  • [ ] 미션: 멤버 소개 스크립트를 완성했다

6. 흔한 실수와 해결

벽 1. 변수를 쳤는데 아무것도 안 나온다

일반적인 변수 대입은 성공 출력이 없습니다. 하지만 무출력만으로 성공을 판단할 수는 없습니다. 코드가 완성되어 새 프롬프트가 나왔는지와 오류를 확인하고 $name을 읽어 기대 값인지 검증하세요. >>가 보이면 괄호나 따옴표가 아직 닫히지 않았을 수 있습니다.

벽 2. 문장 안에서 변수가 그대로 찍힌다

작은따옴표 'Name: $name'는 Name: $name을 그대로 출력합니다. 이 예제의 큰따옴표 "Name: $name"는 Name: Lee입니다. 큰따옴표인데도 변수가 풀리지 않았다면, 실제로 입력한 따옴표와 이스케이프 문자를 확인하세요.

벽 3. 숫자를 더했는데 이어 붙는다

이 예제는 문자열 두 개를 이어 붙여 34가 됩니다. 숫자로 계산하려면 숫자를 저장하거나 변환 가능한 문자열에 [int] 같은 명시적 변환을 적용합니다. Int32만 숫자인 것은 아니며 Int64·Double·Decimal도 숫자 형입니다.

벽 4. 배열에서 엉뚱한 게 나온다

증상: 첫 번째 항목을 원했는데 두 번째가 나오거나, 마지막 다음을 부르면 아무것도 안 나옴.
원인: 번호가 0부터 시작한다는 걸 까먹은 겁니다. 첫 번째는 [0], 세 개짜리 목록의 끝은 [2]입니다.
해결: "번호 = 몇 번째 − 1"로 외우세요. 그리고 $list.Count로 목록 길이를 먼저 확인하는 습관을 들이세요.

벽 5. 변수를 만들었는데 잠시 후 없어졌다

같은 실습 세션에서 이어 실행했는지 확인하세요. 별도 세션, 스크립트·함수 범위, 재할당이나 삭제 때문에 기대한 값이 없을 수 있습니다. 같은 창이라는 외형만으로 같은 PowerShell 세션·범위임이 보장되지는 않습니다. 처음 대입하는 줄부터 다시 실행해 확인합니다.


7. 정리

오늘의 핵심 표

개념 비유 파워쉘 표기
변수 이름표 붙은 상자 (메모리에 저장) $name = "Lee"
문자열 글자 데이터 "hello" (문자열 리터럴 예시)
정수 숫자 데이터 3 (따옴표 없이)
배열 번호표 달린 목록 상자 @("a","b","c"), [0]부터

오늘의 함정 카드

상황 결과 교훈
"$name" (큰따옴표) 변수가 풀림 값을 끼워 넣을 때
'$name' (작은따옴표) 글자 그대로 $ 기호 자체를 쓸 때
"3" + "4" 34 따옴표 = 문자열
3 + 4 7 따옴표 없음 = 숫자
"$list[0]" 이상한 출력 배열 칸은 $($list[0])

명령어보다 중요한 감각

"상자 속 물건의 종류를 항상 의식하라." "문자열인 줄 알았는데 숫자였다(혹은 반대)"는 버그는 실제 보안 취약점의 씨앗이 되기도 합니다. 의심스러우면 GetType()으로 신분을 확인하는 습관 — 그게 오늘의 진짜 소득입니다.

알아두면 좋은 것 두 가지: "사용자가 입력한 값을 변수에 담아 명령에 그대로 끼워 넣는" 코드는 인젝션(injection) 공격의 단골 소재입니다 — "외부에서 온 값은 함부로 신뢰하지 않는다"는 철칙의 이유를 Level 2에서 직접 공격해 보며 체감하게 됩니다. 그리고 실전에서는 $a 대신 $loginFailCount처럼 "읽으면 뭔지 아는 이름"을 씁니다. 이름만 봐도 용도가 보이는 코드는 설명서 없이도 읽힙니다.


전부 체크되면 Step 7 완료입니다.


실습 검증 기록

2026-09-10, Windows PowerShell 5.1.26100.9444와 PowerShell 7.6.5에서 본문의 실행 코드를 순서대로 수행했습니다. 숫자·문자열·명시적 형 변환, 따옴표 확장, 0·1·여러 원소 배열, 서비스 배열 개수, 미션의 세 줄 출력을 확인했습니다. 추가 격리 세션에서 미정의 변수와 엄격 모드의 배열 오류를 구분했습니다. 서비스 시작·중지나 프로필 변경은 수행하지 않았습니다.

Microsoft: Variables · Arrays · Quoting rules · StrictMode

한 단계 더 가까이

수업을 마쳤나요?

본문의 완료 기준을 확인한 뒤 직접 표시하세요.

화면이나 링크에 문제가 있나요? 알려주세요.
다음 수업