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

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

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

전제: Step 6 완료. 윈도우 파워쉘에서 진행합니다. 인터넷 연결은 필요 없습니다.

  • 준비물: 윈도우 PC, 파워쉘.
  • 안전: 오늘은 메모리 안에서 노는 실험뿐이라 100% 안전합니다.
  • 주의: 오늘의 최대 함정을 미리 알려 드립니다. 큰따옴표와 작은따옴표가 파워쉘에서는 다르게 작동합니다. 이 하나 때문에 초보들이 수 시간을 헤맵니다. 여러분은 3-4절에서 정면으로 배우고 넘어갈 겁니다.

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


1. 학습 목표

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

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

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

오늘의 도구 한눈에 보기

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

지금까지 우리는 명령을 치고 결과를 보고 끝냈습니다. Get-Date를 치면 날짜가 나오지만, 그 결과는 화면을 지나가고 사라집니다. 사람이라면 수첩에 적겠죠 — "와이파이 비밀번호 = blue sky 77"처럼 이름을 붙여 값을 저장합니다. 프로그래밍에서 이 수첩 역할을 하는 것이 변수(variable)이고, 적는 내용이 숫자인지 글자인지 목록인지에 따른 종류가 자료형(data type)입니다. 이 두 개념은 앞으로 나올 모든 스크립트의 알파벳입니다.

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

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

$name = "Lee"

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

파워쉘에서 변수 이름은 항상 $로 시작합니다. 이 달러 표시가 "이건 변수다"라는 신호입니다.

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

상자 비유를 조금만 현실로 옮겨 봅시다. 여러분이 $name = "Lee"를 실행하는 순간, 컴퓨터는 메모리(RAM) 어딘가에 "Lee"를 기록하고, name이라는 이름과 그 위치를 짝지어 기억합니다. 파워쉘 창을 닫으면 메모리의 이 기록도 사라집니다 — 변수는 "창이 열려 있는 동안만 유효한 메모"입니다.

(참고: 이 "메모리"라는 단어는 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이 바로 나오면 성공입니다. 상자 두 개 속의 숫자를 꺼내 더한 겁니다.

왜 하는가: 숫자가 변수에 들어가면 계산 결과를 저장했다가 다음 계산에 쓸 수 있습니다. 예를 들어 "전체 로그 줄 수에서 에러 줄 수를 빼면 정상 줄 수" 같은 식의 분석이 가능해집니다.

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

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

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

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

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

실제 결과 (실측):

34

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

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

$x.GetType().Name
String

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

왜 하는가: "분명 숫자를 넣었는데 계산이 이상하다"는 초보의 고전적 버그입니다. 원인의 9할이 "숫자인 줄 알았는데 문자열이었다"입니다. GetType()은 의심될 때 정체를 밝히는 신분증 확인기라고 생각하세요.

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

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

"이름: $name"
'이름: $name'

출력:

이름: Lee
이름: $name

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

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

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

예측해 보기: "내 나이: $a + $b 살"은 어떻게 출력될까요? (정답: 내 나이: 3 + 4 살$a$b는 각각 풀리지만 +는 그냥 글자 취급됩니다. 따옴표 안에서 계산은 일어나지 않습니다. 직접 확인해 보세요.)

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
"첫 번째 멤버: $($members[0])"
3
첫 번째 멤버: Kim

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

Kim Lee Park[0]

배열 전체가 풀린 뒤 [0]이 글자로 붙어 버렸습니다 — 파워쉘이 어디까지가 변수인지 헷갈린 겁니다. "큰따옴표 안에서 복잡한 건 $( )에 담아라" — 이것만 기억하세요.

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

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

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

$now = Get-Date
$now
2026년 9월 9일 수요일 오전 8:31:07

무슨 일이 일어났나: Get-Date의 결과(현재 시각)가 화면에 출력되는 대신 $now라는 상자에 들어갔습니다. 이제 이 값을 원하는 만큼 재사용할 수 있습니다.

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

$services = Get-Service
$services.Count
310

(숫자는 컴퓨터마다 다릅니다. 필자의 PC에서는 310이 나왔습니다.)

출력 읽는 법: 컴퓨터의 전체 서비스 목록이 $services라는 배열에 들어갔고, .Count로 개수를 샀습니다. 명령 결과가 배열이 된 겁니다 — 개별 서비스는 $services[0]처럼 번호로도 꺼낼 수 있습니다.

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

예측해 보기: $services를 실행한 직후와 10분 뒤, 두 번의 .Count는 같을까요? (정답: 보통 같지만, 그 사이 서비스가 시작되거나 중지되면 달라질 수 있습니다. 변수는 저장된 순간의 스냅샷이라는 점 — 이 감각이 "기록과 현재를 비교한다"는 보안 사고방식의 출발점입니다.)


4. 미션과 연습문제

미션 — 멤버 소개 스크립트

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

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

연습문제

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

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

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

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


5. 모범 답안과 완료 기준

미션 모범 답안

$team = @("Lee", "Kim", "Park")
$team.Count
"우리 팀은 $($team.Count)명입니다"
"팀장은 $($team[0])입니다"

기대 출력:

3
우리 팀은 3명입니다
팀장은 Lee입니다

검증하는 법: 세 번째 출력에서 N 자리에 실제 숫자가 나오면 성공, $team.Count가 글자로 나오면 따옴표 문제(3-4절 복습), 네 번째에서 이상한 문장이 나오면 $( ) 문제(3-6절 복습)입니다.

심화: $team[3]을 출력하면 어떻게 될까요? (힌트: 번호는 0부터 세고, 목록엔 0·1·2번만 있습니다. 직접 해 보세요 — 실측하면 조용히 아무것도 안 나옵니다. "없는 칸은 오류가 아니라 빈 값"이라는 파워쉘의 성격도 이번에 배워 둡시다.)

연습문제 해답

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

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

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

문제 4 해답. 빈 값이 됩니다(또는 오류). 변수는 메모리에만 저장되고 파워쉘 창을 닫으면 사라집니다. 이것이 Step 9에서 "스크립트 파일로 저장"하는 이유입니다 — 파일은 창이 닫혀도 남습니다.

완료 기준 체크리스트

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

6. 흔한 실수와 해결

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

증상: $name = "Lee"를 치고 아무 출력도 없음.
원인: 고장이 아닙니다. 저장 명령은 원래 조용합니다.
해결: $name을 한 번 더 쳐서 내용을 확인하세요. "입력했는데 조용하다 = 저장됐다"로 이해하면 됩니다.

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

증상: "이름: $name"이름: $name으로 출력됨.
원인: 작은따옴표 ' '를 쓰고 있습니다. 작은따옴표는 내용을 있는 그대로 취급합니다.
해결: 큰따옴표 " "로 바꾸세요. 이 함정은 모든 초보가 한 번은 겪는 통과의례입니다.

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

증상: 3 + 4를 기대했는데 34가 나옴.
원인: 값을 따옴표로 감싸서 문자열이 됐습니다. 문자열의 +는 이어 붙이기입니다.
해결: 따옴표 없이 $a = 3처럼 저장하세요. 의심스러우면 $a.GetType().Name으로 신분 확인 — Int32가 나와야 숫자입니다.

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

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

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

증상: 분명 저장했는데 빈 값이 나옴.
원인: 파워쉘 창을 닫았다 열었거나, 다른 창에서 만들었습니다. 변수는 메모리에만 살고, 창마다 별개입니다.
해결: 같은 창에서 이어서 실습하세요. 창을 닫으면 변수는 전부 사라집니다.


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 완료입니다. 사이드바의 체크박스를 눌러 진도를 저장하세요.