C# - 구조체 (Struct, Structure)

2025. 9. 12. 14:17·C#

구조체 (Struct, Structure)

구조체는 여러 데이터를 하나의 단위로 묶어서 표현할 수 있는 사용자 정의 자료형이다.

 

공식 문서에서는

구조체는 값 형식으로, 여러 개의 관련된 변수를 하나의 단위로 캡슐화하는 자료형입니다.

 

라고 되어있다.

열거형 보다는 알아들을만 하다.

즉, 여러 개의 변수를 하나의 박스 안에 묶어 놓은 것이 구조체인데 이것을 잘 활용하면 나만의 커스텀 자료형을 정의해서 사용할 수 있다는 이야기다.

 

구조체를 선언하는 방식은 아래와 같다.

struct Car
{
	public float maxSpeed;		// 최고 속도
	public string maker;		// 제작사
	private int carNumber;		// 차량 번호 (비공개)
}

 

이렇게 Car라는 새로운 자료형을 만들어서 직접 변수 선언이 가능하다.

Car firstCar;
firstCar.maxSpeed = 480.5f;
firstCar.Maker = StarkIndustry;

Console.WriteLine(firstCar.maxSpeed);	// 480.5f
Console.WriteLine(firstCar.Maker);	// StarkIndustry

 

 

왜 이런게 필요한지 어떻게 활용하는지 와닿지 않을 수 있다.

예시 코드를 더 확인해보자.

using System;

namespace structure
{
    internal class Program
    {
        static void Main(string[] args)
        {
            float maxSpeedCar1 = 220.4f; // 첫째 자동차 최고 속도
            string makerCar1 = "Honda";
            int carNumberCar1 = 1234;

            float maxSpeedCar2 = 180.4f;
            string makerCar2 = "Toyota";
            int carNumberCar2 = 2345;

            float maxSpeedCar3 = 150f;
            string makerCar3 = "Kia";
            int carNumberCar3 = 3456;

            Console.WriteLine(maxSpeedCar1);
            Console.WriteLine(makerCar1);
            Console.WriteLine(carNumberCar1);
            
            Console.WriteLine(maxSpeedCar2);
            Console.WriteLine(makerCar2);
            Console.WriteLine(carNumberCar2);

            Console.WriteLine(maxSpeedCar3);
            Console.WriteLine(makerCar3);
            Console.WriteLine(carNumberCar3);
        }

    }
}

 

이런 코드가 있다고 가정해보자.

지금은 메이커가 3개 뿐이지만 저게 수십개가 되고, 관리해야할 변수가 늘어나면 정신없이 나열되어 있을 것이다.

작성자도 헷갈릴 거 같은데 협업 시 남이 코드를 보면 읽는데만 더 많은 시간을 사용하게 될 것이고 휴먼 에러 발생 확률도 높아진다.

 

그래서 이걸 구조체로 나누어 보면 어떻게 되느냐?

using System;

namespace structure
{
    internal class Program
    {
        struct Car
        {
            public float maxSpeed;
            public string maker;
            private int carNumber;
        }

        static void Main(string[] args)
        {
            Car firstCar;
            firstCar.maxSpeed = 12.14f;
            firstCar.maker = "Tesla";
            
            Car SecCar;
            SecCar.maxSpeed = 222.14f;
            SecCar.maker = "Tesla";

            Console.WriteLine(firstCar.maxSpeed);
            Console.WriteLine(firstCar.maker);
            
            Console.WriteLine(SecCar.maxSpeed);
            Console.WriteLine(SecCar.maker);
            
            // .. . ..
        }

    }
}

 

코드가 줄어들긴 커녕 늘어났다고 할 수도 있지만 코드가 속성에 따라 분류되어 직관적으로 이해하기 더 좋아진 걸 볼 수 있다.

 

 

