김산나
[멋쟁이사자처럼부트캠프 유니티 게임 개발 7기] 2026년 1월 13일 회고록 - 클래스 본문
2026_01_13 강의 요약본
1. 클래스
클래스는 설계도라고 생각하면 좋다.
클래스는 다음과 같이 구성되어 있다.
class 클래스이름
{
// 필드 - (변수 데이터)
// 프로퍼티 - (속성)
// 메서드 - (기능)
}
대충 말하자면 변수와 함수의 집합체이다.
변수가 클래스 안에서는 필드로 불리고, 함수는 메서드로 불린다.
프로퍼티는 함수의 일종? 같은 건데 이따 나오니 그때 ㄱㄱ
가령 "플레이어 캐릭터"에 대한 클래스를 생성해 두면, 매번 캐릭터를 만들 때마다 변수, 기능을 설정해주는 것보다 쉽다.
<실습 코드>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _20260113
{
class 클래스이름
{
// 필드 - (변수 데이터)
// 프로퍼티 - (속성)
// 메서드 - (기능)
}
class Character
{
// public은 다른 곳에서 사용 가능하다.
// private는 클래스 내부에서만 사용할 수 있다.
public string name;
public int level;
public int hp;
public int mp;
private int maxHp;
private int maxMp;
// 기본 생성자 - 초기화 담당 (Defalt Data)
public Character()
{
name = "용사님";
level = 1;
hp = 100;
mp = 100;
}
// 인자 있는 생성자
public Character(int _maxHp, int _maxMp)
{
maxHp = _maxHp;
maxMp = _maxMp;
}
public void ShowStatus()
{
Console.WriteLine($"이름: {name}");
Console.WriteLine($"레벨: {level}");
Console.WriteLine($"hp: {hp}");
Console.WriteLine($"최대 hp: {maxHp}");
Console.WriteLine($"mp: {mp}");
Console.WriteLine($"최대mp: {maxMp}");
}
}
internal class Class_1
{
static void Main(string[] args)
{
// 객체 생성
Character player1 = new Character(); // 메모리 지정, 생성자 호출
player1.name = "홍길동";
player1.level = 1;
player1.hp = 100;
player1.mp = 80;
Console.WriteLine($"이름: {player1.name}");
Console.WriteLine($"레벨: {player1.level}");
Console.WriteLine($"hp: {player1.hp}");
// Console.WriteLine($"최대 hp: {player1.maxHp}"); - private 사용 불가
Console.WriteLine($"mp: {player1.mp}");
// Console.WriteLine($"최대mp: {player1.maxMp}"); - private 사용 불가
Console.WriteLine();
player1.ShowStatus(); // 클래스 내 함수 사용, 함수를 통한 private 출력 가능
Console.WriteLine();
Character player2 = new Character(100, 100); // 새로운 객체 생성, 인자가 있는 생성자 받음, private 값 입력 가능
player2.name = "김철수";
player2.level = 3;
player2.hp = 10;
player2.mp = 20;
player2.ShowStatus(); // 함수를 통한 private 출력 가능
}
}
}
*참고 - public과 private
public - 클래스를 선언한 곳에서 자유롭게 수정이 가능함
private - 직접적으로 수정이 불가능하지만, 간접적인 방식(함수, 생성자, 이후에 나올 프로퍼티 등)을 통해 변경할 수 있다.
* 참고 - 절차 지향 vs 객체 지향
절차 지향 프로그래밍 (Procedural Programming)
프로그램을 순차적인 명령어의 목록으로 보는 방식
객체 지향 프로그래밍 (Object-Oriented Programming)
프로그램을 객체들의 상호작용으로 보는 방식
C#이 객체 지향에 해당된다.
2. 클래스의 생성자
생성자란 클래스 객체가 만들어질 때 가장 먼저 한 번 호출되는 함수임.
해당 객체의 초기화를 담당한다.
<실습 코드>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace _20260113
{
class Monster
{
public string name;
public int level;
public int hp;
public int atk;
public int def;
public int expReward;
public Monster()
{
name = "슬라임";
level = 1;
hp = 10;
atk = 10;
def = 5;
expReward = 10;
}
public Monster(string monsterName, int monsterLevel)
{
name = monsterName;
level = monsterLevel;
hp = 50 * level;
atk = 10 * level;
def = 5 * level;
expReward = 10 * level;
}
public void ShowStats()
{
Console.WriteLine($"몬스터 {name} (Lv.{level}) 등장 !");
Console.WriteLine($" HP: {hp}");
Console.WriteLine($" 공격력: {atk}");
Console.WriteLine($" 방어력: {def}");
Console.WriteLine($" 경험치: {expReward}");
}
}
internal class Class_3
{
static void Main(string[] args)
{
// 기본 생성자를 사용하여 객체 생성
Monster Slim = new Monster();
Slim.ShowStats();
// 인자 있는 생성자 사용, 고블린 생성
Monster Goblin = new Monster("고블린", 5);
Goblin.ShowStats();
Console.WriteLine("\n=== 필드 몬스터 ===");
Monster[] monsters = new Monster[3];
monsters[0] = new Monster("늑대", 3);
monsters[1] = new Monster("오크", 7);
monsters[2] = new Monster("트롤", 10);
for(int i =0;i<monsters.Length;i++)
{
monsters[i].ShowStats();
Console.WriteLine();
}
}
}
}
생성자 또한 오버로딩이 가능하다. 매개변수에 차이를 주면 된다.
<출력 결과>

