csharp42 ValueTask로 메모리 효율적인 비동기 처리하기 ValueTask로 메모리 효율적인 비동기 처리하기 Task는 비동기 작업 결과를 나타내는 객체로 매우 널리 쓰이지만, 짧은 실행 경로에서는 불필요한 힙 할당이 발생할 수 있습니다. **ValueTask**는 구조체(struct) 기반의 경량 비동기 반환 타입으로, 결과가 이미 계산된 경우 불필요한 Task 객체 생성을 방지합니다. 메모리 효율이 높고 GC 부담을 줄일 수 있습니다. 단, ValueTask는 Task보다 제약이 많아 잘못 사용하면 오히려 성능이 저하될 수 있습니다. 따라서 "짧은 실행 경로" 또는 "동기적으로 결과를 즉시 반환할 가능성이 높은 비동기 메서드"에서만 사용하는 것이 좋습니다. using System; using Systehttp://m.Threading.Tasks;cla.. 2025. 10. 16. ValueTask로 메모리 효율적인 비동기 처리하기 ValueTask로 메모리 효율적인 비동기 처리하기 Task는 비동기 작업 결과를 나타내는 객체로 매우 널리 쓰이지만, 짧은 실행 경로에서는 불필요한 힙 할당이 발생할 수 있습니다. **ValueTask**는 구조체(struct) 기반의 경량 비동기 반환 타입으로, 결과가 이미 계산된 경우 불필요한 Task 객체 생성을 방지합니다. 메모리 효율이 높고 GC 부담을 줄일 수 있습니다. 단, ValueTask는 Task보다 제약이 많아 잘못 사용하면 오히려 성능이 저하될 수 있습니다. 따라서 "짧은 실행 경로" 또는 "동기적으로 결과를 즉시 반환할 가능성이 높은 비동기 메서드"에서만 사용하는 것이 좋습니다. using System; using Systehttp://m.Threading.Tasks;cla.. 2025. 10. 15. HttpClientFactory로 안정적이고 효율적인 API 통신 관리하기 HttpClientFactory로 안정적이고 효율적인 API 통신 관리하기 HttpClient는 재사용 가능한 객체지만, 잘못 사용할 경우 소켓 고갈(Socket Exhaustion) 문제가 발생할 수 있습니다. new HttpClient()를 매번 생성하면 내부 TCP 연결이 완전히 해제되지 않아 성능 저하와 리소스 누수가 일어납니다. .NET Core 2.1부터 도입된 **IHttpClientFactory**는 이러한 문제를 해결하기 위해 HttpClient의 수명 관리 자동화, Named/Typed Client 지원, Retry / Timeout / Logging 설정 중앙화 기능을 제공합니다. 결과적으로, HttpClientFactory를 사용하면 성능 향상, 유지보수 편의성, 보안 강화를 .. 2025. 10. 13. HashSet<T>와 Dictionary<TKey,TValue>로 빠른 조회 성능 확보하기 HashSet와 Dictionary로 빠른 조회 성능 확보하기 List는 선형 검색 → 평균 O(n) 성능. 데이터가 많아지면 성능 저하 심각. Dictionary와 HashSet는 해시 기반 → 평균 조회/삽입/삭제가 O(1) 수준. HashSet: 값의 존재 여부를 빠르게 판단할 때 적합. Dictionary: 키-값 매핑에 최적화. 주의: 해시 충돌과 메모리 사용량 증가 가능 → 고유성 검사/대량 데이터 처리에 이점이 크다. using System; using System.Collections.Generic; using System.Diagnostics; class Program { static void Main() { const int N = 1_000_000; .. 2025. 10. 2. 전역 using 지시문으로 프로젝트 코드 간결화 전역 using 지시문으로 프로젝트 코드 간결화기존 C# 프로젝트에서는 모든 파일에 공통 using을 반복적으로 선언해야 했음. 전역 using 지시문(global using)을 사용하면 프로젝트 전체에 한 번만 선언 가능. 불필요한 중복 제거 → 코드 가독성 및 유지보수성 향상. 주의: 너무 많은 전역 using은 네임스페이스 충돌 가능성을 높임. // Before: 모든 파일에 중복 선언 using System; using System.Collections.Generic; using System.Linq; class Demo { static void Main() { List nums = new() { 1, 2, 3 }; Console.WriteLine(num.. 2025. 10. 1. 효율적인 예외 처리와 ThrowHelper 패턴 효율적인 예외 처리와 ThrowHelper 패턴예외(Exception)는 흐름 제어용이 아님 → 정상 로직에서 자주 발생하면 성능 저하. try/catch 블록 안에서 코드를 실행하는 것 자체는 비용이 적지만, 실제 예외 발생 시 스택 추적 생성 때문에 비용이 큼. .NET 런타임/라이브러리는 ThrowHelper라는 패턴을 사용해 공용 메서드에서 예외 객체 생성·throw를 분리하여 JIT 최적화와 코드 크기 감소를 유도. 비동기 메서드(async/await)의 예외는 자동으로 Task.Exception에 담김 → 반드시 await해야 예외 전파됨. using System; class ThrowHelper { public static void ThrowIfNull(object? obj, s.. 2025. 9. 30. 박싱(Boxing)과 언박싱(Unboxing) 이해하기 박싱(Boxing)과 언박싱(Unboxing) 이해하기 C#에서 값 형식(int, double, struct)은 스택에 저장되고, 참조 형식(class, object)은 힙에 저장됩니다. 값 형식을 object나 인터페이스 타입으로 변환할 때 **박싱(Boxing)**이 발생하며, 힙에 새로 객체가 생성됩니다. 반대로 object에서 다시 값 형식으로 꺼낼 때는 **언박싱(Unboxing)**이 일어나는데, 잘못된 형변환은 런타임 오류를 발생시킵니다. 이 과정은 성능에 영향을 줄 수 있으므로 주의가 필요합니다. using System; class Program { static void Main() { int num = 123; // 박싱: 값 형식을 .. 2025. 9. 25. nullable<T>로 안전하게 값 형식 다루기 nullable로 안전하게 값 형식 다루기C#의 값 형식(int, bool, DateTime 등)은 기본적으로 null을 가질 수 없습니다. 하지만 nullable 또는 축약형 T?를 사용하면 값 형식에도 null을 허용할 수 있습니다. 이 기능은 데이터베이스 값 매핑이나 옵션 값 처리에서 매우 유용합니다. using System; class Program { static void Main() { int? age = null; // nullable int if (age.HasValue) { Console.WriteLine($"Age: {age.Value}"); } else { .. 2025. 9. 18. 문자열 보간($"")으로 가독성 향상 문자열 보간($"")으로 가독성 향상C# 6.0부터 제공되는 문자열 보간(string interpolation) 기능은 $"..." 문법을 사용하여 변수나 표현식을 문자열 안에 직접 삽입할 수 있게 해줍니다. string.Format보다 간단하고 가독성이 높으며, 유지보수에도 유리합니다. using System; class Program { static void Main() { string name = "Kim"; int age = 30; // 기존 방식 string oldWay = string.Format("Name: {0}, Age: {1}", name, age); Console.WriteLine(oldWay).. 2025. 9. 16. LINQ SelectMany로 컬렉션 플래튼닝 LINQ SelectMany로 컬렉션 플래튼닝SelectMany는 컬렉션의 컬렉션을 단일 시퀀스로 변환하는 LINQ 메서드로, 중첩된 배열이나 리스트를 평탄화(flatten)하는 데 사용됩니다. 목적은 계층적 데이터 구조를 간단히 처리하여 쿼리를 효율적으로 만드는 것입니다. 복잡한 조인을 피하고 가독성을 높입니다. using System; using System.Collections.Generic; using System.Linq; public class LINQExample { public void FlattenNestedLists() { var nestedList = new List> { new List { "A1", "A2" },.. 2025. 9. 15. 델리게이트와 이벤트를 활용한 느슨한 결합 구현 델리게이트와 이벤트를 활용한 느슨한 결합 구현델리게이트는 메서드 시그니처를 나타내는 타입으로, 함수를 변수처럼 다루며 이벤트는 델리게이트를 기반으로 한 발행-구독 패턴입니다. 목적은 클래스 간 결합도를 낮추고, 확장성을 높이는 것입니다. 이벤트 핸들러를 등록하여 변경 사항을 알릴 때 유용합니다. using System; public class Publisher { // 델리게이트 정의 public delegate void NotificationHandler(string message); // 이벤트 선언 public event NotificationHandler OnNotification; public void Notify(string message) { .. 2025. 9. 11. default 리터럴로 간결한 초기화 default 리터럴로 간결한 초기화C# 7.1부터 default 리터럴을 사용하면 값 타입이나 제네릭 타입을 간단히 초기화할 수 있습니다. 이전에는 default(T)처럼 타입을 명시해야 했지만, 이제는 default만 써도 컴파일러가 타입을 추론하여 기본값(숫자는 0, bool은 false, 참조형은 null 등)을 지정합니다. using System; class Program { static void PrintDefault() { // 제네릭 타입에 대해 간결하게 기본값 할당 T value = default; Console.WriteLine($"Type: {typeof(T)}, Default: {value}"); } st.. 2025. 9. 9. stackalloc으로 고성능 메모리 할당 stackalloc으로 고성능 메모리 할당stackalloc 키워드는 힙 대신 스택 메모리에 고정 크기 배열을 직접 할당할 수 있게 해줍니다. 가비지 컬렉션 부담이 줄어들고, 빠른 메모리 접근이 가능하여 임시 버퍼, 문자열 처리, 고빈도 연산에서 성능을 크게 향상시킬 수 있습니다. using System; class Program { static void Main() { // 스택에 100개의 int 배열을 직접 할당 Span buffer = stackalloc int[100]; for (int i = 0; i { buffer[i] = i * 2; } Console.WriteLi.. 2025. 9. 5. Memory<T>와 Span<T>로 안전한 메모리 관리 Memory와 Span로 안전한 메모리 관리 Span와 Memory는 배열, 문자열, 네이티브 메모리 등 연속된 메모리를 안전하고 효율적으로 다룰 수 있도록 지원합니다. Span는 스택 기반에서 빠르게 동작하며, Memory는 힙에서도 사용할 수 있고 비동기 코드에서도 안전하게 전달할 수 있습니다. using System; class Program { static void Main() { int[] numbers = { 10, 20, 30, 40, 50 }; // 배열 일부를 Span으로 슬라이스 Span slice = numbers.AsSpan(1, 3); foreach (var n in slice) { .. 2025. 9. 3. ref readonly 반환으로 불필요한 복사 방지 ref readonly 반환으로 불필요한 복사 방지C# 7.2부터 ref readonly 반환을 사용하면 메서드가 값을 복사하지 않고 원본 데이터에 대한 읽기 전용 참조를 반환할 수 있습니다. 이 기능은 특히 구조체처럼 크기가 큰 값 타입을 다룰 때 성능 최적화에 효과적입니다. using System; struct BigStruct { public int A, B, C, D, E, F, G, H; } class DataContainer { private BigStruct[] data = new BigStruct[100]; public ref readonly BigStruct GetItem(int index) { return ref data[index]; //.. 2025. 9. 2. readonly struct로 불변 값 타입 최적화 readonly struct로 불변 값 타입 최적화 C# 7.2부터 도입된 readonly struct는 구조체가 불변임을 보장하여, 값 복사 비용을 최소화하고 불변성을 유지할 수 있습니다. 특히 성능에 민감한 코드에서 안전하고 빠른 불변 값 타입을 정의할 때 유용합니다. using System; readonly struct Point { public int X { get; } public int Y { get; } public Point(int x, int y) { X = x; Y = y; } // 읽기 전용 메서드 - 값 타입 불변성 유지 public double Distance => Math.Sqrt(X * X + .. 2025. 9. 1. async와 await로 비동기 프로그래밍 처리하기 async와 await로 비동기 프로그래밍 처리하기 C#의 async와 await 키워드는 비동기 프로그래밍을 단순화해줍니다. 복잡한 콜백 구조 없이도 직관적으로 비동기 작업을 작성할 수 있으며, 긴 실행 시간이 필요한 I/O 작업(파일 처리, DB 조회, API 호출 등)에서 UI 멈춤 현상을 방지하는 데 매우 효과적입니다. using System; using Systehttp://m.Net.Http;using Systehttp://m.Threading.Tasks;class Program { static async Task Main() { Console.WriteLine("데이터 요청 시작..."); string result = await GetDataA.. 2025. 8. 27. nameof 연산자로 안전한 코드 작성 nameof 연산자로 안전한 코드 작성 nameof 연산자는 변수, 메서드, 클래스 등의 식별자 이름을 문자열로 가져오는 기능입니다. 하드코딩된 문자열 대신 nameof를 사용하면 리팩터링 시에도 안전하고, 코드의 유지보수성을 크게 높여줍니다. using System; class Person { public string Name { get; set; } } class Program { static void Main() { var person = new Person { Name = "Alice" }; // nameof 사용 전 Console.WriteLine("속성명: Name"); // nameof 사용 후 (안전한 방.. 2025. 8. 26. Span<T>를 이용한 고성능 문자열 처리 Span를 이용한 고성능 문자열 처리 Span는 관리 힙을 할당하지 않고 연속된 메모리 영역을 안전하게 다룰 수 있게 해주는 구조체입니다. 문자열을 잘라 쓰거나 배열 일부만 처리할 때 복사 없이 접근할 수 있어 성능과 메모리 효율이 뛰어납니다. using System; class Program { static void Main() { string text = "Hello, World!"; // 문자열 일부를 잘라내기 (복사 없음) ReadOnlySpan span = text.AsSpan(7, 5); Console.WriteLine(span.ToString()); // World //.. 2025. 8. 12. switch 표현식으로 깔끔한 조건 분기 처리 switch 표현식으로 깔끔한 조건 분기 처리 C# 8.0부터 도입된 switch 표현식은 기존 switch 문보다 더 간결하고 안전한 방식으로 조건 분기를 처리할 수 있게 해줍니다. 특히 enum, 튜플, 패턴 매칭 등과 함께 사용하면 코드의 가독성과 유지보수성이 크게 향상됩니다. enum UserRole { Admin, Manager, Guest } class Program { static void Main() { var role = UserRole.Manager; string access = role switch { UserRole.Admin => "모든 권한 허용", UserRole.Man.. 2025. 7. 25. 이전 1 2 3 다음