구조체의 특징

  • 값 형식 ( Value Type ) - 할당시 값이 복사 됨 (클래스는 참조 형식)
  • 기본 생성자 사용 불가 - 직접 초기화 하거나 사용자 정의 생성자를 만들어야 함
  • 필드, 메서드, 속성, 이벤트 포함 가능
  • 상속 불가 - 클래스와 달리 다른 구조체 / 클래스 를 상속받을 수는 없지만 인터페이스는 구현 가능

 

또한 구조체는 클래스와 비슷하게 생긴데다가 기능도 비슷해서 헷갈릴 수 있는데 몇가지 차이가 있다.

이걸 간단하게 표로 비교해서 보자.

구분 구조체 struct 클래스 class
형식 값 형식 Value Type 참조 형식 Reference Type
메모리 스택 Stack 힙 Heap
상속 불가 (인터페이스만 구현 가능) 가능
생성자 기본 생성자 불가 기본 생성자 자동 제공
복사 값 자체를 복사 참조(주소)가 복사

 

구조체는 작고 독립적인 데이터 묶음을 만들 때 적합하고

클래스는 상속, 다형성, 참조 공유가 필요한 복잡한 상황에 적합하다.


 

심화 실습 문제를 풀어보면서 구조체에 대해 조금 더 익혀보자

문제

- Weapon 이라는 구조체 설계도를 하나 만든 후, 속성으로는 public 문자열 형 name을 가지게 하세요.
- Soilder이라는 구조체 설계도를 하나 더 만든 후, 속성으로 Weapon구조체를 담을 수 있는 배열 및 현재 손에 들고 있는 Weapon이 무엇인지 저장할 배열의 인덱스로 사용할 정수형 변수 하나를 작성합니다.
- 메인에 돌아와서 솔져 구조체를 하나 만들어줍니다. 솔져의 무기 목록 배열에 Weapon 구조체를 3개 담을 수 있게 초기화 시켜주시고, 솔져가 가진 무기의 배열에 본인이 희망하는 이름을 담은 무기 3가지를 모두 기입하여 줍니다. 처음엔 1번을 들고 있습니다(인간의 말로)
- 함수를 하나 만들되, 솔져형을 참조형 인자로 받는 void형 함수를 제작할 것입니다. 함수의 이름은 ChangeWeapon으로 하고 기능은 다음과 같습니다.
    - 함수가 호출되면 배열 속의 Weapon 이름들을 전부 출력하고 다음줄에 어떤 무기로 바꿀것인지 콘솔에 적습니다.
    - 유저로부터 1~3사이 정수를 입력받되 1~3이 아닐 경우, 제대로 1~3사이 정수를 입력하라고 콘솔에 입력 후 무한으로 재입력을 요구합니다.
    - 제대로 1,2,3 중 하나를 입력 받았을 경우, 만약 본인의 손에 들고 있는 무기와 같은 무기를 입력하였어도 '현재 들고 있는 무기와 동일합니다' 를 출력 후, 재입력을 요구합니다.
    - 본인 손에 들고 있는 무기와는 다른 무기를 정상적으로 골랐다면 콘솔 출력을 통해 해당 무기로 바뀌었음을 출력합니다.
    - 이후 메인 문에 ChangeWeapon 함수를 한줄 한줄 3번 실행하되, 아래 각각의 상황에 맞게 호출하세요.
        - 시작 시 본인이 들고 있는 무기와 일치하는 숫자를 유저가 입력한 상황.
        - 1~3이 아닌 숫자를 입력한 상황.
        - 정상적으로 무기 변경이 일어날 수 있는 상황.
- 이외 자유롭게 제작, 자유롭게 테스트

using System;

namespace structure
{
    internal class Program
    {
        struct Weapon
        {
            public string name;
        }

        struct Soldier
        {
            public int currentWeapon;
            public Weapon[] weapons;
        }

