[DelphiCon 요약] Spring4D 소개 – 델파이 개발을 한 수준 높이기
- 2021-01-08
- Posted by: Narae Kim
- Category: 기술자료
- 원본 비디오 시청: https://delphicon.embarcadero.com/talks/introduction-to-spring4d-taking-delphi-development-to-the-next-level/
- DelphiCon 전체 보기 (현재 무료, 향후 유료 전환 예상): https://delphicon.embarcadero.com/replays/
- 데브기어의 DelphiCon 소개 페이지로 가기: https://devgear.co.kr/archives/3692
Spring4D 소개 – 델파이 개발을 한수준 높이기 (Introduction to Spring4D – Taking Delphi Development to the Next Level) 를 요약했습니다. (이 요약 번역은 원본 비디오와 내용이 일부 다르거나, Q&A등 일부 생략되었을 수 있습니다.)
이 스프링4D는 델파이 개발을 더 쉽고 더 견고하게 할 수 있도록 미리 구성된 라이브러리입니다. 많은 개발자들에게 필요했던 타입과 확장 기능이 구현되어 있습니다. 예를 들어, 스마트 포인터를 사용하면 메모리 누수 걱정없이 오브젝트를 만들어 쓸 수 있습니다. Spring4D의 컬렉션은 컬렉션이나 리스트 관리가 매우 간편합니다. (이런 라이브러리 또는 프레임워크를 사용하면) 코드는 더 짧아지고, 일관성과 품질은 더 높아집니다.
- Spring4D란?
- Spring4D를 받는 방법
- Spring4D의 기본 구성
- Spring4D 구성 요소: Spring.Base
- Nullable<T>
- Event<T>
- 스마트 포인터 (Shared<T> 와 Weak<T>)
- Collections
- Collections 인터페이스
- 읽기전용 vs 불변
- IEnumberable<T>
- 스트리밍과 지연 실행
- ICollection<T>
- IList<T>
- IMap, IDictionary, IMultiMap
- 더 많은 내용
발표자 (Stefan Glienke)는 델파이 경력 20년이 넘은 개발자이며, Spring4D 오픈소소의 개발 책임자입니다. (웹페이지: https://delphisorcery.blogspot.com )
- 원본 비디오 시청: https://delphicon.embarcadero.com/talks/introduction-to-spring4d-taking-delphi-development-to-the-next-level/
Spring4D 란
- 델파이 오픈소스 라이브러리 (2010년에 출시된 XE와 그 이후 버전에서 사용 가능)
- 상업용 무료 사용 (아파치 2.0 오픈 소스 라이선스)
- 델파이 RTL 확장
- 제네릭스(Generics)와 RTTI를 적극 활용
- 계속 발전하는 중이고 상업용 소프트웨어 개발에 활용되고 있음
- 원칙: “골라 쓰기” – 원하는 것만 골라서 사용할 수 있다. 강제하지 않는다.
- 버전: 2020년 12월 현재 1.2.4 – 곧 2.0 발표 예정
Spring4D를 받는 방법
- Git에서 내려받기 https://bitbucket.org/sglienke/spring4d.git (버전콘트롤을 사용하지 않는다면 전체 파일 다운로드)
- Build.exe 를 실행하여 간편하게 설치/설정 가능 (또는 전체 파일을 직접 컴파일 하여 사용하기)
- 코드를 모두 받아서 컴파일하여 사용할 수 있지만, 미리 컴파일된 .dcu를 사용하는 것이 편함 (단 몇초지만 매번 컴파일하는 시간도 아끼자)
Spring4D의 기본 구성
- Base: RTL 확장, 컬렉션
- Core: 의존성 주입(DI, Dependency Injection) 컨테이너, 인터셉션/목킹(Mocking)
- Data: ObjectDataSet을 이용해 (TDBGrid 등) 데이터를 인식하는 UI 콘트롤에 연결
- Persistence: ORM
- Extensions: 암호화 및 기타 유틸리티 (암호화는 다른 암호화 전문 라이브러리보다 약함)
Spring4D 구성 요소: Spring.Base
- Nullable<T>
- Event<T> 멀티 캐스트 이벤트
- 스마트 포인터 (Shared<T> 와 Weak<T>)
- Collections: 가장 많이 활용되는 라이브러리
- IEnumerable<T>
- 리스트, 딕셔너리, 멀티맵, 세트, 큐
Nullable<T>
- 특정 타입을 지키는 데이터 타입(Type safe date type) 이면서도 Null값을 가질 수 있다.
- Null (값이 없음)을 넣기 위해 아래와 같이 억지로 만든 값을 사용할 필요가 없다.
- 날짜 타입에 “날짜가 주어지지 않음”을 넣기 위해 -40000 이라는 가상의 값 넣기
- Boolean에 “참인지 거짓인지 모름”을 넣기 위해 True/False/FileNotFound로 Inum을 직접 만들기
- Variant 타입과는 다름
- Variant는 호환 가능한 타입 변환을 암시적으로 수행하므로 언제든 다른 타입으로 변환될 여지가 있지만 Nullable<T>는 타입을 지키므로 정해진 타입 이외에는 담을 수 없다.(type safe)
- 예를 들어 Variant에는 숫자 3과 문자열 ‘3’을 모두 넣을 수 있고, 상황에 따라 사용되지만, Nullable<Integer>에는 정수 3만 넣을 수 있고 문자열 3을 넣을 수는 없다.
//// Nullable<T> 예문
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
uses Spring; procedure … var n, n2: Nullable<TDateTime>; // uses Spring (Spring 유닛 사용) 필요 d: TDateTime; begin d := now; Log.Lines.Add(n.HasValue.ToString); Log.Lines.Add(n.ToString); // DataTime을 문자열로 출력할 때는 지역 설정 등 RTL에서 적용된 형식으로 출력 Log.Lines.AddParagraph; n := d; Log.Lines.Add(n.HasValue.ToString); // 로컬 변수로 사용된 Nullable<T>은 할당을 하지 않고 바로 사용 가능 Log.Lines.Add(n.ToString); Log.Lines.AddParagraph; n := nil; //n에 들어있는 값을 없앤다 Log.Lines.Add(n.HasValue.ToString); Log.Lines.Add(n.GetValueOrDefault().ToString); // GetValueOrDefault() 값이 있으면 그 값을, 없으면 기본값을 출력 Log.Lines.AddParagraph; Log.Lines.Add((n=n2).ToString); n := d; Log.Lines.Add((n=n2).ToString); n2 := d; Log.Lines.Add((n=n2).ToString); end; ////결과 (및 해설) False // 기본값이 적용되면, Nullable.HasValue의 결과는 False Null // 기본값이 적용되면, Nullable.ToString의 결과는 ‘Null’(값없음) True // 특정 시간을 넣으면, Nullable.HasValue의 결과는 True 19.11.2020 18:11:51 //독일 기준 날짜 형식 (발표자의 시간대가 독일로 되어 있음) False // nil을 넣으면, Nullable.HasValue의 결과는 False 30.12.1899 // Nullable.GetValueOrDefault().ToString의 결과는 값없는 경우에 출력할 날짜 기본값 True // n과 n2는 둘다 값이 없으므로, n과 n2를 비교하면 ‘같음’이 된다 False // n에만 d를 넣고, n과 n2를 비교하면 ‘다름’이 된다 True // n과 n2는 둘다 d와 같은 값을 가지므로, n과 n2를 비교하면 ‘같음’이 된다. |
Event<T>
- (필요한 타입을 따로 만들 필요없어서 사용이 쉬운) Observer 패턴과 유사하다.
- publish와 Subscribe를 구현하기 간단하다. 델파이에서 일반 이벤트 사용하는 것과 방식이 같다.
- 제네릭 타입을 사용하므로 파라미터와 리턴 타입이 유연하다
- <T>에 (TNotifyEvent 등) 원하는 타입을 지정하면 된다.
- 빠르고 쓰레드에 안전하다
//// Event<T> 멀티 캐스트 이벤트 예문
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
uses Spring; private fOnMouseMove: Event<TMouseMoveEvent>; // 델파이 기본 이벤트에서 마우스 상태값을 받아온다 // Event<TMouseMoveEvent>를 구독(subscribe)하는 함수 procedure … var subscriber: TEventSubscriber; //구독자 변수 begin subscriber := TEventSubscriber.Create(Self); //구독자 생성 fOnMouseMove.Add(subscriber.HandleMouseMove); //구독자가 잡은 마우스 이동 이벤트를 넣는다 (fOnMouseMove는 실제로 이벤트핸들러들의 목록이므로 Add 메소드를 가지도록 되어있다. 그 결과 한번 작동하면 목록에 있는 모든 이벤트핸들러가 작동한다.) subscriber.OnUpdate.Add(ChangeCaption); //구독자의 OnUpdate이벤트 발생시 실행할 이벤트핸들러 지정 (좌표값을 폼의 캡션에 찍도록 함) subscriber.OnUpdate.Add(ChangeColor); // (마우스 Y좌표가 300이상이면 빨강으로 바꾸고 아니면, 일반 윈도우 색을 유지하도록 함) Log.OnMouseMove := fOnMouseMove; //TMomo인 Log의 OnMouseMove 이벤트에 Event<TMouseMoveEvent>를 연결하여 포함된 이벤트핸들러가 모두 실행되도록 한다. fOnMouseMove.OnChange := NotifyEventChange; //Event<T>에 이벤트핸들러가 추가/삭제 되면 공지한다. (예를 들어 이 예문에서 폼을 종료하면, 이 이벤트가 작동된다. 그 이유는 TEventSubscriber.Create(Self)로 생성되었고, Self는 MainForm였다. 따라서 TEventSubscriber의 owner 역시 메인폼이 된다. 메인 폼이 제거되면, 이 구독자 역시 제거되고 등록된 이벤트핸들러 역시 제거된다.) end; |
스마트 포인터 (Shared<T> 와 Weak<T>)
- 오브젝트와 기타 리소스의 생명주기가 관리 능력 추가
- try finally 를 사용하여 명시적으로 오브젝트를 제거하지 않아도 된다. 이점은 여러 리소스 간에 오브젝트를 주고 받는 것 역시 간편하게 해준다.(어느 곳에서 제거해야 하는지를 걱정할 필요가 없다)
- Weak<T>에서는 순환 참조 문제가 없다 (심지어 델파이에 [Weak] 속성이 추가되기 전부터 있었다)
- 보너스: Weak<T>로 만든 오브젝트는 모든 플랫폼에서 작동한다. 또한 오브젝트가 제거될 때 알림을 받을 수 있다
//// 스마트 포인터 (Shared<T> 와 Weak<T>) 예문
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
// Shared<T>: 레코드 타입으로 사용할 때 procedure … var sl: Shared<TStringList>; begin sl := TStringList.Create; // operator overloading sl.Value.Add(‘델파이콘’); // 멤버에 직접 액세스하지 못하고 Value 속성을 사용하여 액세스한다 Log.Lines.AddStrings(sl); //<T>에서 지정한 타입을 그냥 전달하는 것과 같은 방식으로 전달될 수 있다. end; // IShared<T>: 인터페이스 타입으로 사용할 때 procedure … var sl: IShared<TStringList>; // 인터페이스 타입으로 사용할 때 begin sl := Shared.Make<TStringList>(TStringList.Create); // 직접 생성하지 않고 인터페이스에 맞추어야 한다. sl.Add(‘델파이콘’); // (이 인터페이스는 익명메소드처럼 지정된 타입을 반환하기 때문에) 멤버에 직접 액세스할 수 있다. Log.Lines.AddStrings(sl); //<T>에서 지정한 타입을 그냥 전달하는 것과 같은 방식으로 전달될 수 있다. end; // IShared<T>로 생성된 오브젝트를 직접 제거하고 싶으면, 파라미터로 익명메소드를 넣는다. procedure … var sl: IShared<TStrings>; begin sl := Shared.Make<TStrings>(TStringList.Create, procedure(const s: TStrings) begin Log.Lines.AddStrings(sl); //TMemo인 Log에 ‘델파이콘’을 출력하고 s.Free; //생성된 TStrings를 제거 end); sl.Add(‘델파이콘’); end; // 스마트 포인터로 만든 오브젝트는 오브젝트 제거 코드를 쓰지 않아도. 자동 제거되므로 메모리 누수를 염려하지 않아도 된다. // ReportMemoryLeakOnShutdown := True; //델파이 프로젝트에서 메모리 누수를 확인하는 코드 // Weak<T> procedure … var sl: TStringList; //Share<T>가 아닌 일반 TStringList weakRef: Weak<TStrings>; //문자열을 Weak 참조하기로 한다. begin sl := TStringList.Create; weakRef := sl; // operator overloading sl.Add(‘델파이콘’); Log.Lines.Add(weakRef.IsAlive.ToString); Log.Lines.AddStrings(weakRef); // operator overloading Log.Lines.AddParagraph; sl.Free; //Share<T> 가 아니므로 직접 Free 했다. 그러면, Weak 참조하고 있는 곳에 모두 공지된다. // Weak<T>는 모든 플랫폼에서 작동된다. Log.Lines.Add(weakRef.IsAlive.ToString); Log.Lines.Add(Assigned(weakRef.Target).ToString); //Weak<T>.Target은 Shared<T>.Value와 같은 역할 Log.Lines.Add(weakRef <> nil).ToString; end; ////결과 (및 해설) True // 참조 타겟이 살아있다 델파이콘 // 참조 타겟의 값 False // ‘참조 타겟이 제거되었음’을 알고 있음 False // ‘참조 타겟이 Assigned 되지 않았음’을 알고 있음 False // ‘참조 타겟이 nil 임’을 알고 있음 |
이 외에도 다음의 내용들을 다룹니다. 더 자세한 내용은 원본 비디오를 통해 확인해보세요:
- Collections
- Collections 인터페이스
- 읽기전용 vs 불변
- IEnumberable<T>
- 스트리밍과 지연 실행
- ICollection<T>
- IList<T>
- IMap, IDictionary, IMultiMap
- 더 많은 내용
- 원본 비디오 시청: https://delphicon.embarcadero.com/talks/introduction-to-spring4d-taking-delphi-development-to-the-next-level/
- DelphiCon 전체 보기 (현재 무료, 향후 유료 전환 예상): https://delphicon.embarcadero.com/replays/
- 데브기어의 DelphiCon 소개 페이지로 가기: https://devgear.co.kr/archives/3692
12.0 12.1 AI AWS C++ c++빌더 chatgpt DelphiCon ios rad서버 RAD스튜디오 UI UIUX UX uxsummit vcl 개발 개발사례 고객사례 기술레터 기술백서 데브옵스 데이터 데이터베이스 델파이 리눅스 마이그레이션 맥 머신러닝 모바일 새버전 샘플 세미나 안드로이드 웹 윈도우 인공지능 인터베이스 출시 커뮤니티에디션 코드 클라우드 파이썬 파이어몽키 현대화