참고로 초기화 안 해주면 0, null, false같은 값 들어가 있음.
3. 프로퍼티 (property)
프로퍼티는 클래스 내의 private 데이터를 지키는 문지기 역할을 한다.
정확히 말하자면 private의 값을 public과 같이 변경 가능한 통로인데, 그 통로에 여러 검수 기능을 추가할 수 있기 때문에 문지기의 역할을 할 수 있다.
1. public 자료형 프로퍼티 이름 { get; set; }
2. public 자료형 프로퍼티 이름
{
get { return 리턴값; }
set
{
할당할 변수 = value;
}
}
이런 식으로 사용하는데, 먼저 상단에 private 변수를 선언하고, public으로 선언한 프로퍼티를 통해 값을 받아 "value"라는 임시 변수를 통해 대리 전달받는 것이다.
앞서 설명했듯 private 데이터들은 클래스 내부의 함수를 통해 값을 바꿀 수 있다. 그 원리를 활용한 것이 프로퍼티이다.

실습 코드를 보며 더 정확하게 이해를 해보자.
<실습 코드>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _20260113
{
class Character2
{
private int atk; // 은닉성, 추상화
public int Atk { get; set; } // 자동 프로퍼티
// 읽기 전용
public int MaxHp { get; private set; }
}
internal class Property
{
static void Main(string[] args)
{
Character2 c = new Character2();
c.Atk = 1;
Console.WriteLine("공격력: " + c.Atk);
}
}
}
<출력 결과>

하단을 보면 알 수 있듯, private 변수인 atk에 값을 할당하는 것이 아닌, 프로퍼티 Atk에 값을 할당하였다.
사실 이 예제는 1번 방식인 "자동 프로퍼티"를 보여주는 예시로, 사실상 atk가 없어도 너무너무 잘 돌아가는 코드이다.
자동 프로퍼티 방식은 프로퍼티를 좀 더 쉽게 사용할 수 있도록 만든 일종의 줄임말이다.
private 변수와 상호작용하는 코드 예시는 다음과 같다.
<실습 코드>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _20260113
{
class Player
{
private string name;
private int gold;
private int maxHP;
public string Name { get { return name; } set { name = value; } }
public int Gold
{
get { return gold; }
set { if (value < 0)
{
Console.WriteLine("골드가 부족합니다.");
}
else
{
gold = value;
}
}
}
}
internal class Property_2
{
static void Main(string[] args)
{
Player player = new Player();
player.Name = "홍길동";
player.Gold = -1000;
// player.maxHP = 100; // ->읽기 전용이라 수정 불가
Console.WriteLine($"이름: {player.Name}");
Console.WriteLine($"골드: {player.Gold}");
}
}
}
<출력 결과>

