멤버 변수와 로컬 변수
📖 개념 설명 (이해하기 쉽게)
변수는 “값을 넣어 두는 저장소”인데, 선언한 위치에 따라 멤버 변수와 로컬 변수로 나뉩니다.
| 구분 | 선언 위치 | 살아 있는 동안 | 쓰는 범위 |
|---|---|---|---|
| 멤버 변수 | 클래스 안, 메소드 밖 | 객체가 있는 동안 계속 유지 | 그 클래스의 모든 메소드에서 사용 가능 |
| 로컬 변수 | 메소드 안 | 그 메소드가 실행되는 동안만 | 그 메소드 안에서만 사용 가능 |
비유:
- 멤버 변수 = 방(클래스) 안에 있는 서랍. 방에 있는 동안 계속 있고, 방 안의 누구나 쓸 수 있음.
- 로컬 변수 = 지금 하고 있는 일에만 쓰는 메모지. 일(메소드)이 끝나면 사라짐.
코드로 보기:
public class Player : MonoBehaviour
{
// ---------- 멤버 변수 (클래스 안, 메소드 밖) ----------
// 객체가 있는 동안 유지. Start, Update 등 여러 메소드에서 쓸 수 있음
private int score;
private int level;
void Start()
{
// ---------- 로컬 변수 (메소드 안) ----------
// Start()가 실행되는 동안만 존재. Start() 안에서만 쓸 수 있음
int bonus = 10;
string message = "시작!";
score = 0; // 멤버 변수에 값 넣기
level = 1;
Debug.Log(message + " 점수: " + score);
}
void Update()
{
// Update() 안에서는 bonus, message 를 쓸 수 없음 (로컬이라 Start()에서만 유효)
score += 1; // 멤버 변수는 여기서도 쓸 수 있음
}
}
정리:
- 여러 메소드에서 같이 써야 하는 값 → 멤버 변수 (클래스 안, 메소드 밖에 선언)
- 한 메소드 안에서만 잠깐 쓰는 값 → 로컬 변수 (그 메소드 안에 선언)
📐 컨벤션 (이름·위치)
1. 이름 짓기
| 종류 | 권장 컨벤션 | 예시 |
|---|---|---|
| 멤버 변수 | camelCase (첫 글자 소문자) | score, level, playerName, isGameOver |
| 로컬 변수 | camelCase | bonus, message, tempValue |
| 상수 (변하지 않는 값) | PascalCase 또는 UPPER_SNAKE | MaxLevel, MAX_SCORE |
C#에서는 private 멤버에 _를 붙이는 방식(_score)도 자주 쓰이지만, 이 튜토리얼에서는 camelCase만 사용합니다.
2. 위치
| 종류 | 권장 위치 |
|---|---|
| 멤버 변수 | 클래스 맨 위에 모아서 선언 (메소드보다 위) |
| 로컬 변수 | 쓰기 직전에 가깝게 선언 (메소드 안) |
예시:
public class GameController : MonoBehaviour
{
// 멤버 변수: 클래스 상단에 모음
private int score;
private int level;
private GameBoard gameBoard;
void Start()
{
// 로컬 변수: 사용하는 곳 가까이
gameBoard = FindObjectOfType<GameBoard>();
int linesCleared = 0;
Debug.Log("레벨: " + level);
}
}
📚 단계별로 확장하기
이 개념은 한 번에 외우지 말고, 단계별 학습을 하면서 조금씩 써 보면 됩니다.
| 단계 | 이번 단계에서 익히는 것 |
|---|---|
| 3단계 | 변수는 클래스 안(메소드 밖) 에 두면 멤버, 메소드 안에 두면 로컬. TetrisBlock의 변수 위치 구분 |
| 4단계 | MoveLeft() 같은 메소드 안에서 잠깐 쓰는 값 → 로컬. 클래스 위에 두는 값 → 멤버 |
| 5단계 | FindObjectOfType 결과를 한 번 저장해 두고 여러 메소드에서 쓰려면 → 멤버 변수에 저장 |
| 6~7단계 | score, level, grid 같은 상태를 유지하는 값 → 멤버. 메소드 안의 임시 값 → 로컬 |
| 8단계 | 멤버는 클래스 상단, 로컬은 메소드 안. 이름은 둘 다 camelCase 로 통일 |
각 단계 문서 끝의 💡 이번 단계에서 익히는 개념을 읽어 보세요.
🛠️ 실습: 로컬 변수 · 멤버 변수 단계별로 느끼기
목표: 로컬 변수는 그 메소드 안에서만, 멤버 변수는 여러 메소드에서 쓸 수 있다는 걸 단계별로 Console로 확인합니다.
실습 단계
| 단계 | 할 일 | 구분 |
|---|---|---|
| 1단계 | 로컬 변수만 (메소드 안에서만 선언·사용) | 로컬 = 그 메소드 안에서만 존재 |
| 2단계 | 멤버 변수만 (클래스 안, 메소드 밖에 선언) | 멤버 = 여러 메소드에서 사용 가능 |
| 3단계 | 로컬 + 멤버 함께 써 보기 | 둘의 차이를 한 번에 느끼기 |
이 실습 전용 씬 만들기 (환경 설정)
먼저 이 실습 전용 씬을 만든 뒤 아래 순서로 진행합니다. (자세한 씬 만드는 방법은 개념 실습 테스트 환경 가이드의 씬 만드는 방법 참고.)
이 실습만 할 전용 씬이 없으면 아래 순서로 한 번만 만듭니다. (이미 ConceptTest_MemberLocal 씬이 있으면 File → Open Scene으로 열고 아래 실습만 이어서 하세요.)
- File → New Scene → Basic (Built-in) 또는 Empty → Create
- File → Save As → 저장 위치: Assets/Scenes → 파일 이름: ConceptTest_MemberLocal → Save
- 아래 실습은 모두 이 씬에서 진행합니다. (다른 문서로 왔다 갔다 하지 않습니다.)
실습 1단계: 로컬 변수만 (메소드 안에서만)
목표: 메소드 안에서 선언한 변수는 그 메소드 안에서만 쓸 수 있다는 걸 확인합니다.
- 스크립트 생성: 이름
MemberLocalTest - 아래 코드로 1단계만 작성 후 Play
using UnityEngine;
public class MemberLocalTest : MonoBehaviour
{
void Start()
{
// 로컬 변수: Start() 안에서만 선언·사용
int bonus = 5;
int count = 0;
Debug.Log("[Start] 로컬 bonus: " + bonus);
Debug.Log("[Start] 로컬 count: " + count);
}
void Update()
{
// 여기서 bonus, count 를 쓸 수 없음! (로컬이라 Start()에만 있음)
// 아래 줄은 오류가 나므로 주석 처리하고, "로컬은 이 메소드 안에서만" 확인
// Debug.Log(bonus); // 오류: bonus는 Start()에만 있음
}
}
- Console 확인: Start에서만
bonus,count출력됨. - 직접 해보기: Update() 안에
int temp = 10;을 넣고, Start() 안에서temp를 쓰려고 하면 쓸 수 없음을 확인해 보세요.
실습 2단계: 멤버 변수만 (클래스 안, 메소드 밖)
목표: 클래스 안, 메소드 밖에 선언한 변수는 여러 메소드에서 쓸 수 있다는 걸 확인합니다.
- 같은 스크립트를 아래처럼 멤버 변수만 사용하도록 바꿉니다.
using UnityEngine;
public class MemberLocalTest : MonoBehaviour
{
// 멤버 변수: 클래스 안, 메소드 밖 → Start(), Update() 둘 다에서 사용 가능
private int totalCount = 0;
void Start()
{
Debug.Log("[Start] 멤버 totalCount: " + totalCount);
totalCount = 10; // 멤버에 값 넣기
Debug.Log("[Start] totalCount 변경 후: " + totalCount);
}
void Update()
{
totalCount += 1; // 멤버는 Update()에서도 쓸 수 있음
if (totalCount % 60 == 0)
Debug.Log("[Update] 멤버 totalCount: " + totalCount);
}
}
- Play → Console 확인: Start에서 10으로 바뀐 뒤, Update에서 totalCount가 계속 증가하는 것 확인.
- 정리:
totalCount는 멤버 변수이므로 Start()가 끝나도 사라지지 않고, Update()에서도 쓸 수 있습니다.
실습 3단계: 로컬 + 멤버 함께
목표: 로컬 변수(메소드 안)와 멤버 변수(클래스 안, 메소드 밖)를 같이 써서 차이를 느껴 봅니다.
- 같은 스크립트를 아래처럼 로컬 + 멤버를 같이 쓰도록 수정합니다.
using UnityEngine;
public class MemberLocalTest : MonoBehaviour
{
// 멤버 변수: 클래스 안, 메소드 밖 → 여러 메소드에서 사용 가능
private int totalCount = 0;
void Start()
{
// 로컬 변수: Start() 안에서만 존재
int bonus = 5;
Debug.Log("[Start] 로컬 bonus: " + bonus);
Debug.Log("[Start] 멤버 totalCount: " + totalCount);
totalCount += bonus; // 멤버에 값 더함
Debug.Log("[Start] totalCount 변경 후: " + totalCount);
}
void Update()
{
// Update() 안에서는 bonus 를 쓸 수 없음 (로컬이라 Start()에만 있음)
totalCount += 1; // 멤버는 여기서도 사용 가능
if (totalCount % 60 == 0)
Debug.Log("[Update] 멤버 totalCount: " + totalCount);
}
}
- Hierarchy → Create Empty → 이름:
MemberLocalTestObj→ MemberLocalTest 스크립트 드래그로 추가 -
Play → Console 확인: Start에서 로컬
bonus, 멤버totalCount출력. Update에서는 멤버만 증가. - 직접 해보기:
Update()안에int temp = 10;로컬 변수를 넣고,Start()안에서는temp를 쓸 수 없는지 확인해 보세요.
| ← 개념 목록으로 | 멤버와 메소드 |