        static void Main(string[] args)
        {
            // 솔져 스티브 정의 및 데이터 설정
            Soldier Steve;
            Steve.weapons = new Weapon[3];
            Steve.weapons[0].name = "Storm Breaker";
            Steve.weapons[1].name = "Vibranium Shield";
            Steve.weapons[2].name = "Bamboo Spear";
            Steve.currentWeapon = 0;

            // 무기 변경 함수 호출
            ChangeWeapon(ref Steve);
            ChangeWeapon(ref Steve);
            ChangeWeapon(ref Steve);
            // 무기 변경을 정상적으로 3번 완료하면 메인 종료            
        }

        // 무기 변경 함수
        static void ChangeWeapon(ref Soldier soldier)
        {
            // 배열 속 Weapon 이름들 전부 출력
            for (int i = 0; i < soldier.weapons.Length; i++)
            {
                Console.WriteLine(soldier.weapons[i].name);
            }

            // 입력 무한 요청
            int inputNum;
            Console.WriteLine($"어떤 무기로 바꿀 것입니까? (1 ~ {soldier.weapons.Length} 입력)");
            while (true)
            {
                if (int.TryParse(Console.ReadLine(), out inputNum))
                {
                    // 솔져 웨폰 범위까지만 입력 가능 (1부터 시작)
                    if (inputNum > 0 && inputNum <= soldier.weapons.Length)
                    {
                        // 현재 무기와 같은 번호 입력시 예외
                        if (inputNum - 1 == soldier.currentWeapon)
                        {
                            Console.WriteLine("현재 들고 있는 무기와 동일합니다");
                            Console.WriteLine("다시 입력해주세요");
                        }
                        else
                        {
                            // 정상 입력시 무기 변경 완료 및 루프 종료
                            Console.WriteLine($"{soldier.weapons[soldier.currentWeapon].name} 에서 {soldier.weapons[inputNum - 1].name} 으로 무기를 변경하였습니다  ");
                            soldier.currentWeapon = inputNum - 1;
                            break;
                        }

                    }
                    else
                    {
                        Console.WriteLine($"1 ~ {soldier.weapons.Length} 사이 정수를 입력하세요");
                    }
                }
            }
        }

    }
}

 

 

잘 작동하는데 여기선 작동 보다는 구조체를 간단하게라도 사용해보는 게 목적인 문제로 보인다.

열거형과 마찬가지로 적절한 곳에서 사용할 수 있도록 의식해서 연습하도록 하자.

'C#' 카테고리의 다른 글

C# - 콘솔프로젝트 : 숫자 야구 만들기  (0) 2025.09.12
C# - Window11 에서 Console.SetWindowSize 안 되는 문제  (0) 2025.09.12
C# - 열거형 (Enum, Enumeration)  (0) 2025.09.12
C# - 재귀함수 (Recursive Function)  (0) 2025.09.11
C# - Main  (0) 2025.09.11
'C#' 카테고리의 다른 글
  • C# - 콘솔프로젝트 : 숫자 야구 만들기
  • C# - Window11 에서 Console.SetWindowSize 안 되는 문제
  • C# - 열거형 (Enum, Enumeration)
  • C# - 재귀함수 (Recursive Function)
ellug
ellug
Web / App / Game Dev
  • ellug
    dev.ellug
    ellug
  • 전체
    오늘
    어제
    • 분류 전체보기 (95)
      • Javascript (React, Next) (1)
      • C# (66)
      • Graphics (1)
      • Unity (25)
      • 프로그래머스 (0)
        • Lv.0 (0)
        • Lv.1 (0)
        • Lv.2 (0)
        • Lv.3 (0)
      • AI Agent (0)
      • StableDiffusion (0)
      • ETC (1)
      • 잡담 (0)
      • 유머 (0)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    추상 클래스
    터미널
    Design Pattern
    Queue
    Abstract
    interface
    console
    unity
    Network
    list
    struct
    콘솔
    스택
    class
    알고리즘
    delegate
    useState
    C#
    큐
    firebase
    자료구조
    유니티
    네트워크
    stack
    inputsystem
    최적화
    클래스
    게임
    function
    Photon
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
ellug
C# - 구조체 (Struct, Structure)
상단으로

티스토리툴바