본문 바로가기
개발💻/C#

[C#] readonly와 const의 차이

by Sports Entrepreneur 2024. 10. 5.

C#에서 readonly와 const의 차이를 이해하기  

C#에서 상수를 다룰 때 우리는 흔히 constreadonly라는 두 가지 키워드를 접하게 됩니다. 이 두 키워드는 값을 변경할 수 없다는 공통점을 가지고 있지만, 그 용도와 동작 방식에는 큰 차이가 있습니다. 그 차이를 명확히 이해하는 것은 성능 최적화, 유지보수성, 코드 가독성에서 큰 도움이 될 수 있습니다. 오늘은 constreadonly의 차이점을 자세히 살펴보고, 어떤 상황에서 각각을 사용하는 것이 더 좋은지 알아보겠습니다.

 

값이 할당되는 시점: 컴파일 타임 vs 런타임

가장 큰 차이점은 값이 결정되는 시점입니다.

  • const컴파일 타임 상수입니다. 즉, 프로그램이 컴파일될 때 값이 확정되어야 합니다. const로 선언된 값은 코드에서 하드코딩된 값처럼 처리됩니다. 따라서 const는 선언할 때 바로 값을 할당해야 하며, 이후에 절대 변경할 수 없습니다.

    아래 코드에서 MaxPlayers는 컴파일 시점에 값이 10으로 고정됩니다. 이 상수는 변경할 수 없으며, 모든 코드에서 동일한 값을 공유하게 됩니다.
public const int MaxPlayers = 10;

 

  • readonly런타임 상수입니다. 즉, 객체가 생성되는 시점에 값이 확정될 수 있습니다. readonly는 선언 시 초기화할 수도 있지만, 생성자에서 값이 설정될 수도 있습니다. 이렇게 동적으로 값을 설정할 수 있기 때문에 더 유연하게 사용할 수 있습니다.

    아래 코드에서 PlayerID는 객체가 생성될 때 결정됩니다. 즉, 객체마다 고유한 PlayerID를 가질 수 있다는 장점이 있습니다.
public class Player
{
    public readonly int PlayerID;

    public Player(int id)
    {
        PlayerID = id;
    }
}

 

 

메모리 할당 방식: 고정된 메모리 vs 인스턴스별 메모리

  • const고정된 메모리 위치에 저장됩니다. 이는 프로그램 내 모든 인스턴스에서 동일한 값을 공유한다는 의미입니다. const는 값이 변하지 않는 데이터의 경우 메모리 사용을 최적화할 수 있는 장점이 있습니다. 그러나 그 값은 프로그램이 시작될 때부터 끝날 때까지 동일하게 유지되어야만 합니다.
using System;

public class GameSettings
{
    // 컴파일 타임 상수 (고정된 값)
    public const int MaxPlayers = 10; // 모든 인스턴스가 이 값을 공유
}

public class Program
{
    public static void Main()
    {
        // 모든 인스턴스가 동일한 MaxPlayers 값을 참조
        Console.WriteLine("Maximum Players allowed: " + GameSettings.MaxPlayers);
    }
}
Maximum Players allowed: 10
  • readonly인스턴스 필드입니다. 즉, 각 객체가 고유한 값을 가질 수 있으며, 객체마다 별도의 메모리 공간이 할당됩니다. 이는 객체마다 다른 값을 가져야 하는 경우 매우 유용합니다. 예를 들어, 플레이어의 ID나 특정 설정 값 등을 저장할 때 readonly를 사용하면 객체마다 고유한 값을 안전하게 관리할 수 있습니다.
using System;

public class Player
{
    // 런타임 상수 (인스턴스마다 다를 수 있는 값)
    public readonly int PlayerID;

    // 생성자에서 PlayerID를 설정
    public Player(int id)
    {
        PlayerID = id;
    }

    public void DisplayID()
    {
        Console.WriteLine("Player ID: " + PlayerID);
    }
}

public class Program
{
    public static void Main()
    {
        // 인스턴스마다 다른 PlayerID 설정
        Player player1 = new Player(101);
        Player player2 = new Player(102);

        player1.DisplayID(); // 출력: Player ID: 101
        player2.DisplayID(); // 출력: Player ID: 102
    }
}

 

Player ID: 101
Player ID: 102

 

 

값을 설정할 수 있는 데이터 타입 

  • const는 기본 데이터 타입(예: int, float, bool) 또는 불변 객체(예: string)에만 사용할 수 있습니다. 왜냐하면 const는 컴파일 시점에 값을 결정해야 하기 때문에, 런타임에 변할 수 있는 값이나 참조 타입에는 사용할 수 없습니다.

    아래 예시에서 MaxHealth와 GameTitle은 const로 선언된 기본 데이터 타입입니다. 이 값들은 프로그램 내에서 불변으로 남게 됩니다.
public const int MaxHealth = 100;
public const string GameTitle = "Epic Adventure";
  • readonly참조 타입을 포함하여 모든 데이터 타입에 사용할 수 있습니다. 이는 참조 타입 객체나 배열 등 런타임에 생성되는 데이터를 상수로 처리하고 싶을 때 유용합니다.

    아래 코드는 readonly를 사용하여 배열을 정의한 예입니다. 배열 자체는 수정할 수 없지만, 개별 요소는 변경할 수 있습니다. 이를 통해 데이터 구조를 초기화한 후 불변으로 유지할 수 있습니다.
public class Config
{
    public readonly string[] Levels = { "Level1", "Level2", "Level3" };
}

 

 

수정 가능성: 절대 불변 vs 제한적 수정 

  • const절대로 수정할 수 없습니다. 상수는 코드 내에서 고정된 값으로 취급되며, 이를 수정하려면 코드를 다시 컴파일해야 합니다. 프로그램의 전반적인 실행 과정에서 이 값은 영구적으로 고정됩니다.
  • readonly는 생성자 내에서 한 번만 값을 설정할 수 있고, 이후에는 변경할 수 없습니다. 즉, 객체가 생성될 때 값이 동적으로 결정될 수 있지만, 한 번 설정된 이후에는 불변으로 유지됩니다. 이 특성 덕분에 readonly는 초기화 시에만 변경 가능하고, 그 이후로는 안전하게 값을 고정할 수 있습니다.

    아래 코드에서 Damage 값은 무기 생성 시에만 설정되고, 이후에는 변경되지 않습니다. 이를 통해 무기의 공격력이 불변함을 보장할 수 있습니다.
public class Weapon
{
    public readonly int Damage;

    public Weapon(int damage)
    {
        Damage = damage;  // 생성자에서 한 번만 값 설정 가능
    }
}

 

성능과 최적화 측면에서의 차이  

성능 관점에서도 차이점이 존재합니다.

  • const컴파일 시점에 상수 값으로 대체됩니다. 예를 들어, const 필드를 사용하는 코드는 실제로 상수 값으로 대체되므로 더 빠른 실행을 기대할 수 있습니다. 다만, 값이 변경되지 않는다는 제한이 있기 때문에 필요한 경우에만 사용해야 합니다.
  • readonly런타임에 값을 결정하므로, 약간의 성능 오버헤드가 있을 수 있습니다. 그러나 일반적인 경우 이러한 차이는 무시할 수 있는 수준입니다. 특히 참조 타입이나 런타임에 결정되어야 하는 값의 경우에는 readonly가 더 적합한 선택입니다.

 

언제 readonly를 사용하고 언제 const를 사용할까?  

이제 const와 readonly의 차이를 이해했으니, 실제로 언제 각각을 사용해야 할지 생각해볼 차례입니다.

  • const를 사용할 때:
    • 값이 절대 변경되지 않을 때 (예: 물리 상수, 게임의 상수 값 등).
    • 컴파일 타임에 값이 결정되어야 하며, 여러 곳에서 같은 값을 공유해야 할 때.
  • readonly를 사용할 때:
    • 런타임에 값이 결정되어야 할 때 (예: 객체 생성 시 초기화가 필요한 경우).
    • 참조 타입이나 복잡한 데이터 구조를 사용해야 할 때.
    • 객체마다 고유한 값을 가질 필요가 있을 때.

 

결론  

constreadonly는 모두 불변성을 제공하지만, 각각의 목적과 용도는 다릅니다. const는 변하지 않는 고정된 값을 필요로 할 때 이상적이며, readonly는 런타임에 값을 설정해야 하거나 참조 타입의 불변성을 보장해야 할 때 유용합니다.

이 두 키워드를 적절히 활용하면 코드의 안전성을 높이고, 유지보수성을 강화하며, 성능까지 최적화할 수 있습니다. 개발자는 이 차이점을 명확히 이해하고, 프로젝트의 요구사항에 맞게 올바른 키워드를 선택하는 것이 중요합니다.

 

'개발💻 > C#' 카테고리의 다른 글

[C#] Dynamic 타입: 유연성과 주의점  (0) 2024.11.30
[C#] 구조체와 클래스의 차이  (0) 2024.10.06
[C#] Coupling, Cohesion 1  (0) 2024.08.10
[C#] Observer Pattern 1  (0) 2024.07.13
[C#] Delegate 2  (0) 2024.06.24