멤버십(수원 삼성소프트웨어멤버십)에서 도서를 관리를 담당하는 일을 맡게 되었는데 기존의 도서 관리가 잘 이루어 지고 있지 않은거 같아 도서 관리 프로그램을 만들어 보았습니다.
WPF 와 C#을 사용해서 개발 했으며 DB는 SQL2003을 사용했습니다. 예전에 한번 올렸었던 도서 관리 프로그램과 기능적인 면에서는 비슷하며 추가된 기능으로는 도서 검색시 온라인서점에서 판매되고 있는 도서까지 함께 보여줘서 도서 신청까지 가능하다는 점이 있습니다.
DB에는 도서에 대한 도서 코드와, ISBN, 대출사용자, 대출날짜, 등록날짜 가 저장되며, 도서 검색시 Naver OpenAPI를 사용하여 관련된 책목록을 가져온뒤 DB에 저장된 도서가 있을 경우 대출가능한 도서로 판단하는 방식입니다.
WPF를 사용하면서 가장 아쉬웠던 점 중에 하나인 Text의 장평을 조절하는 부분을 직접 구현하여 보다 세련되게 Text를 표현하도록 구현 했습니다. 내부 서버에 연결하는 코드가 포함되어 있어 아직 소스코드는 올리지 않았습니다. 따로 요청하시거나 코드가 정리되는데로 업로드 하도록 하겠습니다.
오늘은 C# Destructor에 대에서 알아보도록 하겠습니다. 대부분 알고 있는 계념이라 생각하지만서도, 쉽게 혼동 할 수 있는 부분이 있으므로 정리 해보았습니다. 이미 알고 계신분들은 다시한번 복습의 시간을, 잘 모르셨던 분들은 새로운 내용을 습득하시는 계기가 되었으면합니다.
일반적으로 Desturctor는 소멸자라는 뜻을 가지고 있으며, 생성자와는 반대의 개념으로 사용됩니다. 소멸자는 클래스의 객체가 소멸될 때 호출되어집니다. 객체 생성시 할당했던 메모리를 소멸자로 하여금 회수하도록 하는 것입니다.
C++과 마찬가지로 소멸자는 매개변수를 가질수 없을 뿐더러 접근 제한자를 가질수 없고, 명시적으로 호출을 될 수도 없습니다. 소멸자는 생성자의 호출 순서와는 반대 되는 순서로 호출이 되어지는데요, 아래 예제 코드를 통해 살펴보도록 하겠습니다. 소멸자는 자신이 만든 클래스면 앞에 ~를 붙여 함수를 구현 합니다. 예를들어 사용자가 구현한 클래스의 이름이 MyClass일 경우 다음과 같이 구현 할 수 있습니다.
~ MyClass() { // 이부분에 메모리를 회수하는 작업을 구현합니다. }
간단한 예제를 통해 소멸자에 대해 좀더 알아보도록 하겠습니다.
using System; class A { public A() { Console.WriteLine("Creating A"); } ~A() { Console.WriteLine("Destroying A"); } }
class B : A { public B() { Console.WriteLine("Creating B"); } ~B() { Console.WriteLine("Destroying B"); }
} class C : B { public C() { Console.WriteLine("Creating C"); } ~C() { Console.WriteLine("Destroying C"); } } class App { public static void Main() { C c = new C(); Console.WriteLine("Object Created "); Console.WriteLine("Press enter to Destroy it"); Console.ReadLine(); c = null; Console.Read(); } }
위와 같이 3개의 A,B,C라는 클래스가 존재한다고 할때 실행 결과는 어떻게 될가요?
정답은 알아 내셨나요?? 정답을 공개하자면 아래와 같은 결과가 나타납니다.
정답은 맞추셧나요? 한번에 정답을 맞추셧다면, C#의 특성 & OOP의 개념을 잘 이해하고 계신 분이십니다. (아래 이유를 정리 해 놓았으니 보시고 이해한 답과 맞는지 비교해 보시기 바랍니다.) 그리고 틀리셨다면, 그 이유는 무엇일까요??
몇몇 분들에게 질문을 드려봤었지만, 정답을 틀리신 대부분의 사람들은 아래와 같은 결과를 예상했었는데요. New를 통해 객체를 생성하고, 이를 다시 NULL로 없애 버렸기 때문에 소멸자가 호출된다. 라고 생각을 하셨기때문입니다.
그렇다면 왜 저렇게 나오는 것일가요? New를 호출 했는데 Delete를 안해서 소멸자가 호출되지 않은걸가요?? (C++을 주로 사용하시는 분들께서는 이렇게 대답을 하시지만, 정답이 아닙니다.)
C#에서는 소멸자 호출 시점이 고정되어 있지 않기 때문입니다, C#에서는 효율적인 메모리 관리를 위해 가비지 콜렉터(Garbage Collector)라는 기능을 제공하고 있습니다. 가비지 콜렉터란 쉽게 생각해서 쓰레기 처리기 정도로 생각을 하실 수가 있는데요. New등을 통해 선언된 메모리가 더이상 사용되지 않는 쓰레기 상태가 되었을때 알아서 없애 준다는 계념입니다. (이때 소멸자가 호출이 되는거죠,)
이로인해 개발자는 메모리를 할당 놓고 사용만 하면되고, 해제하는데에 일일이 찾아 해제를 하지 않아도 자동으로 해제가 된다는 것입니다. 그럼 어떻게 가비지 컬렉터가 작동을 하는 것일가요?
제가 예전에 김역욱 MVP님 세미나를 들으면서 가비지 컬렉터에 대한 내용을 들은적이 있는데 재미있는 내용같아 이야기 해드리겠습니다.
메모리를 하나의 기숙사라고 생각합시다. 그리고 그 기숙사에 살고있는 사람들이 우리가 생성해놓은 객체라고 하겠습니다. 그리고 마지막으로, 기숙사생들을 관리하는 사감이 있습니다. 보통 우리는 어떤 할일이 있을때는 깨어있고, 할일이 없으면 잠을 잡니다. 그리고 사감은 현재 기숙사의 상황을 체크하기 위해서 기숙사를 돌면서 자고 있는 사람들을 체크합니다.
기숙사에서 생활하고 있는사람들 한명 한명 한명 돌아가면서, "야~ 자냐~?" 하고 물어봅니다. (당연히 자고 있는 사람이라면 대답을 하지 않겠죠??ㅎ) 만약에 그렇게 물어봤는데 "나지금 안자요~" 라고 대답을 한다면, 넘어가고 쥐죽은듯이 자고 있는 사람들은 기록을 합니다.
그리고 다음번에 체크를 할 때는, 아까 자고 있던 사람들 한테만 가서 또 같은 방법으로 "야~자냐~?" 라고 물어봅니다. 이와 같은 방법으로 약 3번정도 물어본 뒤 진짜로 자고 있는 사람들은 가차없이 "죽여" 버립니다. -_-
조금 섬뜩한 내용이긴 하지만, 이와 같은 방식으로 현재 사용중인 메모리와 비 사용중인 메모리를 구분 지음으로서, 불필요한 메모리 사용을 줄이게 되는 것입니다.
다시 코드로 돌아와서, 코드를 살펴 보겠습니다.
C c = new C(); Console.WriteLine("Object Created "); Console.WriteLine("Press enter to Destroy it"); Console.ReadLine(); c = null; Console.Read();
위 코드를 보시면, c = null; 이라는 부분을 찾을 수 있는데요, 맨 윗줄 new C()를 통해 변수 c에 새로운 객체 C가 저장되었지만, null이 들어옴과 동시에 이전에 저장되어 있던 객체가 방황을 하게 됩니다. -_- (나는 누구인가..) 그러다가 할일이 없으면 잠이 들겠죠? 하지만 잠이 들었다고 해서 바로 객체가 소멸하는것이 아니라, 위에서 설명 했듯이 가비지콜렉터가 자는 메모리를 죽여(-_-)줘야지만 소멸자가 호출됩니다.
그래서, null이 들어간 직후에는 소멸자가 호출이 되지 않은 것입니다. 그렇다면 소멸자를 호출하게 만드는 방법은 없을가요?
네 있습니다. 바로 가비지 컬렉터를 직접 호출하도록 해주는 방법인데요, .Net Framework에서는 가비지 컬렉터를 GC라는 이름의 클래스로 제공 사용합니다. 직접 가비지 컬렉터를 호출 해주기 위해서는 GC 클래스에 Static으로 선언된 Collect 함수 호출을 통해 가비지 컬렉터의 동작을 명령 할 수 있습니다.
그럼 코드를 살짝 바꿔 아래와 같이 작성해 보겠습니다.
C c = new C(); Console.WriteLine("Object Created "); Console.WriteLine("Press enter to Destroy it"); Console.ReadLine(); c = null; GC.Collect(); Console.Read();
null을 대입한 이후 바로 Collect를 호출함으로서 쓸모 없는 메모리를 해제 하게끔 합니다. 위와 같이 코드를 살짝 변경한 뒤 실행 한 결과는 아래와 같습니다.
조금 이해가 되셨나요? 가비지 컬렉터는 메모리를 알아서 관리 해주기때문에, 편리하기도 하지만, 그렇다고 너무 가비지 컬렉터에 의존하다 보면 오히려 프로그램의 성능을 저하 시킬 수 있으니 유의하시기 바랍니다. (메모리가 커지면 커질 수록 관리 대상 메모리가 많아짐으로 성능저하를 유발할 수 있습니다. )
이번시간에는 WPF에서의 User Interface에 대해 소개 해 드릴건데요, 지금까지 너무 숨가쁘게(?)뛰어 온것 같으니, 동영상 하나 보고 시작하기로 하겠습니다. 아래 동영상은 전혀 WPF와 관련이 없는 동영상이니 그냥 긴장하지 마시고 가볍게 재생 버튼을 클릭해주시면 됩니다. ^_^ ㅋ
-_-....
영상은 재밌으셧나요??? ㅎㅎ
그렇다면 여기서 문제!!!!! 동영상에서 나오는 인물들의 공통 점은??
-_-.....
눈치 빠르신 분들 or 스크롤을 미리 내려보신분은 이미 알고 계시겠지만, 정답은 "DCInside 합성겔러리 필수요소" 들이죠??ㅎ 갑자기 쌩뚱맞게 이런 동영상을 준비한 이유는 지금 소개해 드릴 내용때문인데요 (위에선 관련 없다더니 갑자기 왠말이냐!! -_-ㅋ)
어떤 무엇이든간에 그것을 구성하는 필수요가 있기 마련입니다. 예를들어 노래방-탬버린, 소주-새우깡, 가요계-동방신기 등이 있죠? 그렇다면 UI의 필수요소는 무었일까요? (.... 어떻게든 동영상을 괜히 넣었단 말 안들으려고 엄청난 끼워 맞추기를 진행중입니다.)
여러가지가 있겟죠? 위 그림에서만 찾아보더라도, Button,Label,TextBox,ScrollBar 등등등.. 여러가지 UI객체를 찾아볼 수 있는데요, 그 중에서 이게 없으면 아무것도 안된다!! 하는 킹왕짱 중요한게 있다면 무엇일까요?
정답은 Page 또는 Window입니다.(너무 쉬웠나요??) UI객체를 붙일 일종의 도화지라고도 할 수 있겠죠? 우리가 보통 Win32나 MFC, WinFrom등을 사용해서 UI를 구현 하면 대부분 Window방식으로 구현합니다. Window 방식이란 일반적으로 우리가 사용하는 Form기반 Application이라고 생각하시면 되는데요,
WPF에서는 이런 Window 방식 이외에 Page방식을 제공합니다. Page방식이란, 우리가 인터넷을 할때 하이퍼링크를 통해 Page단위로 화면을 이동합니다. 마치 Application에도 이와 같은 방식을 지원하는게 Page인데요, Window 단위로 정보를 표현해야만 했던 기존 방식보다 하나의 화면에 동적으로 다양한 정보를 표현 가능하다는 장점이 있습니다. (그렇다고 Window방식이 쓸모 없다는 것은 아닙니다.)
WPF에서 사용하는 XAML은 XML을 기반으로 표현하기 때문에, XAML(or CLR)로 표현한 UI는 위 그림과 같이 트리 형태로 표현 될 수 있습니다. 이 말은, 최소객체를 제외한 나머지 모든 객체는 자식 객체를 가질수 있다는 말로, 버튼 객체위에 이미지를 올려놓는다던지 하는 부분도 쉽게 구현 할 수 가 있습니다. (이부분에 대해서는 뒷부분에서 자세히 다룰 예정입니다.)
오늘 포스팅은 여기까지로 하고, 내일은 XAML에서의 Layout Control에 대해서 알아보도록 하겠습니다. 내일부터는 본격적으로 XAML을 사용한 실제 코딩과 관련된 부분을 다룰 예정이니, XAML을 작성하고 테스트 해볼 수 있는 환경을 구축 하시고 따라해보시기를 권장합니다.
이번시간에는 XAML이 무엇인지에 대해 조금더 알아보는 시간을 갖도록 하겠습니다. 길지 않은 내용이니 살짝 보시고 다음 내용으로 넘어가시면 될것 같습니다. 전 시간에 WPF에서 UI를 표현하는데 XAML을 사용한다고 했습니다. 그런데 많은 사람들이 XAML 이 WPF고 WPF가 XAML이다라고 잘못 생각하시는 분들이 많습니다. 저도 사실 처음 WPF를 접했을때 이와 같이 생각을 했었는데요,
결론적으로 말하면 XAML 는 WPF가 아닙니다. XAML은 응용프로그램의 객체를 표현 하는 XML 기반의 선억적 프로그래밍 모델이기 때문에, XAML은 XAML대로의 기능을 가지고 있는 것이죠.
XAML은 XML 과 CLR을 더한 것이라 할 수 있습니다. 다른 말로는 CLR객체를 XML형태로 표현 하는것이라고 할 수 도 있는데요, XML을 사용해 CLR 객체를 선언하고 이를 XAML Parser가 CLR로 변환 해주는 과정을 통해 우리가 사용하는 CLR 언어인 C#이나 VB.Net과 연결 하여 사용이 가능한 것입니다.
WPF는 CLR의 일부분이므로, 굳이 XAML을 사용하지 않아도 기존의 CLR을 사용하여 UI를 구현할 수 있는거죠, 하지만, XAML을 사용하여 UI를 구현하는 것이 보다 직관적이고, 관리가 용이해짐으로, 꼭 필요한 부분(동적 생성등)을 제외하곤 XAML을 사용해 코딩하는것이 바람직하다 할 수 있습니다.
얼마전에 올렸던 ART Project Design Prototype이다... 흰색 시안이 처음 만들었던 시안이고, 검정색은 악덕 PL의 초특급 갈굼(병들어 보인다 햇던가...)때문에 바꾼 시안이다. 나는 나 나름대로 흰색에 만족하고 있었는데, 바꾸고 보니까 검정색이 괜찮은거 같기도 하다.
요즘 온라인게임에 빠져서 포스팅이 살짝(? 대략 3시간정도...??ㅠ) 늦엇네요. 죄송합니다.
저번시간에 이어 WPF Overview 2번째 시간입니다. 저번 시간에는 WPF가 어떻게 구성되었고 어떻게 작동되는것인가에 대해 알아보았는데요, 처음 접하시는 분들께서는 다소 어려운 감이 있을수도 있습니다.
이번시간에는 좀더 가벼운 주제로, 왜 WPF를 사용해야 하는가 그리고 WPF를 사용하면 왜 좋은가? 에 대해서 알아보도록 하겠습니다.
보통 우리는 디자인이 요구되는 프로젝트를 할때 디자이너와 함께 작업을 합니다. (최근 UX가 발전하면서 Application의 UI 디자인은 필수요소라고 할 수 있죠.) 디자이너는 Photoshop이나 Illustrator, Powerpoint 등을 사용해서 디자인을 제작합니다. (그림 가장왼쪽) 그리고나서 각각의 세부항목들을 잘라서 JPG,PNG,PPT등의 포멧으로 변환하여 개발자에게 넘겨주죠? (간혹가다 잘라주지 않고 '통이미지'로 보내주는 사람이 있는데.. 이건뭐.... 직접 잘라다 쓰란소리죠 ㅠ ) 뭐 어쨋든 개발자는 이렇게 이미지 파일을 받으면 C++,C#, VB(주로 사용하는 언어가 없다고 미워하진 마세요ㅠ 떠오르는것들만쓴겁니당)와 같은 언어를 사용해 UI를 구현하게 됩니다.
많은 개발자 분들이 느끼시겠지만, 개발의 한계를 이해 하지 못하는 디자이너 분들의 환상적인 디자인 때문에, 수많은 삽질과 노가다를 시작합니다. 현실은 언제나 그렇듯이 냉혹합니다ㅠ 열심히 한다고 원하는 결과가 뚝딱 나오는건 아니죠ㅜ
엄청난 삽질과 노가다를 통해 디자이너의 요구대로 구현을 하다보면 실제로 구현하기 너무 힘든 부분이 발생하는 경우도 있습니다. 위에서 예시를 든 콤보박스를 보면..
간지가 좔좔 흐르는 콤보 박스에 각각 아이템들에는 체크박스도 포함되어 있네요.. 체크박스도 보통 체크박스는 아닌듯 하고.. 위와 같이 구현을 하려면 보통은 콤보박스를 새로 구현을 해야합니다. 체크 박스따로 만들고 체크박스포함된 콤보박스 아이템 만들고 거기다 콤보박스 틀에 내부 기능까지... 해야 할 일이 너무 많습니다. ( 이럴경우를 보고 배보다 배꼽이 크다고 하죠.)
개발자 입장에서는 이것도 해보고 저것도 해보다가 결국 타협을 하기 시작합니다. 이건 기술적으로 안되, 저거 하려면 시간이 너무 오래걸려 이렇게 자신과의 타협을 하면서 나온결과물은 그림 오른쪽, 기존 콤보박스와 별다른 차이가 없죠.
이제부터 디자이너와 개발자의 싸움이 시작됩니다. 디자이너는 왜 자기가 디자인 해준데로 구현을 못하냐고 소리치고, 개발자는 그게 말처럼 쉽게 되는게 아니니까 니가 해봐라 하고, 그럼 가능한선에서 예쁘게 만들라고 합니다. 이말은 마치 디자이너가 어느정도 컨셉을 정해주면 개발자가 알아서 개발이 가능한 형태로 새로 디자인해서 개발을 해라 라는 말과 같죠..
그럼 개발자들은 이렇게 말합니다.
개발만으로도 할일이 태산같은데, 디자이너가 할일까지 해야 하겟냐는거죠.. WPF는 이런 상황에 놓인 개발자들을 위한 해결책이라 할 수 있습니다. 아래 그림을 살펴보도록 하겠습니다.
아까와 비슷한 그림이지만 잘 살펴보면 이번에는 개발자의 콤보박스가 디자이너가 요구한데로 그대로 구현이 되어있다는걸 확인 하실 수 있습니다. WPF를 사용한 결과인데요, 어떻게 된일일까요?
눈에 띄는것을 보면, 이전에 Photoshop이나 Illustrator를 JPG,PNG등의 포멧으로 전달 햇던 작업이 딸랑 XAML이라는 것하나로 해결된것을 확인 할 수 있습니다. XAML이란 WPF에서 UI를 표현하기 위한 언어로 디자이너와 개발자가 모두 사용가능한 형태의 중간 언어라고 할 수 있습니다.
"중간 언어" 라고 표현을 했는데, 그렇다면 디자이너들은 그럼 우리가 언어를 배워야 하는거 아니냐 라고 말할 수 있겟죠? 배워서 남주는건 아니니 배운다고 나쁠건 없지만, 배우기 싫으면 굳이 배우지 않아도 언어를 충분히 다룰 수 있습니다. Exression Studio와 같은 Tool을 사용해 디자인을 하고, XAML으로 저장만하면 되기 때문이죠.
XAML은 디자이너의 디자인을 객체단위로 XML로 표현하는 방법이라 할 수 있습니다. 개발자는 이렇게 XML형태로 만들어진 디자인을 가져다가 그대로 사용하면 되는것이죠. 정리하면 디자이너가 위와 같은 버튼을 하나 그렷다고 가정을 해보겠습니다.
그럼 XAML(왼쪽)으로 표현될것이며, 개발자가 버튼을 을만들면 C#,VB.NET(중앙,오른쪽) 과 같이 코드로 표현하게 됩니다. 차이점은 코드를 통해 UI를 구현 할 경우 디자이너가 보내준 그림을 기준으로 개발자가 새로 구현 해야하지만, 디자이너가 만들어준 XAML을 사용하면 개발자가 UI를 새로 구현할 필요 없이 내부 Logic만 구현하면 바로 사용이 가능 하다는거죠.
아직까지는 살짝 애매할 수 도 있는 부분이지만, XAML에 대한 이야기와 디자이너와 협력 부분은 뒷부분에서 더 자세히 다루도록 하겠습니다. (지금은 일단 XAML이라는게 있구나 라고 만 이해해 두시면되겠습니다.)
XAML은 Expression Designer나 Expression Blend와 같은 Tool에서 쉽게 제작이 가능하며 Expression Studio에서 만들어진 XAML은 곧바로 VisualStudio에서 사용이 가능합니다. 한가지 덧붙이자면, VisualStudio에서 개발한 프로젝트를 Expression Blend에서 불러와 디자인 작업을 할 수 도 있고, Expression Blend에서 작업한 프로젝트를 Visual Studio에서 불러와 사용할 수있습니다.
여기서 중요한 점은 바로, UI와 Logic의 분리 입니다. 이제 디자이너는 디자인만 하고, 개발자는 내부 Logic만 구현하면 되는 시대가 된거죠.
일단 이번 시간은 여기까지로 하고, 다음 시간부터는 XAML과 WPF에 대해 조금더 알아보도록 하겠습니다. 지금 시간이 대략 새벽 4시가 가까워지고 있는데 ㅠ 너무 졸려서 인지 쓰면서도 내가 맞는 말을 하고 있는가 싶습니다. ㅠ 일단 일어나서 한번더 읽어보긴 하겠지만, 혹시나 읽으시다가 잘못된 부분이나 질문은 사정없이 태클 걸어주시기 바랍니다. 그럼 전 꿈나라로~~
보. 너. 스.!!!! XAML이 국내에 소개되면서 많은 개발자들 사이에서 논란이 되었던 XAML에 대한 발음에 대해 말씀드리겠습니다. 이건 지극히도 개인적인 의견이며 정답이 아닐 수도 있으니 100%신뢰 하지는 마시길 바랍니다.
지금 삼성소프트웨어멤버십에서 진행중인 ART프로젝트 디자인 시안이다. 지금까지 보통 프로젝트 시작하면 엔진부분을 담당햇는데 이번 프로젝트에서는 UI부분을 대부분 담당하게된다. Photoshop CS3를 사용하여 작업하였으며, 조만간 팀원들이 OK한다면 WPF로 작업 시작할 예정이다.
프로젝트에 대해 간단히 소개하자면, 많은사람들이 X-Ray는 알고있을것이다. 뭐 물론 CT또한 이름은 모두 들어봤을테고.. 3D Max도 알고잇을테다.
간단히 설명하면 위에서 언급한것들을 Mix 하는것과 같다.
X-Ray를 통해 촬영한 여러장의 투영영상을 조합하여 CT영상을 만들고 CT영상 여러장을 조합하여, 3차원 영상으로 변환하고, 이를 활용하는 Application이다.
프로젝트에 대한 진행상황이나 프로젝트를 진행하면서 얻어낸 Tip 등은 블로그를 통해 올릴 생각이다.