테트리스 강좌

초등학생도 쉽게 따라할 수 있는 Unity 테트리스 게임 개발 강좌 자료

멤버 변수와 로컬 변수

📖 개념 설명 (이해하기 쉽게)

변수는 “값을 넣어 두는 저장소”인데, 선언한 위치에 따라 멤버 변수와 로컬 변수로 나뉩니다.

구분 선언 위치 살아 있는 동안 쓰는 범위
멤버 변수 클래스 안, 메소드 밖 객체가 있는 동안 계속 유지 그 클래스의 모든 메소드에서 사용 가능
로컬 변수 메소드 안 그 메소드가 실행되는 동안만 그 메소드 안에서만 사용 가능

비유:

코드로 보기:

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으로 열고 아래 실습만 이어서 하세요.)

  1. File → New Scene → Basic (Built-in) 또는 Empty → Create
  2. File → Save As → 저장 위치: Assets/Scenes → 파일 이름: ConceptTest_MemberLocal → Save
  3. 아래 실습은 모두 이 씬에서 진행합니다. (다른 문서로 왔다 갔다 하지 않습니다.)

실습 1단계: 로컬 변수만 (메소드 안에서만)

목표: 메소드 안에서 선언한 변수는 그 메소드 안에서만 쓸 수 있다는 걸 확인합니다.

  1. 스크립트 생성: 이름 MemberLocalTest
  2. 아래 코드로 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()에만 있음
    }
}
  1. Console 확인: Start에서만 bonus, count 출력됨.
  2. 직접 해보기: Update() 안에 int temp = 10; 을 넣고, Start() 안에서 temp를 쓰려고 하면 쓸 수 없음을 확인해 보세요.

실습 2단계: 멤버 변수만 (클래스 안, 메소드 밖)

목표: 클래스 안, 메소드 밖에 선언한 변수는 여러 메소드에서 쓸 수 있다는 걸 확인합니다.

  1. 같은 스크립트를 아래처럼 멤버 변수만 사용하도록 바꿉니다.
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);
    }
}
  1. Play → Console 확인: Start에서 10으로 바뀐 뒤, Update에서 totalCount가 계속 증가하는 것 확인.
  2. 정리: totalCount는 멤버 변수이므로 Start()가 끝나도 사라지지 않고, Update()에서도 쓸 수 있습니다.

실습 3단계: 로컬 + 멤버 함께

목표: 로컬 변수(메소드 안)와 멤버 변수(클래스 안, 메소드 밖)를 같이 써서 차이를 느껴 봅니다.

  1. 같은 스크립트를 아래처럼 로컬 + 멤버를 같이 쓰도록 수정합니다.
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);
    }
}
  1. Hierarchy → Create Empty → 이름: MemberLocalTestObj → MemberLocalTest 스크립트 드래그로 추가
  2. Play → Console 확인: Start에서 로컬 bonus, 멤버 totalCount 출력. Update에서는 멤버만 증가.

  3. 직접 해보기: Update() 안에 int temp = 10; 로컬 변수를 넣고, Start() 안에서는 temp를 쓸 수 없는지 확인해 보세요.

← 개념 목록으로 멤버와 메소드