1. 프로젝트 만들기


자, 이제 프로젝트를 한번 만들어봅시다. 우선 Microsoft Visual Studio를 실행시킨 후에, 파일(F) -> 새로 만들기(N) -> 프로젝트(P)...를 누르거나 Ctrl+Shift+N을 눌러 '새 프로젝트' 창을 엽니다.


.

여기서 '콘솔 앱(.NET Framework)'를 선택하고 확인을 누릅시다. 우리가 콘솔 앱 프로젝트에서 배우는 내용들은 Windows Forms이나 WPF의 기초가 되므로 여기서 확실하게 배우고 넘어가야 합니다. 아래의 확인 버튼을 눌러 프로젝트를 만들어 봅시다.



그러면 아래와 같이 코드 창이 보이고, 솔루션 탐색기에서 우리가 만든 프로젝트를 확인할 수 있을 것입니다. 그럼, 이제부터 C#의 기본적인 코드를 보면서 언어에 대한 감을 잡도록 합시다.



2. 기본구조 파악


모든 준비가 끝나셨으면 아래와 같이 작성하여 프로그램을 만들어봅시다.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, world!");
        }
    }
}
위와 같이 작성하셨으면, F6을 누르면 '빌드(build)'가 됩니다. 여기서 빌드란 프로그램을 만드는 작업을 의미하며, 빌드 과정에는 컴파일이나 패키징, 테스트 등과 같은 다양한 과정이 모두 포함되어 있습니다. 

  컴파일(Compile)은 무엇인가요?


컴파일은 사람이 이해할 수 있는 소스 파일을 컴퓨터가 이해할 수 있는 기계어 파일로 만드는 과정을 말합니다. 


.NET 컴파일 과정


위와 같은 과정을 자세히 살펴보자면, 각각의 언어마다 별개의 컴파일러가 존재합니다. 우리가 C#로 작성된 소스 코드를 컴파일하면, C# 컴파일러에 의해 exe나 dll 파일과 같은 출력 파일이 만들어집니다. 이렇게 만들어진 파일을 어셈블리(Assembly)라고 부릅니다. 그리고 이 어셈블리 안에는 CIL(Common Intermediate Language)와 메타데이터(Metadata), 매니페스트(Manifest) 정보가 포함되어 있습니다. 


여기서 CIL란 컴퓨터가 해석 가능한 원시 코드(Native Code)가 되기 전 중간 단계의 언어입니다. 우리가 작성한 소스 코드는 바로 CIL로 변환되는 것입니다. 여기에서 컴파일 과정은 끝이 납니다. 이후는, JIT(Just-In-Time) 컴파일러에 의해 컴퓨터가 이해할 수 있는 원시 코드로 다시 컴파일되어 우리가 만든 프로그램이 실행되게 됩니다.


만약 디버깅하고 싶으시다면 F5를 누르면 바로 디버깅이 시작됩니다. 그런데 Hello, world가 정상적으로 출력됐나 확인하기 위해 F5를 눌렀으나 순식간에 콘솔 창이 나타났다 사라진다면, 디버깅하지 않고 실행(Ctrl+F5)를 눌러 확인하시면 됩니다. 

  디버깅(Debugging)은 무엇인가요?


프로그램 내에 있는 기존의 논리적인 오류나 잠재적인 오류를 가리켜 버그(bug)라 하며, 이러한 오류를 수정해나가는 과정을 디버깅이라 말합니다. 우리가 프로그램을 만드는 과정에서 '반드시'라고 해도 될 정도로 많은 결함들이 생겨납니다. 프로그램이 실행 중에 비정상적으로 종료되거나, 우리가 생각한 결과와는 다른 잘못된 결과 값을 출력할 때 디버깅을 통해 근본적인 원인을 찾아낼 수 있습니다.


Ctrl+F5를 눌러 결과를 확인해보면,

Hello, world!
계속하려면 아무 키나 누르십시오 . . .

위와 같이 Hello, world!가 출력되는 것을 확인하실 수 있습니다. 코드로 돌아가서, 9행의 Console.WriteLine()는 괄호 안에 오는 문자열을 콘솔 창에 출력시킵니다. 즉, "Hello, world!"라는 문자열을 콘솔 창에 출력시키라는 말과 같습니다. 
...
    Console.WriteLine("Hello, world!");
...
Console.WriteLine()와 동일한 기능을 하는 Console.Write()도 존재하는데 둘의 차이는 개행을 하고 안 하고의 차이입니다. 저 예제에서 Console.WriteLine()을 Console.Write()로 바꾼 다음에 다시 결과를 확인해봅시다.
...
    Console.Write("Hello, world!");
...

결과:

Hello, world!계속하려면 아무 키나 누르십시오 . . .

아까와 비교해보면 "계속하려면 아무 키나 누르십시오 . . ."가 "Hello, world!"가 끝나는 그다음에 왔죠? Console.WriteLine()으로 문자열을 출력시키면 그다음 줄(Line)로 넘어갑니다. Console.Write()는 다음 줄로 넘어가지 않고 바로 출력시킵니다.

Console.WriteLine()와 Console.Write()는 이해를 했습니다. 그런데, using은 뭐고 namespace는 뭐고 class는 뭐고, static void Main()는 또 뭘까요? 이제부터 하나씩 차근차근 알아보도록 하겠습니다.

3. using

using은 말 그대로 '사용하다'라는 의미를 가지고 있습니다. 그렇다면 1행의 using은 무엇을 사용하는 것일까요?
using System;
바로 네임스페이스 System을 사용한다는 말과 같습니다. using을 이용하면, 전체 이름을 참조하지 않고 선언된 네임스페이스 내부 개체들에 접근할 수 있어 불필요한 타이핑을 막습니다. 그렇다면, 네임스페이스(namespace)는 뭘까요?

4. namespace

네임스페이스(namespace)는 관련된 구조체, 클래스, 델리게이트, 인터페이스 등을 그룹화 한것을 말합니다. 예를 들어서, System.Collections.Generic에는 제네릭 컬렉션을 정의하는 클래스와 인터페이스들이 들어있습니다. 또 System.Linq에는, LINQ를 사용하는 쿼리를 지원하는 클래스와 인터페이스들이 들어있습니다. 이처럼 네임스페이스는 사용하기 편리하게끔 성격이 비슷한 것들을 묶어놓는 것과 같습니다. 추후에 더 자세히 설명하도록 하겠습니다.

클래스(class)는 크게 두가지로 나뉩니다. 필드(field)와 메소드(method)로 나뉘게 되는데 필드는 정적인 상태를, 메소드는 동적인 기능을 표현합니다. 독립적으로 존재할 수 있는 최소 단위, C# 프로그램을 구성하는 기본 단위이며, 이 하나의 클래스를 가지고도 여러 개의 객체(object)를 만들어낼 수 있습니다. 클래스에 대해서도 추후에 자세하게 다룰 예정입니다.

5. main

마지막으로 static void Main는 메소드(method)이며, 메인(main) 메소드는 그중에서 가장 중요한 메소드 이며, 프로그램의 최초의 진입점(Entry Point)을 나타냅니다. 모든 프로그램에는 메인 메소드가 반드시 존재해야하며, 메인 메소드가 시작되면 프로그램이 시작되며, 종료되면 프로그램도 같이 종료됩니다. 여기서 static는 한정자로 정적인 메소드를 의미하며, void는 반환 형식으로 반환 값이 없음을 의미합니다. (메소드(method)는 C언어의 함수(Function)와 같습니다.)