Static classes를 사용하지 않는 방법
I’m happy to translate the article for you, but I’ll need the full text you’d like translated (the body of the post, including any headings, paragraphs, and code blocks). Please paste the content you want translated, and I’ll keep the source line and all formatting exactly as you requested.
정적 클래스와 메서드의 공통 특성
정적 클래스와 메서드는 종종 유틸리티 클래스로 사용되어 애플리케이션 전역에서 접근 가능한 함수를 제공합니다. 예를 들어, ‘Y’와 ‘N’을 true 또는 false 로 변환하는 코드를 반복해서 작성하는 대신, 이 로직을 정적 유틸리티 클래스에 넣어 필요할 때마다 재사용함으로써 Don’t Repeat Yourself 원칙을 따를 수 있습니다.
정적인 확장 메서드도 비슷한 이점을 제공하며, 기존 타입에 재사용 가능한 기능을 추가할 수 있게 해줍니다.
대부분의 개발자는 정적 클래스를 주로 이러한 유틸리티 시나리오에만 사용한다고 생각하고, 그 잠재력을 충분히 탐구하지 못합니다. 아래에 몇 가지 예시와 모범 사례 가이드를 소개합니다.
예시: 유틸리티 정적 클래스
public static class ConverterUtils
{
public static bool CharToBool(char c)
{
return c == 'Y' || c == 'y';
}
}
bool result = ConverterUtils.CharToBool('Y');
예시: 확장 메서드
public static class CharExtensions
{
public static bool ToBool(this char c)
{
return c == 'Y' || c == 'y';
}
}
bool result = 'N'.ToBool();
정적 클래스: 일반 개요
정적 클래스는 정적 멤버만을 포함하고 인스턴스화를 방지하기 위해 private 생성자를 가진 클래스입니다. 클래스를 static으로 선언하면 컴파일러와 다른 개발자에게 해당 클래스는 인스턴스화되지 않아야 하며, 멤버는 클래스 이름을 통해 직접 접근해야 함을 알립니다.
- 인스턴스가 필요 없음 – 정적 멤버를 사용하기 위해 객체를 만들 필요가 없으므로 전역 유틸리티 함수에 이상적입니다.
- 공유 상태(또는 그 부재) – 정적 메서드는 인스턴스 데이터(비정적 필드/속성)에 접근할 수 없으며, 다른 정적 멤버만 사용할 수 있습니다. 따라서 정적 필드를 사용하지 않는 한 상태가 없으며, 정적 필드를 사용할 경우 애플리케이션 전반에 걸쳐 공유 상태가 발생할 수 있습니다.
정적 클래스와 메서드 사용에 대한 모범 사례
- 정적 클래스를 무상태(state‑less)로 유지 – 데이터 저장이나 상태 추적을 피하십시오. 무상태 정적 클래스는 입력 매개변수만으로 동작하고 부작용 없이 결과를 반환하므로 효율적이고 안전합니다.
.NET Framework의 예로System.Console와System.Math가 있습니다;Console.WriteLine이나Math.Sqrt와 같은 메서드는 내부 상태 없이 입력을 받아 출력합니다. - 이상적인 시나리오 – 날짜 포맷팅, 이미지 변환, 계산 수행 등 전역 또는 공유 데이터를 유지하지 않고 빠르고 재사용 가능한 로직이 필요한 경우.
요약하면, 정적 클래스를 효과적으로 사용하려면 모든 입력을 메서드 인수로 제공하고 클래스 내에 어떠한 상태도 저장하지 않도록 하십시오.
정적 데이터에 주의하세요
정적 변수는 모든 스레드와 인스턴스가 공유하므로 그 값이 예측하기 어렵습니다—값이 변경되면 단일 공유 메모리 위치가 영향을 받습니다. 정적 메서드가 정적 데이터를 의존하거나 수정한다면, 특히 다중 스레드 환경에서 일관되지 않은 결과가 발생할 수 있습니다.
public static class Calculation
{
private static int totalCount;
public static void GetCount()
{
totalCount = 0;
for (int i = 0; i < 10; i++)
{
totalCount += i;
Thread.Sleep(100);
}
Console.WriteLine("TOTAL COUNT : {0}", totalCount);
}
}
여러 스레드에서 GetCount를 실행하면 모든 스레드가 동일한 totalCount 변수를 공유하기 때문에 예상치 못한 결과가 나타날 수 있습니다. 정적 메서드는 기본적으로 스레드‑안전하지 않으므로 직접 동기화를 처리해야 합니다. 자세한 내용은 K. Scott Allen의 기사 Static and Thread Safety 를 참고하세요.
정적 클래스의 단점
- 강한 결합 – 정적 클래스는 코드가 강하게 결합되고 테스트하기 어려워질 수 있습니다.
- 숨겨진 의존성 – 메서드가 다른 곳에 설정된 정적 데이터에 의존할 수 있어 작업 순서가 중요해지고 예기치 않은 결과가 발생할 수 있습니다.
public static class TaxStructure
{
public static int TaxRate { get; set; }
}
public static class CalculateTax
{
public static void ShowTax()
{
Console.WriteLine(TaxStructure.TaxRate);
}
}
TaxStructure.TaxRate를 CalculateTax.ShowTax()를 호출하기 전에 설정해야 합니다. 설정하지 않거나 순서를 잘못 호출하면 출력이 올바르지 않을 수 있습니다. 이러한 숨겨진 의존성은 코드를 유지보수하고 테스트하기 어렵게 만들 수 있습니다.