본문 바로가기

전체 글1251

Delphi에서 제네릭 리스트(TList<T>) 효율적으로 사용하기 (Intermediate) Delphi에서 제네릭 리스트(TList) 효율적으로 사용하기 (Intermediate) 델파이(Delphi)에서 TList는 제네릭을 지원하는 강력한 리스트 컬렉션으로, 타입 안정성과 성능을 모두 제공합니다. 기존의 TList는 Pointer 기반이라 형변환이 필요했지만, TList는 컴파일 타임에 타입이 고정되어 안전합니다. 또한 for..in 구문과 함께 사용하면 더 직관적인 코드 작성이 가능합니다. uses System.Generics.Collections, System.SysUtils; procedure TestGenericList; var Numbers: TList; I: Integer; begin Numbers := TList.Create; try // 값 추가.. 2025. 8. 13.
Dictionary에서 값으로 키 찾기 Dictionary에서 값으로 키 찾기C#의 Dictionary는 키를 통해 값을 찾는 데 최적화되어 있습니다. 하지만 특정 값을 기준으로 키를 찾아야 할 때가 있습니다. 이 경우 LINQ를 사용하면 깔끔하게 해결할 수 있습니다. using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { var fruits = new Dictionary() { {"A", "Apple"}, {"B", "Banana"}, {"C", "Cherry"}, {"D", "Duri.. 2025. 8. 13.
FireDAC에서 매개변수화 쿼리로 SQL 인젝션 방지하기 (Intermediate) FireDAC에서 매개변수화 쿼리로 SQL 인젝션 방지하기 (Intermediate) Delphi에서 데이터베이스 쿼리를 실행할 때, 문자열을 직접 연결하면 SQL 인젝션 공격에 취약해질 수 있습니다. FireDAC의 TFDQuery 컴포넌트를 사용하면 매개변수화(Parameterized) 쿼리를 적용하여 보안성과 성능을 모두 향상시킬 수 있습니다. 매개변수는 :파라미터명 형식으로 선언하며, ParamByName 메서드로 값을 지정합니다. uses FireDAC.Comp.Client; procedure TForm1.btnSearchClick(Sender: TObject); begin FDQuery1.SQL.Text := 'SELECT * FROM Customers WHERE Name = :N.. 2025. 8. 12.
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.
TPath.GetTempFileName + TFile로 안전한 임시 파일 사용하기 TPath.GetTempFileName + TFile로 안전한 임시 파일 사용하기임시 데이터를 다룰 때는 OS가 보장하는 임시 폴더와 충돌 없는 파일명을 쓰는 게 안전합니다. System.IOUtils의 TPath.GetTempPath, TPath.GetTempFileName과 TFile.WriteAllText/ReadAllText/Delete를 조합하면, 경로/이름 충돌 걱정 없이 생성→사용→정리까지 한 번에 처리할 수 있습니다. uses System.SysUtils, System.IOUtils; procedure UseTempFile; var TempDir, TempFile, Data, ReadBack: string; begin TempDir := TPath.GetTempPath;.. 2025. 8. 11.
nameof로 하드코딩 문자열 없이 안전하게 이름 참조하기 nameof로 하드코딩 문자열 없이 안전하게 이름 참조하기 nameof는 변수/매개변수/속성/메서드 이름을 컴파일 타임에 문자열로 얻는 키워드예요. 예외 메시지, 로그, 바인딩 등에서 “매직 스트링”을 없애 오타와 리팩터링 버그를 막아줍니다. using System; class Program { static void Main() { PrintUser(null); } static void PrintUser(string userName) { if (userName is null) throw new ArgumentNullException(nameof(userName), $"{nameof(userName)} is requi.. 2025. 8. 11.
TStringBuilder로 효율적인 문자열 결합하기 TStringBuilder로 효율적인 문자열 결합하기 Delphi에서 반복문이나 대량 문자열 조합 시 + 연산자를 사용하면 메모리 재할당이 빈번해 성능 저하가 발생할 수 있습니다. TStringBuilder는 내부 버퍼를 관리해 한 번만 메모리를 할당하고 문자열을 누적하므로, 대용량 텍스트 생성에 탁월합니다. uses System.SysUtils, System.Classes; procedure BuildLargeString; var SB: TStringBuilder; I: Integer; ResultStr: string; begin SB := TStringBuilder.Create; try for I := 1 to 10000 do SB.AppendFormat.. 2025. 8. 8.
비동기 스트림(Asynchronous Streams)으로 대용량 데이터 처리 최적화 비동기 스트림(Asynchronous Streams)으로 대용량 데이터 처리 최적화C# 8.0부터 제공되는 비동기 스트림(IAsyncEnumerable)은 대용량 데이터나 네트워크 스트리밍 작업에서 메모리를 효율적으로 사용하고, 데이터가 준비되는 대로 처리할 수 있도록 도와줍니다. await foreach 문을 사용하면 비동기적으로 데이터를 하나씩 받아 처리할 수 있어, 전체 데이터를 모두 메모리에 로드할 필요가 없습니다. using System; using System.Collections.Generic; using Systehttp://m.Threading.Tasks;class Program { static async Task Main() { await foreach.. 2025. 8. 8.
TRegEx로 유효한 이메일 주소 검사하기 TRegEx로 유효한 이메일 주소 검사하기델파이의 System.RegularExpressions 유닛에 포함된 TRegEx를 사용하면 복잡한 패턴 매칭을 간편하게 구현할 수 있습니다. 이메일 형식 검증처럼 정규식이 필요한 작업을 손쉽게 처리할 수 있어 실무에서 자주 활용됩니다. uses System.SysUtils, System.RegularExpressions; function IsValidEmail(const Email: string): Boolean; const EmailPattern = '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'; begin // IgnoreCase 옵션으로 대소문자 구분 없이 검사 Result := TReg.. 2025. 8. 7.
Enumerable.Range()와 Select()를 활용해 숫자 리스트와 계산 결과 만들기 Enumerable.Range()와 Select()를 활용해 숫자 리스트와 계산 결과 만들기 Enumerable.Range(start, count) 메서드를 사용하면 정수 시퀀스를 쉽고 깔끔하게 생성할 수 있습니다. 여기에 Select()를 결합하면 간단한 수열 연산도 한 줄로 처리할 수 있어 매우 유용합니다. using System; using System.Linq; class Program { static void Main() { var squares = Enumerable.Range(1, 5) .Select(n => n * n); Console.WriteLine("1부터 5까지의 제곱수:"); .. 2025. 8. 7.
익명 메서드로 코드 가독성 향상하기 익명 메서드로 코드 가독성 향상하기 익명 메서드는 로컬 변수처럼 선언되어 특정 코드 블록 내에서만 사용 가능한 메서드입니다. 주로 콜백 함수, 정렬, 스레딩, 이벤트 핸들링 등에서 유용하며 코드 가독성을 높이고 메서드 분리를 최소화할 수 있습니다. procedure TForm1.Button1Click(Sender: TObject); var Multiply: reference to function(A, B: Integer): Integer; Result: Integer; begin Multiply := function(A, B: Integer): Integer begin Result := A * B; end; Result := Multiply(6, 7); S.. 2025. 8. 6.
using var 선언으로 자원을 자동 해제하는 간결한 패턴 using var 선언으로 자원을 자동 해제하는 간결한 패턴 C# 8.0 이상에서는 using 블록 대신 using var 선언만으로도 IDisposable 객체의 리소스를 자동 해제할 수 있습니다. 코드가 더 깔끔해지고 들여쓰기 깊이도 줄여 유지보수성을 높일 수 있는 실무 팁입니다. using System; using System.IO; using Systehttp://m.Threading.Tasks;class Program { static async Task Main() { using var client = new Systehttp://m.Net.Http.HttpClient(); Console.WriteLine("웹 요청 중..."); str.. 2025. 8. 6.
TStreamReader로 인코딩된 텍스트 파일 읽기 (Beginner) TStreamReader로 인코딩된 텍스트 파일 읽기 (Beginner) 델파이에서 다양한 인코딩(UTF-8, ANSI 등)의 텍스트 파일을 읽을 때는 TStreamReader를 사용하면 간편합니다. TStreamReader 생성자에 인코딩을 지정해주면, 올바른 문자 변환이 자동으로 이뤄져 파일 내용이 깨지지 않습니다.​uses System.Classes, System.SysUtils;​procedure ReadTextFile(const FileName: string);var Reader: TStreamReader; Line: string;begin // UTF-8 인코딩으로 읽기 Reader := TStreamReader.Create(FileName, TEncoding.UTF8); try while n.. 2025. 8. 5.
??= Null 병합 할당 연산자 활용하기 ??= Null 병합 할당 연산자 활용하기 C# 8.0에서 도입된 ??= 연산자는 왼쪽 피연산자가 null일 경우에만 오른쪽 값을 할당합니다. 이 연산자는 객체 초기화나 기본값 설정에 자주 사용됩니다. List? names = null; // ??=를 사용하여 null일 경우에만 새 리스트를 할당 names ??= new List(); names.Add("김원호"); Console.WriteLine(string.Join(", ", names)); 코드 간결화: if 문 없이도 기본값 설정 가능 가독성 향상: null 체크와 할당을 한 줄에 처리 NRE(NullReferenceException) 방지에 유용 서비스 클래스에서 DI 주입되지 않은 인스턴스에 기본 구현 제공 시 ViewModel에서 nul.. 2025. 8. 5.
TStringHelper를 이용한 문자열 분할과 트리밍 TStringHelper를 이용한 문자열 분할과 트리밍 델파이의 TStringHelper는 string 타입에 유용한 메서드를 확장해주는 기능입니다. 특히 Split, Trim, ToUpper 등은 문자열 처리에서 자주 사용되며 가독성도 크게 향상됩니다. uses System.SysUtils, System.Classes; procedure ParseUserInput(const Input: string); var Parts: TArray; Name, Email: string; begin Parts := Input.Split([',']); // 콤마 기준으로 분할 if Length(Parts) >= 2 then begin Name := Parts[0].Trim; Emai.. 2025. 8. 4.
string.Join()으로 문자열 배열 간단하게 결합하기 string.Join()으로 문자열 배열 간단하게 결합하기문자열 배열이나 리스트를 하나의 문자열로 합치려면 string.Join() 메서드가 가장 간편하고 안전한 방법입니다. 반복문 없이도 한 줄로 처리할 수 있어 코드가 깔끔해집니다. using System; class Program { static void Main() { string[] fruits = { "사과", "바나나", "포도" }; string result = string.Join(", ", fruits); Console.WriteLine("과일 목록: " + result); } } 출력 결과 과일 목록: 사과, 바나나, 포도 string.Join(separator, ar.. 2025. 8. 4.
레코드를 객체처럼 다루기: 메서드 포함 레코드 레코드를 객체처럼 다루기: 메서드 포함 레코드 델파이의 record는 단순한 데이터 저장용으로 쓰이지만, 메서드나 생성자도 정의할 수 있어 객체처럼 활용할 수 있습니다. 이 기법은 간단한 구조 데이터에 기능을 부여하고자 할 때 유용합니다. type TEmployee = record Name: string; Salary: Currency; procedure RaiseSalary(Amount: Currency); function GetInfo: string; end; procedure TEmployee.RaiseSalary(Amount: Currency); begin Salary := Salary + Amount; end; function TEmployee.GetI.. 2025. 8. 1.
record 타입으로 불변 객체 선언하기 record 타입으로 불변 객체 선언하기 record는 C# 9.0 이상에서 도입된 참조형 타입으로, 기본적으로 불변성을 유지하면서 값 기반 비교를 지원합니다. 객체를 불변으로 유지하면서도 편리하게 사용할 수 있어, DTO, 설정 객체 등에 적합합니다. public record User(string Name, int Age); class Program { static void Main() { var user1 = new User("Kim", 30); var user2 = user1 with { Age = 31 }; Console.WriteLine(user1); // User { Name = Kim, Age = 30 } Conso.. 2025. 8. 1.
TTask를 이용한 백그라운드 작업 처리 TTask를 이용한 백그라운드 작업 처리 Systehttp://m.Threading.TTask를 활용하면 UI를 멈추지 않고 백그라운드에서 작업을 처리할 수 있습니다. 예를 들어, 긴 로직이나 서버 통신을 처리할 때 UI 응답성을 유지하면서 동시에 병렬 처리를 구현할 수 있습니다. uses System.Threading, System.SysUtils, Vcl.Dialogs; procedure DoBackgroundWork; begin TTask.Run( procedure begin Sleep(3000); // 3초 동안 작업 수행 TThread.Synchronize(nil, procedure begin Show.. 2025. 7. 31.
Dictionary<TKey, TValue>.TryGetValue()로 안전하게 값 조회하기 Dictionary.TryGetValue()로 안전하게 값 조회하기 컬렉션에서 키와 값을 함께 다룰 때 ContainsKey()와 인덱서를 사용하는 대신, TryGetValue()를 사용하면 한 번의 호출로 키 존재 여부와 값을 동시에 체크할 수 있어 더 효율적이고 성능도 우수합니다. using System; using System.Collections.Generic; class Program { static void Main() { var scores = new Dictionary { ["Alice"] = 90, ["Bob"] = 85 }; if (scores.TryGetValue("B.. 2025. 7. 31.