전체 글1308 클래스(Class) 기반 객체 설계 기초 클래스(Class) 기반 객체 설계 기초 클래스(Class)는 객체지향 프로그래밍(OOP)의 기본 단위로, 데이터(필드)와 동작(메서드)을 하나의 구조로 묶어 유지보수성을 높입니다. 현실 객체를 클래스로 표현하면 비즈니스 로직 분리와 확장이 쉬워집니다. Delphi는 자동 메모리 해제 기능이 없으므로, try..finally로 객체를 직접 관리해야 합니다. program ClassDemo; {$APPTYPE CONSOLE} uses System.SysUtils; type TEmployee = class private FEmpNo: Integer; FName: string; FSalary: Currency; public constructor Create(AEmp.. 2025. 10. 17. nullable reference type으로 null 안정성 높이기 nullable reference type으로 null 안정성 높이기C# 8.0부터 추가된 nullable reference type(NRT) 기능은 개발자가 null로 인한 **NullReferenceException(널 참조 예외)**을 예방하도록 돕는 강력한 컴파일러 기능입니다. 즉, string? → null을 허용하는 참조형 string → null을 허용하지 않는 참조형 컴파일러는 코드 상에서 null이 될 수 있는 가능성을 미리 경고해주며, 이를 통해 런타임 예외 대신 컴파일 타임에서 문제를 해결할 수 있습니다. #nullable enable // nullable reference type 기능 활성화 using System; class Program { static void Mai.. 2025. 10. 17. 포인터 안전하게 다루기 (Pointer & Memory Handling) 포인터 안전하게 다루기 (Pointer & Memory Handling)포인터(Pointer)는 메모리 주소를 직접 다루는 강력한 기능이지만, 잘못 쓰면 프로그램이 즉시 크래시합니다. @, ^ 연산자를 통해 메모리 접근이 가능하며, GetMem/FreeMem으로 수동 관리할 수 있습니다. 포인터보다 레코드, 배열, 객체를 우선 사용하되, 파일 입출력, 네트워크 송수신, DLL 연동 시 포인터가 꼭 필요합니다. program PointerDemo; {$APPTYPE CONSOLE} uses System.SysUtils; type PInt = ^Integer; var Ptr: PInt; begin New(Ptr); // 메모리 할당 try Ptr^ := 12.. 2025. 10. 16. ValueTask로 메모리 효율적인 비동기 처리하기 ValueTask로 메모리 효율적인 비동기 처리하기 Task는 비동기 작업 결과를 나타내는 객체로 매우 널리 쓰이지만, 짧은 실행 경로에서는 불필요한 힙 할당이 발생할 수 있습니다. **ValueTask**는 구조체(struct) 기반의 경량 비동기 반환 타입으로, 결과가 이미 계산된 경우 불필요한 Task 객체 생성을 방지합니다. 메모리 효율이 높고 GC 부담을 줄일 수 있습니다. 단, ValueTask는 Task보다 제약이 많아 잘못 사용하면 오히려 성능이 저하될 수 있습니다. 따라서 "짧은 실행 경로" 또는 "동기적으로 결과를 즉시 반환할 가능성이 높은 비동기 메서드"에서만 사용하는 것이 좋습니다. using System; using Systehttp://m.Threading.Tasks;cla.. 2025. 10. 16. 레코드(Record)로 데이터 구조 최적화하기 레코드(Record)로 데이터 구조 최적화하기 record는 클래스보다 가벼운 구조체형 데이터 컨테이너로, 스택(Stack)에 저장되어 빠르고 메모리 효율적입니다. 단순 데이터 그룹을 표현할 때 적합. packed record를 사용하면 메모리 정렬 패딩을 제거해 파일 입출력 시 크기를 최소화할 수 있습니다. program RecordDemo; {$APPTYPE CONSOLE} uses System.SysUtils; type TEmployee = record EmpNo: Integer; Name: string[30]; Salary: Currency; JoinDate: TDateTime; function GetInfo: string; end; TPack.. 2025. 10. 15. ValueTask로 메모리 효율적인 비동기 처리하기 ValueTask로 메모리 효율적인 비동기 처리하기 Task는 비동기 작업 결과를 나타내는 객체로 매우 널리 쓰이지만, 짧은 실행 경로에서는 불필요한 힙 할당이 발생할 수 있습니다. **ValueTask**는 구조체(struct) 기반의 경량 비동기 반환 타입으로, 결과가 이미 계산된 경우 불필요한 Task 객체 생성을 방지합니다. 메모리 효율이 높고 GC 부담을 줄일 수 있습니다. 단, ValueTask는 Task보다 제약이 많아 잘못 사용하면 오히려 성능이 저하될 수 있습니다. 따라서 "짧은 실행 경로" 또는 "동기적으로 결과를 즉시 반환할 가능성이 높은 비동기 메서드"에서만 사용하는 것이 좋습니다. using System; using Systehttp://m.Threading.Tasks;cla.. 2025. 10. 15. 병렬 처리: TParallel.For 활용하기 병렬 처리: TParallel.For 활용하기TParallel.For는 델파이의 멀티스레딩 라이브러리(Parallel Programming Library, PPL)에 포함된 병렬 반복문 기능입니다. 반복문을 여러 CPU 코어에 나누어 실행해 성능을 향상시킵니다. 데이터 집합을 병렬로 처리할 때 사용 CPU 연산이 많은 반복문 최적화할 때 사용 대규모 데이터 분석, 이미지 처리, 수학 계산 등에 활용 사용 program ParallelForDemo; {$APPTYPE CONSOLE} uses System.SysUtils, System.Threading, System.Diagnostics; procedure RunDemo; var SW: TStopwatch; I: Integer; Re.. 2025. 10. 13. 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. 동적 배열로 유연한 데이터 처리하기 동적 배열로 유연한 데이터 처리하기 고정 배열은 크기가 컴파일 시점에 결정되지만, **동적 배열(Dynamic Array)**은 런타임에서 크기를 조정할 수 있음. ERP/SI 시스템에서 사용자 입력, 조회 결과 등 크기를 알 수 없는 데이터를 저장할 때 필수적. SetLength로 크기를 변경 가능, 반복문(for-in)으로 가독성 있게 순회 가능. // ✅ Delphi 11+ : 동적 배열 program DynamicArrayDemo; {$APPTYPE CONSOLE} uses System.SysUtils; var Arr: TArray; I: Integer; begin SetLength(Arr, 5); // 배열 크기 지정 for I := 0 to High(Arr) do .. 2025. 10. 2. 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. 메모리 스트림(TMemoryStream) 활용하기 메모리 스트림(TMemoryStream) 활용하기 TMemoryStream은 메모리에 데이터를 임시 저장하는 스트림 클래스입니다. 왜 유용한가: 파일 I/O보다 빠르고, 데이터 직렬화/역직렬화, 네트워크 전송 등 중간 버퍼 용도로 많이 사용됩니다. DB BLOB 데이터 처리 사용 이미지/파일 압축 전 메모리 버퍼 사용 암호화 전후 변환 단계 사용 program MemoryStreamDemo; {$APPTYPE CONSOLE} uses System.SysUtils, System.Classes; procedure RunDemo; var ms: TMemoryStream; s: string; buffer: TBytes; begin ms := TMemoryStream.Create; try .. 2025. 10. 1. 전역 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. 안전한 if..else와 case 구문: Nullable 대응 패턴 안전한 if..else와 case 구문: Nullable 대응 패턴 if..else와 case는 분기 제어의 핵심 문법. Delphi 11+에서는 Nullable로 DB NULL 값도 안전하게 처리. 레거시(Delphi 7/XE)는 VarIsNull/Assigned 활용. ERP/SI 환경에서 DB 값이 비어 있을 때 예외 방지 및 안정적 분기 처리. // ✅ Delphi 11+ : Nullable와 case 결합 program NullableDemo; {$APPTYPE CONSOLE} uses System.SysUtils, System.Generics.Defaults; var Discount: Nullable; begin Discount := Null; // DB에서 값 없음 if no.. 2025. 9. 30. 효율적인 예외 처리와 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. 리소스 문자열(ResourceString)로 다국어 지원 구현하기 리소스 문자열(ResourceString)로 다국어 지원 구현하기 다국어 지원(i18n)을 고려할 때 ResourceString을 사용하면 코드 수정 없이 번역 리소스만 교체하여 손쉽게 언어를 변경할 수 있습니다. resourcestring SWelcome = '환영합니다!'; SExitMsg = '프로그램을 종료하시겠습니까?'; procedure TForm1.FormCreate(Sender: TObject); begin Caption := SWelcome; end; procedure TForm1.Button1Click(Sender: TObject); begin if MessageDlg(SExitMsg, mtConfirmation, [mbYes, mbNo], 0) = mrYes then .. 2025. 9. 26. ValueTask로 비동기 성능 최적화하기 ValueTask로 비동기 성능 최적화하기C#에서 비동기 메서드는 기본적으로 Task를 반환합니다. 하지만 매우 짧게 끝나는 연산이나 반복 호출되는 API에서는 Task 객체 생성 자체가 오버헤드가 될 수 있습니다. 이때 **ValueTask**를 사용하면 불필요한 Task 객체 생성을 줄여 메모리 효율과 성능을 개선할 수 있습니다. using System; using Systehttp://m.Threading.Tasks;class Program { static async ValueTask GetNumberAsync(bool fastPath) { if (fastPath) { // 바로 값을 반환 (Task 객체 생성 X) .. 2025. 9. 26. TCriticalSection으로 멀티스레드 동기화하기 (Advanced) TCriticalSection으로 멀티스레드 동기화하기 (Advanced) 델파이(Delphi)에서 멀티스레드를 활용하면 성능을 높일 수 있지만, 동시에 여러 스레드가 같은 리소스를 접근하면 데이터 충돌이나 불안정한 동작이 발생할 수 있습니다. 이를 방지하기 위해 TCriticalSection을 사용하면 특정 코드 블록을 한 번에 하나의 스레드만 실행하도록 보호할 수 있습니다. uses System.SysUtils, System.Classes; var Counter: Integer; procedure Worker; var I: Integer; begin for I := 1 to 1000000 do Inc(Counter); // 여러 스레드가 동시에 접근 → 잘못된 값 발생 가.. 2025. 9. 25. 박싱(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. Generics.Collections로 타입 안전한 리스트 사용하기 (Beginner) Generics.Collections로 타입 안전한 리스트 사용하기 (Beginner) 델파이(Delphi)에서는 TList 같은 일반 리스트가 있지만, 모든 데이터를 Pointer로 다루어 타입 변환 과정에서 실수할 위험이 있습니다. Generics.Collections의 TList를 사용하면 타입 안전성과 가독성을 높일 수 있습니다. uses System.Generics.Collections, System.SysUtils; procedure Demo; var Numbers: TList; I: Integer; begin Numbers := TList.Create; try Numbers.Add(10); Numbers.Add(20); Numbers.Add(30);.. 2025. 9. 24. 이벤트(Event)와 델리게이트(Delegate) 기본 활용 이벤트(Event)와 델리게이트(Delegate) 기본 활용C#에서 **델리게이트(delegate)**는 메서드를 참조하는 타입이며, **이벤트(event)**는 델리게이트를 기반으로 특정 동작이 발생했을 때 알림을 전달하는 메커니즘입니다. UI 버튼 클릭, 데이터 변경 알림 등 다양한 곳에서 활용됩니다. using System; class Alarm { // 델리게이트 선언 public delegate void AlarmHandler(string message); // 이벤트 선언 public event AlarmHandler? OnAlarm; public void TriggerAlarm() { OnAlarm?.Invoke("알람이 울립니다!.. 2025. 9. 24. 이전 1 2 3 4 ··· 66 다음