먼저 값을 프로퍼티(Gold)에 할당한다.
그럼 프로퍼티의 로직대로 할당된 값을 확인하고, 그에 맞는 판단을 한다.
예제에는 -1000을 넣었기 때문에 private 변수인 gold에 접근하지 못했다.
다음 예제는 생성된 객체의 값을 프로퍼티를 통해 판정하는 경우를 보여준다.
<실습 코드>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Schema;
namespace _20260113
{
class Students
{
private string name;
private int score;
public int Score
{
get { return score; }
set
{
if (value >= 0 && value <= 100) score = value;
else { Console.WriteLine("잘못된 값입니다."); }
}
}
public string Grade // 읽기 전용이면 굳이 원본 변수 선언할 필요 없음.
{
get
{
{
if (score >= 90) return "A";
else if (score >= 80) return "B";
else if (score >= 70) return "C";
else if (score >= 60) return "D";
else return "F";
}
}
}
public Students(string _name)
{
name = _name;
}
public void StudentInfo()
{
Console.WriteLine("-----------------------------");
Console.WriteLine($"이름: {name}");
Console.WriteLine($"점수: {score}");
Console.WriteLine($"등급: {Grade}");
Console.WriteLine("-----------------------------\n");
}
}
internal class Property_3
{
static void Main(string[] args)
{
Students student = new Students("홍길동");
student.Score = 95;
student.StudentInfo();
Console.WriteLine();
student.Score = 75;
student.StudentInfo();
Console.WriteLine();
// 잘못된 값 입력 시도
student.Score = 150; // 100으로 제한되어야 함
student.Score = -10; // 0으로 제한되어야 함
student.StudentInfo();
}
}
}
private 변수 score의 프로퍼티인 Score은 0-100의 점수인지 확인하는 역할을 하고 있다.
Grade의 같은 경우, 마치 public 변수처럼 작동하고 있다. Grade값을 결정하는 변수는 score.
Grade 프로퍼티에서는 score의 값을 확인하고 그 값에 맞는 결과값을 뱉는다.
변수의 탈을 쓴 함수 = 프로퍼티
4. 정적 멤버 static
전날에도 가볍게 살펴본 내용이다.
static키워드와 함께 변수를 선언하면 생성된 모든 객체들이 공유하게 된다.
예제를 확인하자.
<실습 코드>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _20260113
{
class Character3
{
// 정적 멤버 (Static Members)
// static: 모든 캐릭터가 공유
public static int totalCount = 0;
// 일반: 각 캐릭터마다 다름
public string name;
public void AddCounter()
{
totalCount++;
}
}
internal class Static
{
static void Main(string[] args)
{
Character3 c1 = new Character3();
Character3 c2 = new Character3();
c1.name = "전사";
c2.name = "마법사";
Character3.totalCount = 1; // 생성한 객체가 아닌, 클래스를 호출하여 사용 (해당 클래스의 객체들이 공유하는 값이므로)
Console.WriteLine(c1.name);
Console.WriteLine(c2.name);
c1.AddCounter();
c2.AddCounter();
Console.WriteLine("카운트: " + Character3.totalCount);
}
}
}
모두 공유하는 값이기 때문에 생성된 객체의 이름이 아닌, 클래스 이름으로 호출한다.
Console.WriteLine("카운트: " + Character3.totalCount);
또한 전역변수의 값을 수정하는 함수를 어떤 객체에서 호출해도 값이 그대로 전역변수 하나에 공유되는 것을 확인할 수 있다.
<출력 결과>

5. this
생성자를 사용할 때, 정신줄을 놓고 있으면 필드값과 동일한 이름으로 넣게 된다.
그럴 때 고민하지 말고 this 키워드를 사용하면 된다. 먼저 예제를 확인하자.
<실습 코드>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _20260113
{
class Skill
{
private string name;
private int atk;
public Skill()
{
}
public Skill(string name, int atk)
{
this.name = name; // 변수 이름이 충돌하는 경우 사용. ( This 붙은 게 생성된 객체의 것. )
this.atk = atk;
}
public void SkillStart()
{
Console.WriteLine("스킬 이름: " + this.name); // 이건 사실 생략해도 됨
Console.WriteLine("스킬 데미지: " + this.atk);
}
}
internal class This
{
static void Main(string[] args)
{
Skill s = new Skill("블리자드", 1000000);
s.SkillStart();
}
}
}
name =name 이런 식으로 코딩하면 당연히 에러가 난다. 하지만 this라는 키워드로 이 변수는 객체의 것입니다 하면 컴퓨터가 이해할 수 있다.
반대로 this가 없는 name의 경우 해당 함수의 (매개)변수이다.
<출력 결과>

정상적으로 출력되는 것을 볼 수 있다.
===========================================================
클래스를 선언 및 사용할 수 있게 되었다 !
전역 멤버를 사용할 수 있게 되었다 !
