실제 프로그램 제작
지금까지 어쩌면 먼길을 돌아 왔다. 이제 실제 프로그램 제작시 사용하는 방식으로 프로그램을 작성해 보겠습니다.
Visual Studio .NET을 실행하여 파일 메뉴의 새로 만들기의 부메뉴 프로젝트를 선택하면 다음과 같은 대화 상자가 생성됩니다.
이제 Windows 응용 프로그램을 선택하고 이름을 적당히 입력(BaseProgram라고 입력)한 후 확인을 선택하면 다음과 같이 솔루션 탐색기에 프로젝트가 추가 됩니다.
솔루션 탐색기의 실제 소스 파일인 Form1.cs는 적당히 이름을 변경(여기서는 BaseProgram.cs)합니다. 참조를 펼쳐 보면 앞에서 설명한 것 보다 좀더 많은 어셈블리가 참조 되어 있다(참조는 많이 해도 사용하지 않으면 컴파일이 자동으로 무시되므로 상관없다). App.ico는 Icon 파일이고 AssemblyInfo.cs는 Version등 환경 설정을 하는 내용들이 들어 있습니다. 내용을 알기 전에서 손대지 않는 것이 좋다.
이제 속성 창을 봅시다. 필자는 설명하기 좋게 솔루션 탐색기를 닫아 아래와 같이 속성 창이 화면에 많이 나오게 설정했다. 만약 속성창을 닫았으면 보기 메뉴의 속성창을 선택하면 화면에 나타납니다.
속성 중 디자인의 (Name)은 클래스 이름입니다. 이 이름을 적당히(MainForm) 수정합니다. 속성창에서 아래로 조금 내리면 Text라는 Attribute가 Form1으로 되어 있는데 Title 바에 표시되는 문자열이니 적당히 수정합니다. 이제 컴파일을 하면 에러가 하나 발생하는데 향후 Source에서 수정할 것입니다.
이제 Source를 봅시다. Source는 솔루션 탐색기 BaseProgram.cs에서 마우스 오른쪽 버튼을 선택하여 생성된 팝업 메뉴에서 코드 보기를 선택하면 Source를 볼 수 있습니다. 참고로 BaseProgram.cs를 더블클릭하면 디자인이 있는 .cs 파일이라면 위 그림과 같이 디자인 모드로 열린다.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace BaseProgram
{
/// <summary>
/// Form1에 대한 요약 설명입니다.
/// </summary>
public class MainForm : System.Windows.Forms.Form
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.Container components = null;
public MainForm()
{
//
// Windows Form 디자이너 지원에 필요합니다.
//
InitializeComponent();
//
// TODO: InitializeComponent를 호출한 다음 생성자 코드를 추가합니다.
//
}
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows Form 디자이너에서 생성한 코드
/// <summary>
/// 해당 응용 프로그램의 주 진입점입니다.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}
앞에서 수동으로 열심히 Source를 작성한 사람은 Source가 많이 눈에 익을 것입니다. 수동으로 작성할 때 작성하지 않은 것을 위주로 Source를 설명해 보겠습니다.
1. namespace BaseProgram
문법 정리에서 C#은 namespace가 존재한다고 설명했다. 그러나 그 이후에 수동으로 작성한 프로그램들에서는 namespace를 사용하지 않았다. 그러면 namespace를 선언하지 않은 Class들은 어떻게 되는가? 그것은 이름없는 namespace 소속이 되어 문제없이 동작합니다.
2. InitializeComponent()
MainForm 생성자에서 Form을 초기화 하고 Event를 연결했던 것을 기억할 것입니다. 생성자에서 수행하던 이 모든 작업을 Visual Studio의 속성창에서 모두 작성하게 될 것이므로 InitializeComponent라는 함수를 하나 만들어 별도로 호출하는 구조로 되어 있습니다.
3. Windows Form 디자이너에서 생성한 코드
이 부분에 Visual Studio의 속성창에서 작성한 코드들이 들어 갈 것입니다. 이 부분을 펼쳐 보면 내부에 InitializeComponent Method가 선언되어 있고 속성창에서 설정한 내용들이 그 Method 내에 들어 있습니다.
4. Dispose
Form이 종료될 때 호출되는 Method입니다.
5. Application.Run(new Form1())
위 Source를 보면 Class가 MainForm으로 되어 있는 것을 알 수 있습니다. 그러나 기본적으로 생성되는 Form1이라는 이름으로 어플리케이션을 동작시키고 있습니다. 따라서 여기에서 에러가 발생합니다. Form1을 MainForm으로 수정하면 됩니다.
다시한번 정리를 하면, 프로젝트를 만든후, 솔루션 탐색기에서 Form1.cs를 프로잭트이름.cs로 변경하고, 속성창에서 (Name)을 MainForm으로 Text를 Title 바에 표시될 이름으로 변경하며, Source에서 Form1을 MainForm으로 변경합니다. 프로그램 작성시 이 과정을 꼭 한 후 시작하는 버릇을 들이기 바랍니다.
이제 마우스와 키보드를 처리해 보도록 하겠습니다. Visual Studio의 속성창의 위쪽 번개 모양의 아이콘(이벤트 아이콘)을 선택하면 화면은 다음과 같이 바뀝니다.
이 화면이 나오기 위해서는 위 그림과 같이 디자인 모드 파일을 열어야만 합니다. MouseDown에서 마우스 더블클릭 하면 자동으로 MouseDown이라는 Event가 연결이 되고 Delegate에 의해 호출될 함수가 생성되어 편집할 수 있도록 그 위치로 이동합니다. 여기서는 간단히 MessageBox.Show("마우스가 눌러졌습니다.");를 입력합니다. KeyDown도 같은 방법으로 처리합니다.
이제 다시 소스를 보도록 하겠습니다. 아래 Source는 위에서 설명한 내용은 되도록 생략하고, Windows Form 디자이너에서 생성한 코드를 펼쳐서 내부까지 보인것입니다.
namespace BaseProgram
{
public class MainForm : System.Windows.Forms.Form
{
public MainForm()
{
InitializeComponent();
}
#region Windows Form 디자이너에서 생성한 코드
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오.
/// </summary>
private void InitializeComponent()
{
//
// MainForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Name = "MainForm";
this.Text = "테스트 프로그램";
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.MainForm_KeyDown);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.MainForm_MouseDown);
}
#endregion
[STAThread]
static void Main()
{
Application.Run(new MainForm());
}
private void MainForm_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
MessageBox.Show("마우스가 눌러졌습니다.");
}
private void MainForm_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
MessageBox.Show("키보드가 눌러졌습니다.");
}
}
}
InitializeComponent Method에 Event가 연결되어 있고 Delegate에 의해 호출될 MainForm_MouseDown과 MainForm_KeyDown이 정의된 것을 볼 수 있습니다.
이제 어셈블리(.exe, .dll) 구조에 대해 알아 보겠습니다. 프로젝트 디렉토리의 bin의 Debug(배포를 위해 Release로 컴파일 하면 Release) 디렉토리를 보면 다음과 같이 프로젝트이름.exe 파일이 생성된 것을 볼수 있습니다.
BaseProgram.exe를 마우스로 더블클릭하면 실행이 됩니다. 뭐 별 것 없습니다. 그러나 C#으로 작성한 실행파일과 C++로 작성한 실행파일은 내부 구조가 완전히 다릅니다. C++로 작성한 실행파일은 현재 OS에서 실행 가능한 Native 코드로 구성되어 있습니다. 그러나 C#으로 작성한 실행파일은 다음과 같은 구조로 구성되어 있습니다.
- CLR(Common Language Runtime) Loader : CLR을 메모리에 적재 시키는 기능을 수행합니다.
- Menifest : 어셈블리의 전체 요약 정보(Version, Security 정보, 링크된 다른 어셈블리 정보)를 가지고 있다(특수한 Metadata로 보면 된다).
- Metadata : 코드의 외형 정보(namespace 정보, Type 정보, Member 정보)를 가진다(C++의 Header 파일과 비슷한 기능 수행).
- MSIL(MicroSoft Intermediate Language) : C#으로 작성한 실제 내용이 국제 표준인 IL언어로 변경되어 들어 있습니다.
실행파일을 마우스로 더블 클릭 하는 순간 CLR이 메모리에 적재되어 있지 않다면 적재시키게 됩니다. 적재된 CLR이 어셈블리를 분석하여 실행을 해줍니다. CLR 내부를 약간 설명하면 어셈블리 내의 MSIL을 JIT(Just In Time) 컴파일러가 Native 코드로 컴파일하여 실행하는 것입니다. 이 구조 때문에 .NET(C#, C++ .NET, Basic .NET 등)으로 만든 실행파일은 CLR이 없으면 동작하지 않습니다. 이것이 CLR이 포함된 .NET Framework를 설치해주어야 하는 이유입니다.
이 실행 구조에 의해 다음과 같은 장단점이 있습니다.
장점 | 단점 |
- 호환성이 뛰어 나다. 언어간 호환성 : Visual Basic .NET, C++ .NET 등 어느 언어로 컴파일 하여도 위의 구조로 파일이 생성됩니다. 따라서 어떤 언어로 작성한 dll이어도 서로 호환이 됩니다. OS간 호환성 : 실현 가능성은 희박하지만 UNIX에도 CLR을 지원하기만 하면 호환되게 됩니다. 현재 PDA 등에 탑재되는 Windows CE와의 호환성만으로도 OS간 호환성은 큰의미가 있습니다. - CPU에 따른 실행시 최적화 C++ 6.0이후 버젼으로 컴파일을 수행하면 호환성을 위해 80386(32Bit) CPU에 맞추어서 Native 코드가 생성됩니다. 즉 그이후 나온 CPU는 충분한 기능을 발휘 못한다고 보면됩니다. 그러나 .NET은 실행시 Native 코드를 생성하여 실행하므로 CPU에 최적화하여 충분한 기능을 발휘할 수 있게 됩니다. 이 내용을 보면 C++ 6.0이후 버전으로 컴파일한 실행파일은 80286에서는 동작하지 않음을 알수 있습니다. 따라서 .NET은 CPU간 호환성도 있습니다. |
- 실행시 JIT 컴파일을 수행하므로 초기 수행 속도 저하가 있습니다. 이 부분에 대해서는 속도 저하를 막기 위해 Microsoft사에서 많은 노력을 하고 있습니다. 현재 노력한 흔적을 이야기 하면 필요한 부분만 변환하여 실행하고, CPU가 노는 시간에 변환(부하 분산)하는 등의 기능이 들어 있습니다. |
예제 프로그램 다운로드
'C#' 카테고리의 다른 글
C#06. GDI+ 및 깜박임 문제 해결 (0) | 2022.03.08 |
---|---|
C#05. 메뉴 및 툴바 지원 (0) | 2022.03.08 |
C#03. 기본 프로그램 제작 2 (0) | 2022.03.08 |
C#02. 기본 프로그램 제작1 (0) | 2022.03.08 |
C#01. C++과 문법적으로 다른점 (0) | 2022.03.07 |