앞서 우리는 if문에 대해 배워보았습니다.

[C#] 프로그래밍의 꽃 if문

if문에서는 어떤 상황을 가정하며 상황에 맞는 결과를 출력 혹은 행동할 수 있게끔 프로그램을 이끌어가는 하나의 흐름으로 볼 수 있습니다.

switch문 또한 if문과는 조금 다른 형태의 흐름을 제어하는 제어문이라 볼 수 있습니다. 

 


switch문의 기본 형태

switch (조건의 대상이 되는 변수)
{
	case 조건값1 :
    	조건값1이 참일 경우 실행;
        break;
    case 조건값2 :
    	조건값1이 참일 경우 실행;
        break;
    case 조건값3 :
    	조건값1이 참일 경우 실행;
        break;
    case 조건값4 :
    	조건값1이 참일 경우 실행;
        break;
    default :
    	위의 조건값에 해당하지 않는 경우에 실행;
        break;	
}

의 기본 형태로 진행하고 있습니다. 조건은 꼭 조건4까지만 있는 것이 아닌 원하는 만큼 넣어도 됩니다.

 

  1. switch문은 case 별로 나누어서
  2. case에 해당하는 조건을 찾아간 다음, 그에 해당하는 행동요건을 실행합니다. 
  3. 그리고 중지! (break) 하는 형태를 이루고 있습니다.
  4. 위에서 원하는 조건(case)를 찾지 못한다면, 기본값(default)을 찾아서 실행하는 것이지요.

 

예시를 들어보도록 하겠습니다.

[1부터 5까지의 숫자를 한 개 입력받아서 실행하면 그에 따른 결과값을 출력하는 예제입니다.]

using System;

namespace MyFirstApp
{
	class Program
    {
    	static void Main(String[] args)
        {
        	int input = 0;
            
            Console.Write("1~5까지의 숫자를 입력하세요 : ");
            input = Convert.ToInt32(Console.ReadLine());
            
            switch(input)
            {
            	case 1:
                Console.WriteLine("1을 입력하셨군요!");
                break;
                case 2:
                Console.WriteLine("2를 입력하셨군요!");
                break;
                case 3:
                Console.WriteLine("3을 입력하셨군요!");
                break;
                case 4:
                Console.WriteLine("4를 입력하셨군요!");
                break;
                case 5:
                Console.WriteLine("5를 입력하셨군요!");
                break;
                default:
                Console.WriteLine("1 ~ 5 외의 숫자를 입력하셨습니다!");
                break;
            }
        }
    }
}


 

실제 입력을 해서 확인해보면, 3을 입력하면 -> 3을 입력하셨군요! 라는 문장이 나오게 됩니다. 

 

여기서는 지금까지와 다른 한 문장이 추가되었는데, 바로 Convert.ToInt32(Console.ReadLine()); 입니다.

C#은 프로그래머가 쓰기 좋게 만들어져서 이러한 형태처럼 해석을 하기 편하게 만들어져 있습니다. 처음보면 당황할 수 있지만, 조금만 익숙해진다면 그 무엇보다 편하게 쓸 수 있습니다.

Convert.ToInt32(Console.ReadLine()) 하나씩 해석해보도록 하겠습니다.

 

  1. 괄호에서 제일 안쪽, 오른쪽부터 해석합니다. 
  2. Console.ReadLine() -> 한 줄을 읽겠다. (Console에 들어있는 기능 중 하나인 REadLine 기능을 쓰려고 한다.)
  3. 2번에서 읽어들인 것을 ToInt32 (Int 형으로, 즉 정수형으로), Convert (변환하겠다.) // Convert.ToInt32 를 한번에 해석해서 변환하려고 하는데, To Int32인 정수형으로 변환하고자 합니다. 정도로 해석할 수 있겠습니다.

앞으로 볼 내용들도 대부분 이러한 형태를 가지게 됩니다. 복잡한 형태라도 대부분이 이러한 형태를 가지고 있는데, 이 부분은 나중에 다시 설명하도록 하겠습니다. 지금은 입력받는 것은 문자열이지만, 입력받는 것은 정수형으로 받아야하므로 바뀐다는 사실만 알아두시면 됩니다. 

 


그렇다면 만약에 break문을 안쓰게 되면 어떻게 될까요?

using System;

namespace MyFirstApp
{
	class Program
    {
    	static void Main(String[] args)
        {
        	int input = 0;
            
            Console.Write("1~5까지의 숫자를 입력하세요 : ");
            input = Convert.ToInt32(Console.ReadLine());
            
            switch(input)
            {
            	case 1:
                Console.WriteLine("1을 입력하셨군요!");
                break;
                case 2:
                Console.WriteLine("2를 입력하셨군요!");
                
                case 3:
                Console.WriteLine("3을 입력하셨군요!");
                
                case 4:
                Console.WriteLine("4를 입력하셨군요!");
                
                case 5:
                Console.WriteLine("5를 입력하셨군요!");
                
                default:
                Console.WriteLine("1 ~ 5 외의 숫자를 입력하셨습니다!");
                break;
            }
        }
    }
}

이러한 형태로 말이죠.

여기에 3을 입력한다면, 결과는 

3을 입력하셨군요!

4를 입력하셨군요!

5를 입력하셨군요!

1 ~ 5 외의 숫자를 입력하셨습니다. 

가 나오게 될 것입니다.

 

여기서 우리는 break가 특정 case에 따른, 결과값을 break해준다는 사실을 볼 수 있습니다.

 


위와 같은 결과를 활용하면 이러한 형태를 만들 수도 있습니다.

 

using System;

namespace MyFirstApp
{
	class Program
    {
    	static void Main(String[] args)
        {
        	int input = 83;
            
            Console.WriteLine("당신의 성적은 ");
            switch(input)
            {
            	case 100: case 99: case 98: case 97: case 96: case 95: case 94: case 93:
                case 92: case 91:
                Console.WriteLine("A입니다.");
                break;
                case 90: case 89: case 88: case 87: case 86: case 85: case 84:
                case 83: case 82: case 81:
                Console.WriteLine("B입니다.");
                break;
                case 80: case 79: case 78: case 77: case 76: case 75: case 74: case 73:
                case 72: case 71:
                Console.WriteLine("C입니다.");
                break;
                case 70: case 69: case 68: case 67: case 66: case 65: case 64: case 63:
                case 62: case 61:
                Console.WriteLine("D입니다.");
                break;                
                default:
                Console.WriteLine("F입니다.");
                break;
            }
        }
    }
}

다양한 case를 활용해서 성적처리 프로그램을 만들었습니다. 단점은 너무 코드를 쓸 양이 많아진다는 점과 실수를 처리하기에는 부적절할 수도 있습니다. 그래서 위와 같은 코드는 if절로 처리하는 것이 더 효율적입니다.  <조금 더 정확하게는 간단한 상수값을 통한 비교라면 switch문이 효율적이지만, 복합적인 상황 혹은 여러 가지 조합을 이용한 비교라면 if문이 유리합니다.>

 

using System;

namespace MyFirstApp
{
	class Program
    {
    	static void Main(String[] args)
        {
        	int input = 83;
            
            Console.WriteLine("당신의 성적은 ");
            
            if ( input > 90 || input <= 100)
            {
                Console.WriteLine("A입니다.");
            }
            else if ( input > 80 || input <= 90)
            {
            	Console.WriteLine("B입니다.");
            }
            else if ( input > 70 || input <= 80 )
            {
            	Console.WriteLine("C입니다.");
            }
            else if ( input > 60 || input <= 70)
            {
            	Console.WriteLine("D입니다.");
            }
            else 
            {
            	Console.WriteLine("F입니다.");
            }
                        
        }
    }
}

switch문으로 일일히 쓰는 것보다 if문을 활용한 범위를 쓰는 것이 더 깔끔합니다. 물론 더 다양한 형태로 사용할 수도 있습니다. 위의 코드는 하나의 예시일 뿐입니다. 

if문과 switch문의 차이는 위와 같은 차이점이 있으며 보통 정수 혹은 딱딱 떨어지는 스위치를 누르는 것과 비슷하게 적용한다면 switch문이 유리하며, 특정 범위와 같은 범주라면 if문이 유리합니다. 

이는 프로그래머의 성향일 뿐 정해진 답은 없습니다. 

다만 좋은 프로그래밍은 누가보더라도 '가독성'이 좋은 코드입니다. 한 눈에 읽히는 것이 가장 좋습니다.

 

항상 중요한 것은 실습을 통해 둘 사이의 차이점을 이해하고 적절한 상황에 적절한 도구를 사용하는 것이겠죠?

우리가 프로그래밍을 구현함에 있어서 가장 중요한 점 중 하나는 특정 상황에 따라 맞는 행동을 해주는 것입니다. 그럴 때 사용하는 것이 바로 if문입니다.

if 문은 영어의 뜻 그대로 "만약 ~ 한다면" 이라는 의미를 가지고 있습니다.

하나를 예로 들어보도록 하죠.

- 만약에 인터넷을 더블클릭 한다면 -> 인터넷이 시작될 것이다.

- 만약에 키보드 엔터 버튼을 누른다면 -> 다음 줄로 넘어갈 것이다.

이러한 형태로 만약 ~한다면, ~할 것이다. 라는 형태를 이루고 있습니다. 

 

우리가 사용하고 있는 대부분의 프로그램 또한 무언가를 클릭하면 무언가가 선택이 되거나 그에 맞는 행동을 하기 마련입니다. 

 

if 문의 일반적인 사용 방법

if ( 우리가 원하는 조건, 10보다 큰 숫자라면 )
{
	10보다 큰 숫자가 왔을 때의 행동
	Console.WriteLine("나는 10보다 크다!");
}

의 형태처럼 사용할 수 있습니다. 

위의 코드를 조금 더 자세한 코드로 바꾸어서 이야기하자면, 

if ( num > 10 ) 
{
	Console.WriteLine("10보다 큰 숫자입니다!");
}

num이라는 숫자가 10보다 크다면, { } 안의 코드가 실행되는 형태입니다. 만약에 num > 10 이 거짓이라면 { } 안의 코드는 실행되지 않습니다. 

 

자 그래서 if 문의 기본 형태는 

if ( 참(true)인지 거짓(false)) 
{
	참이면 실행되는 명령
}

의 형태를 이루고 있습니다. 여기서 용어의 통일을 위해서 우리는 { } 괄호 안의 감싸져 있는

코드를 '코드 블럭(Code Block)'이라고 부릅니다.

 

그리고 if ( 이곳에 있는 문장을 '조건식' ) 이라 합니다. 

 

if문의 형태는 기본적으로 조건식을 검사한 뒤에, 나머지 코드 블럭에 있는 문장을 실행하는 형태로 코드를 진행하고 있습니다. 

 


간단한 실습

자 그럼 위에서 배운 대로 간단한 실습을 해보도록 하겠습니다.

 

using System;

namespace MyFirstApp
{
	class Program
    {
    	static void Main(string[] args)
        {
        	int num = 10;
            
            if ( num == 8 ) 
            {
            	Console.WriteLine("이곳은 출력되지 않는 공간입니다.");
            }
        }
    }
}

위의 코드는 if문을 활용하는 하나의 코드 형태입니다. if문 안에 있는 코드블럭은 실행되지 않습니다. 

조건식에 들어있는 문장이 false(거짓)이기 때문이죠.

 

위의 코드를 같은 의미이지만 다른 형태로 바꾸어보면 이렇게 바꾸어 볼 수도 있습니다.

using System;

namespace MyFirstApp
{
	class Program
    {
    	static void Main(string[] args)
        {
        	int num = 10;
            
            if ( false ) 
            {
            	Console.WriteLine("이곳은 출력되지 않는 공간입니다.");
            }
        }
    }
}

조건식 안에 있는 문장 자체를 false로 바꾸어주었습니다. 

 

원래 num == 8 (여기서 == 는 두 개의 값이 같은지 틀린지를 확인한 뒤에, true와 false를 반환해줍니다.) 에서 false를 반환받아서 최종적으로는

if ( false )의 형태가 됩니다.  

 

if문은 중첩해서 사용할 수 있으므로 if문의 코드블럭 안에 다시 if문을 무한정으로 할 수 있다는 장점이 있습니다. 초반에 프로그래밍에 잘 모를 때는 여러가지 방법을 이용해서 나에게 주어진 문제를 풀어보면서 프로그래밍을 익혀나가야 하기에, 효율적인 프로그래밍 보다는 여러 방식으로 도전해보는 것을 추천드립니다.

 


if와 else if 그리고 else

자 그렇다면, 사람이 조건식을 판단할 때는, 단순하게 만약에 ~ 하다면 -> 하지만 그렇지 않다면 ~ 할거다.

라는 논리를 이야기합니다. 이러한 논리적 흐름을 C#에서도 마찬가지로 구현해두었습니다.

 

그것이 바로 if와 else if 그리고 else문 입니다.

 

먼저, if와 else

if와 else문은 조건식이 참이라면, if 문 안에 있는 코드블럭을 실행하고, 그렇지 않다면 else문을 실행하는 형태입니다. 둘 중에 하나는 무조건 실행되는 구조라 생각할 수 있습니다. 

 

if (조건식)
{
	실행할 코드
}
else 
{ 
	실행할 코드
}

이러한 기본 형태로 사용합니다.

 - if문이 실행안되면, else문이 실행되며

 - if문이 실행되면, else문은 실행이 되지 않는 구조입니다. 

 

if 가 참(true)이면 if문을 실행한다. / if문이 거짓이라면 else 문을 실행한다. 

의 형태로 진행되는 것이지요. 그래서 else문에는 조건식이 없습니다. if문이 아니라면 실행될 뿐인거죠.

 


if - else if - else

우리의 현실 세계는 if - else 문 만으로는 표현할 수 없습니다. 조금 더 복잡한 조건을 표현할 녀석이 필요한 것이지요. 그래서 존재하는 것이 if - else if - else 입니다.

 

먼저, 예제 코드부터 보도록 하겠습니다.

int number = 75;

if ( number > 90)
{
	Console.WriteLine("A입니다.");
}
else if ( number < 90 && number >= 80 )
{
	Console.WriteLine("B입니다.");
}
else if ( number < 80 && number >= 70 )
{
	Console.WriteLine("C입니다.");
}
else if ( number < 70 && number >= 60 )
{
	Console.WriteLine("D입니다.");
}
else 
{
	Console.WriteLine("F입니다.");
}

입력된 성적을 바탕으로 성적을 산출하는 프로그램입니다.  현재 성적은 75점으로 if문을 거쳐서 else if문을 계속해서 체크하며 C 성적까지 가고 있습니다.

 

여기서 조건식은 number < 80 && number >=70 는 80점 미만, 70점 이상을 의미하며, 

부등식으로 사용되었던, 70 <= number < 80을 의미합니다. 고등학교 1학년 때 배운, 부등식을 말로 표현한 형태입니다. 주로 사이에 있는 값은 && (그리고 혹은 and)값으로 표현해서 나타냅니다.

 

만약, number > 80 || number < 70 이면 (여기서 작대기처럼 보이는( || ) 것은 or(또는)을 의미합니다.

80보다 크고, 70보다 작다를 의미합니다. 

 

else if문은 if문이 실행안되면, else if문에 있는 조건식을 체크하고 -> 참이면 코드블럭을 실행, 거짓이면 다음 else if문의 조건식을 확인하는 형태로 진행하고 있습니다. 

모든 조건식이 거짓을 가리키고 있으면 기본으로 else문에 있는 코드블럭을 실행하는 형태인 것이죠.

 

 

 

이렇게 기본 형태를 가질 수 있는 것이죠. 여기서 if - else if - else 문은 당연히 중첩된 구조를 가질 수 있으며 다양한 형태로 활용이 가능합니다.

다음 시간에는 switch문의 활용에 대해 살펴보도록 하겠습니다. 감사합니다.

 

 

 

컴퓨터는 문자와 숫자를 구분하지 못한다. 그렇다면 문자로 등록되어 있는 문자열을 숫자로 바꿀 수 있는가? 답은 그렇다 이다. 

 

string a = "12";

라는 값이 있다고 생각해보자. 이는 분명히 문자열입니다. 12라는 문자열이죠. 이를 다른 숫자와 더하려고 한다면 문제가 생깁니다.

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string a = "12";
            string b = "13";

            Console.WriteLine(a+b);
            
        }
    }
}

 

  위의 코드를 입력하고 실행해보시면, 출력 결과로 1213를 받을 수 있습니다. 문자열로 선언된 두 개의 문자열이기 때문에 우리가 원하는 결과인 12+13 = 25의 결과를 받지 못한 것 입니다. 그렇다면 어떻게 12와 13을 숫자로 바꿔야 할까요?

 

  여기에 대한 답은 Parse를 쓰거나 ToInt32 메소드를 사용하는 것 입니다. 

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string a = "12";
            string b = "13";

            Console.WriteLine(a+b);

            int c = int.Parse(a);
            int d = int.Parse(b);

            Console.WriteLine(c + d);

            int e = Convert.ToInt32(a);
            int f = Convert.ToInt32(b);

            Console.WriteLine(e + f);
            
        }
    }
}

실행해보면 우리가 원하는 값인 25를 얻을 수 있습니다. 문자열을 숫자로 바꿀 수 있는 것처럼 숫자를 문자열로도 바꿀 수 있습니다. 

 

만약 a 문자열 변수에 12가 아닌 "안녕?" 을 넣으면 어떻게 될까요? 

답은 실행은 되지만 오류가 납니다.

 

 

이러한 형태로 말이죠!
(물론! 입력타입을 검사해서 적합한 타입이면 정수형으로 바꾸어주는 메소드가 존재합니다.)

 

추가로 현재 변수가 가지는 데이터형을 알아내는 메소드도 있습니다.

 

GetType()

GetType() 메소드를 활용하면 현재의 데이터 형이 무엇인지 바로 알 수 있습니다. 

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 10;
            float b = 10.32f;
            string c = "abc";

            Console.WriteLine("a의 데이터 형은 : {0}", a.GetType());
            Console.WriteLine("b의 데이터 형은 : {0}", b.GetType());
            Console.WriteLine("c의 데이터 형은 : {0}", c.GetType());

        }
    }
}

이렇게 메소드를 활용하면 각각의 형태를 하나씩 출력해보면서 확인해볼 수 있습니다. 

이 외에도 문자열을 다룰 수 있는 여러 메소드가 존재합니다. IndexOf(), LastIndexOf(), Contains(), ToLower(), ToUpper() 등이 있지만 이러한 부분도 뒤에 가서 다루도록 하겠습니다. 

# 추가 실습으로 우리가 배운 데이터 형을 선언해보고 각각의 형을 확인해보시길 바랍니다. 


Const는 상수

변수를 선언할 때, const를 붙여서 선언하게 되면, 한번 선언한 뒤에 변경이 안되는 상수가 됩니다.

const double pi = 3.14;

우리가 pi라는 형태는 3.14를 많이 사용합니다. 이러한 값을 사용할 때, 단순히 값으로만 입력하면 무엇을 의도했는지 잘 모르겠죠? 그래서 프로그램의 가독성을 위해서 그리고 실수로라도 값을 바꿀 것에 대비해서 const 상수형을 사용하는 것입니다. 여기에 추가로 전체 파일에 대한 수정을 해야 한다고 한다면, 위의 상수 하나만 교체해주면, 프로그램 내부에 있는 모든 상수값이 교체가 됩니다! 

 

실제로 상수 값을 변경하려고 한다면 컴파일에서 컴파일 오류가 납니다. 컴파일러가 상수를 변경할 수 있는 실수를 대신 막아주는 것이죠!

 


Enum 열거형

열거형은 말 그대로 값들을 나열해주는 역할을 합니다. 상수가 많아지거나 선택지가 생기게 될 수도 있습니다. 실제 상수를 너무 많이 사용하게 되면 실제로 실수하는 경우가 생깁니다. 이러한 실수는 컴파일러가 오류를 발생시켜 막아주지도 못합니다. 그렇기에 열거형을 통해 자동으로 값을 배정받도록 하는 것이지요.

 

enum 변수명 {상수1, 상수2, 상수3, ...};

의 형태로 선언합니다. 상수1은 0이라는 숫자를 입력받으며, 상수2는 1의 숫자를 받습니다. 하나씩 증가하면서 각각의 수를 매칭된다고 생각하면 됩니다.

 

어떻게 출력되는가에 대한 예제를 살펴보로독 하겠습니다.

 

using System;

namespace MyFirstApp
{
    class Program
    {
        enum RequestResult { DONE, FAILED, REJECT, APPROVAL };  // 상수는 일반적으로 대문자로 선언합니다.

        static void Main(string[] args)
        {
            Console.WriteLine((int)RequestResult.DONE);
            Console.WriteLine((int)RequestResult.FAILED);
            Console.WriteLine((int)RequestResult.REJECT);
            Console.WriteLine((int)RequestResult.APPROVAL);

        }
    }

 

위의 코드를 실행시켜보면 0, 1, 2, 3의 값이 출력으로 나옵니다. 

 

그러면 여기서 (int)를 빼고 출력해보면 어떻게 될까요?

using System;

namespace MyFirstApp
{
    class Program
    {
        enum RequestResult { DONE, FAILED, REJECT, APPROVAL };  // 상수는 일반적으로 대문자로 선언합니다.

        static void Main(string[] args)
        {
            Console.WriteLine(RequestResult.DONE);
            Console.WriteLine(RequestResult.FAILED);
            Console.WriteLine(RequestResult.REJECT);
            Console.WriteLine(RequestResult.APPROVAL);

        }
    }
}

결과는 DONE, FAILED, REJECT, APPROVAL의 형태로 출력됩니다! 

 

그런데 항상 값이 0부터 시작해서 1씩 증가해야 하는 값이어야 하는가 하면 그렇지 않습니다. 원하는 값으로 배정할 수 있습니다. 

 

using System;

namespace MyFirstApp
{
    class Program
    {
        enum RequestResult { DONE = 100, FAILED = 200, REJECT = 300, APPROVAL = 400 };  // 상수는 일반적으로 대문자로 선언합니다.

        static void Main(string[] args)
        {
            Console.WriteLine((int)RequestResult.DONE);
            Console.WriteLine((int)RequestResult.FAILED);
            Console.WriteLine((int)RequestResult.REJECT);
            Console.WriteLine((int)RequestResult.APPROVAL);

        }
    }
}

이러한 형태로 값을 따로따로 배정하면서 사용할 수도 있습니다. 

 

using System;

namespace MyFirstApp
{
    class Program
    {
        enum RequestResult { DONE = 100, FAILED = 200, REJECT = 300, APPROVAL = 400 };  // 상수는 일반적으로 대문자로 선언합니다.

        static void Main(string[] args)
        {
            RequestResult myResult = RequestResult.DONE;

            Console.WriteLine(myResult == RequestResult.DONE);
            Console.WriteLine(myResult == RequestResult.FAILED);
            Console.WriteLine(myResult == RequestResult.REJECT);
            Console.WriteLine(myResult == RequestResult.APPROVAL);

        }
    }
}

실제 사용은 이러한 형태로 사용됩니다. 우리가 원하는 결과 값을 저장해두고 그러한 값이 온다면 실행시켜주는 형태로 진행하는 것이죠. 여기서 사용된 == 은 같은 값인지 아닌지를 확인시켜주는 비교 연산자입니다. 결과가 같으면 true를 아니면 false를 반환합니다. 

앞서 데이터 형과 변수 (상)편에 이은 포스팅입니다. 이전 글에 대한 정보는

[C# 입문] 데이터 형과 변수 (상) 에 있습니다.

 


문자를 다루는 방법에는 문자 자체를 다루는 문자 형식과 문자로 이루어진 문자열 형식으로 문자들을 다룰 수 있습니다. char과 string입니다. 

char

문자 형 char는 1개의 문자를 다루는 데이터 형입니다. 우리가 Hello, World를 입력한다고 생각합시다. 그러면 char형으로는 하나하나 입력해주어야 하는 것이죠.

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            char a = 'H';
            char b = 'e';
            char c = 'l';
            char d = 'l';
            char e = 'o';
            char f = ',';
            char g = ' ';
            char h = 'W';
            char i = 'o';
            char j = 'r';
            char k = 'l';
            char l = 'd';

            Console.Write(a);
            Console.Write(b);
            Console.Write(c);
            Console.Write(d);
            Console.Write(e);
            Console.Write(f);
            Console.Write(g);
            Console.Write(h);
            Console.Write(i);
            Console.Write(j);
            Console.Write(k);
            Console.WriteLine(l);

        }
    }
}

 이렇게 하나의 문자를 담을 수 있는 것을 char형이라 합니다. 이러한 char형을 모아두면 string이라고 하는 문자열이 됩니다.

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string a = "Hello, World!";

            Console.WriteLine(a);

        }
    }
}

 

위의 문자로 이루어진 복잡한 형태가 문자열로 깔끔한 형태로 바꾸어주었습니다. 이러한 문자열 string은 정해진 데이터 범위가 없습니다. 데이터가 저장될 수 있는 양이 그때마다 다르기 때문이죠. 

 

그렇다면 여기서 또 생각해볼 수 있는 형태가 있습니다. 만약 문자열과 문자열을 더하게 되면 어떻게 될까요?

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string a = "Hello, World!";
            string b = " 안녕 세상!";
            string c;

            c = a + b;

            Console.WriteLine(c);

        }
    }
}

출력 결과를 확인하면

 

두 개의 문자열이 더해져서 나오는 것을 확인할 수 있습니다. 이렇듯 문자열은 다양한 상태로 사용될 수 있습니다. 그렇다면 여기서 문자의 갯수를 세고 싶다면 어떻게 해야할까요? 직접 하나하나 세야 할까요? 그렇지 않습니다. 우리에게는 강력한 메소드가 있으니까요!

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string a = "Hello, World!";
            string b = " 안녕 세상!";
            string c;

            c = a + b;

            Console.WriteLine(a.Length);
            Console.WriteLine(b.Length);
            Console.WriteLine(c.Length);

        }
    }
}

실제 실행을 시켜보면 13, 7, 20이 나옵니다.

실제로 하나씩 세어보도록 하겠습니다.

H e l l o ,   W o r
l d !              

총 13개의 문자가 나옴을 확인할 수 있습니다. 중간에 있는 공백을 포함해서 말이죠.

 

    !      

여기도 공백을 포함해서 7개임을 확인할 수 있습니다. 

c는 a와 b를 합친 것이므로 총 20개의 문자를 세어준 것이죠. 실제 Length의 역할을 string에 들어있는 char 유니코드 문자수가 아니라 인스턴스의 개체 수를 반환해서 수를 세어줍니다. 일반적으로 string에는 마지막에 널문자가 들어갑니다.

H e l l o null문자        

이러한 형태로 마지막 부분에 널문자를 넣음으로써 컴퓨터에게 문자열의 마지막임을 알립니다. 하지만 Length는 마지막 Null 문자를 제외하고 문자의 갯수를 공백을 포함해서 세어줍니다. 아주 편리한 기능이죠?

 


문자열에서는 사용하고 싶은 특수한 문자가 있을 수 있습니다. 예를 들어, ", \, /이러한 형태의 문자는 이대로 사용할 수 없습니다. 그래서 이러한 특수한 문자를 사용할 수 있게 하기 위해서 이스케이프 문자를 만들어두었습니다. 이스케이프 문자를 활용하면 언제든 특수한 문자를 사용할 수 있습니다. 

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string a = "Hello, \t this is tab \tand space";
            string b = "\" 큰 따움표를 사용하기 위해서는 \\를 입력해야 합니다.";

            //우리는 \를 이스케이프 문자라 합니다.

            Console.WriteLine(a);


        }
    }
}

 이스케이프 문자는 엔터 위에 있는 ' \ ' 표시가 이스케이프 문자입니다. 사용하는 곳에 따라 다르게 보이기 때문에 키보드 자판 상 돈 표시를 하고 있습니다.

 

이스케이프 형태 문자 이름 유니코드 인코딩
\' 작은 따옴표 0x0027
\" 큰 따옴표 0x0022
\\ 백 슬래시 0x005C
\0 NULL 0x0000
\a 경고 0x0007
\b 백스페이스 0x0008
\f 폼 피드 0x000C
\n 줄 바꿈 0x000A
\r 캐리지 리턴 0x000D
\t 탭 (시스템 설정에 따라 다름) 0x0009
\v 세로 탭 0x000B

등이 있습니다. 

 


Bool

  참과 거짓으로 이루어진 논리형 입니다. 단순히 true와 false 두가지 밖에 없습니다. 간략한 형태지만 프로그래머들에게는 강력한 도구가 됩니다. bool형이 없는 프로그래밍 언어에서는 0과 1로써 참과 거짓을 표현했는데, 이는 코드를 읽을 때 가독성이 떨어지게 됩니다. 하루에도 수십 줄의 코드를 읽는 프로그래머 입장에서는 굉장히 힘든일이죠. 그래서 bool형은 프로그래머가 코드를 더 잘 읽을 수 있도록 만들어주는 큰 역할을 했습니다.

 

  간략하게 bool형에 대해 살펴보겠습니다.

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            bool a = true;
            bool b = false;

            Console.WriteLine(a);
            Console.WriteLine(b);
        }
    }
}

이 코드를 실행하면 treu와 false가 출력됩니다. 

 


이렇게 기본적인 데이터형에 대해서는 마무리가 되었습니다. 아직 안한 object형도 있지만, 나중에 상속에 대한 이야기를 배운 뒤에 object를 더 자세히 다루도록 하겠습니다. 감사합니다!

 

Hello, World! 코드 분석해보기! 지난 강의에서 2개의 프로그래밍 문제를 드렸습니다. 이 문제에 대한 답부터 살펴보도록 하겠습니다. 

 

첫 번째 문제에 대한 해답은

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("안녕하세요. 저는 OO입니다.");
            Console.WriteLine("앞으로 우리의 프로그램을 재밋게 해보도록 하겠습니다.");
            Console.WriteLine("다음에 뵙겠습니다!");
        }
    }
}

 두번째 문제에 대한 해답은

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("이 줄은 첫번째 줄입니다.");
            Console.WriteLine("");
            Console.WriteLine("이 줄은 세번째 줄입니다.");
            Console.WriteLine("");
            Console.WriteLine("이 줄은 다섯번째 줄 입니다.");
        }
    }
}

 

로 볼 수 있겠습니다. 이 코드와 다르게 쓰셨다고 해도 틀린 것은 아닙니다. 다양한 방법이 있으며 여기에는 이러한 방법이 있다고 볼 수 있습니다. 출력된 결과가 같으면 정답이라 생각하시면 됩니다. 

 


 

 

  이번 포스팅에서는 C#에서 사용되는 데이터 종류에 대해 살펴보도록 할 예정입니다. C#에서 정의된 상태를 이야기하는 것이다 보니 글 자체가 지루해질 우려가 있지만, 반드시 필요한 부분이기도 하니 한 번쯤 쭈욱 읽어보신 다음에 하나하나 직접 쳐보시면서 익혀보는 시간을 갖도록 하시면 됩니다. 

 

  정말 단순한 내용이지만, 단순한 내용이기에 오히려 어려워질 수 있는 단원입니다. 꼭 한번은 끝까지 읽어보시기 바랍니다. 

 


  앞서 이야기햇듯이 컴퓨터는 데이터의 종류를 딱딱 알아맞히지 못합니다. (물론 어느 정도는 컴퓨터 스스로가 판단할 수 있도록 설계되어 있기는 합니다.) 예를 들어, 12와 "12"는 다른 형태로 받아들입니다. 그냥 12는 정수로 받아들여지며, "12"는 문자열로 쓰입니다. 인간은 이를 한 번에 알아들을 수 있도록 12라는 숫자로 자동으로 변환해서 생각합니다. 하지만 컴퓨터는 아니죠.

 

  그래서 필요한 것이 데이터형이 필요합니다. 컴퓨터가 어느정도 추측할 수도 있지만, 이러한 추측은 프로그래머 입장에서 설계의 혼란이 오기 마련입니다. 예를 들어, 숫자 12로 저장하려고 했는데, 컴퓨터의 추측으로 12라는 문자로 입력되면 이후에 오류가 나기 마련입니다. 

 

  이러한 수많은 데이터에 대한 통일을 하기 위해서는 반드시 명시적인 데이터형이 정의되어 있어야 합니다. 

 

  C#의 데이터 형식은 두 가지를 기본 근간으로 이루고 있습니다. 기본 데이터 형식복합 데이터 형식으로 크게 나눌 수 있습니다. 그리고 이러한 데이터 형식은 값 형식참조 형식으로 나누어 집니다.당장에는 기본 데이터 형식에 대해서 살펴보도록 하고 나중에 복합 데이터 형식에 대해 살펴보고자 합니다.

 


기본 데이터 형식

데이터 형식 .NET 형식(Type) 비트 범위
byte System.Byte 부호 없는 정수 8 0 ~ 255
sbyte System.SByte 부호 있는 정수 8 -128 ~ 127
short System.Int16 부호 있는 정수 16 -32,768 ~ 32,767
ushort System.UInt16 부호 없는 정수 16 0 ~ 65,535
int System.Int32 부호 있는 정수 32 -2,147,483,648 ~ 2,147,4283,647
uint System.UInt32 부호 없는 정수 32 0 ~ 4,294,967,295
char System.Char 유니코드 문자 16 -
string System.String 문자 시퀀스 - -
bool System.Boolean 논리 형식 8 true, false
object System.Ojbect 모든 형의 기본 형식 - -
long System.Int64 부호 있는 정수 64 -922,337,203,685,477,508 ~ 922,337,203,685,477,507
ulong System.UInt64 부호 없는 정수 64 0 ~ 18,446,744,073,709,551,615
float System.Single 단정밀도 부동 소수점 형식 32 -3.402823e38 ~ 3.402823e38
double System.Double 배정밀도 부동 소수점 형식 64 -1.79769313486232e308 ~ 1.79769313486232e308
decimal System.Decimal 10진수 부동 소수점 숫자 128 -3.402823e38 ~ 3.402823e38

  여기서 1.3e2 의 형태로 쓰인 수는 1.3 × 10의 제곱 형태를 의미합니다. 우리가 고등학교 때, 배운 로그에서와 비슷한 형태를 의미합니다. 수의 과학적 표기 기법에 따라 표시한 수를 의미합니다. 큰 수를 표시할 때는 e는 에러의 e가 아니라 지수의 Exponent의 e입니다. 

 

이러한 수의 범위를 직접 확인할 수 있는데, 그 방법은 int.MaxValue와 int.MinValue를 사용하는 것입니다.

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("byte의 최댓값 : " + byte.MaxValue);
            Console.WriteLine("byte의 최솟값 : " + byte.MinValue);

            Console.WriteLine("sbyte의 최댓값 : " + sbyte.MaxValue);
            Console.WriteLine("sbyte의 최솟값 : " + sbyte.MinValue);

            Console.WriteLine("char의 최댓값 : " + char.MaxValue);
            Console.WriteLine("char의 최솟값 : " + char.MinValue);
            
            Console.WriteLine("float의 최댓값 : " + float.MaxValue);
            Console.WriteLine("float의 최솟값 : " + float.MinValue);

            Console.WriteLine("double의 최댓값 : " + double.MaxValue);
            Console.WriteLine("double의 최솟값 : " + double.MinValue);

        }
    }
}

 알아보고자 하는 데이터형에다가 .MaxValue를 써주면 됩니다. 위에 코드는 몇 개만 살펴보았지만, 위에서 소개한 데이터형을 더 넣어봄으로써 각각의 값을 확인해보시기 바랍니다. 

 

  실제 실행하면

이러한 형태가 나오는데, char의 값은 ?로 나오는 것을 확인할 수 있습니다. 저장된 값에 따라 값이 변하기 때문에 이러한 형태가 됩니다. 지금은 알 수 없는 값이기에 값이 나오지 않고 있습니다. 심지어 문자열을 저장하는 데이터형인 string은 출력해보려고 하면 오류가 나옵니다. 

 

 


값 형식(Primitive Data Type)과 참조 형식 (Reference Type)

  기본 데이터와 복합 데이터 형에는 각각 값 형식과 참조 형식이 존재합니다. 값 형식은 실제 값을 변수를 통해 데이터를 저장하며, 참조 형식은 참조할 위치에 대한 주소를 저장하는 역할을 합니다. 조금 더 자세히 살펴보면 값 형식은 스택에 의해 저장되며, 참조 형식은 힙과 스택에 의해 할당됩니다. 스택에는 참조하고자 하는 주소지가 저장되어 있는 것이지요. (그리고 가비지 컬렉터에 의해서 할당된 값이 해제됩니다.) 이는 나중에 다시 이야기하도록 하겠습니다.  (이 부분에 대해 자세히 이야기하기 위해서는 스택과 힙이 필요한데, 자료구조에 대한 이야기이므로 나중에 자세히 살펴보도록 하겠습니다.) 

 

* 기본 데이터 형식에는 숫자 형식, 논리 형식, 문자열 형식, 오브젝트 형식으로 크게 나누어 집니다. 여기서 문자열 형식과 오브젝트 형식만 참조형식이며 숫자 형식, 논리 형식은 값 형식입니다.

 

* 스택은 책을 쌓아둔 것을 생각하시면 됩니다. 그래서 가장 먼저 들어간 것이 가장 나중에 나오는 선입 후출의 형태를 가집니다. 

(좌) 힙, (우) 스택

* 힙은 이진 트리라 불리는 형태를 가집니다. 가지가 2개 짜리인 나무 구조를 연상시키는 형태를 의미합니다. 이러한 트리 형태는 컴퓨터에서 자주 쓰이는 자료 구조입니다. 나중에 알아보도록 하겠습니다. 


변수

변수는 값을 저장할 수 있는 공간을 의미합니다. 

int a;
char b;
string c;

  이러한 a, b, c를 변수라 부릅니다. 컴퓨터에서 메모리에 '일정한 공간 만큼을 할당하라'라고 명령을 내리는 역할을 합니다. 그리고 위에서 본 것처럼, 각 데이터형에 따라 얼마만큼의 비트를 할당할지 결정하게 됩니다. a라는 변수는 32비트만큼의 메모리를 차지하고 있습니다. 마치 우리가 살고 있는 현실 세계에서 특정한 땅만큼을 배정해주고, a씨네 집이라고 이름 짓는 것과 같습니다. 

 

   실제 주소는 서울시 코딩서로 200번 길 32처럼 있지만, a씨네 집이라고 별칭을 지어주는 것이지요. 메모리에서도 같은 일이 일어납니다. a라는 변수에는 메모리 주소가 저장되며, a라는 별칭을 통해 이 메모리에 접근하자 라고 약속을 해두는 것입니다. C#에서는 메모리에 대해 크게 신경 쓰지 않아도 되도록 가비지 컬렉터가 존재합니다. 이 부분은 다시 나중에 이야기하도록 하겠습니다. 다만 변수를 선언하면 메모리에 올라가며, 메모리에 직접적으로 접근하는 것은 불가능하며, 변수라는 메모리 주소의 별칭을 통해 접근한다 정도로 이해하시면 되겠습니다.

그림으로 그려보자면 이러한 느낌입니다. 

int a = 10; int라는 데이터 형을 가진 a라는 변수에는 10이 저장되어 있다. 그리고 그 주소는 1000이다. int는 32비트이지만 바이트로 표현하면 4바이트이다. 그래서 주소지도 4씩 증가하는 형태로 표현되어 있다! 

 

※ 변수는 메모리에서 특정한 자리를 차지하는 영역에 대한 별칭을 의미한다! 정도가 변수의 의미라 생각할 수 있겠습니다. 

 

초기 프로그래밍 언어에서는 변수를 선언한 뒤에 반드시 초기화가 필요했습니다. 초기화를 하지 않으면 '쓰레기 값'이라 불리는 임의의 아무 값이 들어가기 때문이죠. 이러한 쓰레기 값으로 인해 프로그램이 오류가 생길 가능성이 있었어서 초기에는 초기화가 필수가 되었습니다. C#에는 초기화를 하지 않으면 컴파일 수준에서 오류를 발생시킵니다. 초기화는 일반적으로 정수 값이라면 0을 넣습니다. 

 


리터럴(Literal)

리터럴이라 하면 문자 그대로의 값을 의미합니다. 실제 사전 상의 의미도 "문자 그대로의"라는 의미가 있습니다. 다음의 코드를 살펴보도록 하겠습니다.

int a = 100;

이라는 코드에서 100은 리터럴입니다. 100이라는 의미 그대로를 가지고 있기 때문입니다. 100이라는 숫자가 쓰이기 위해서는 어떤 부분에는 저장이 되어야 할 것입니다. 이러한 형태로 100이라는 문자 그대로의 의미를 가지는 진짜 숫자가 저장된 형태가 리터럴이라 부릅니다. 고등학교 수학에서는 상수라 불리던 것이 리터럴과 같은 의미를 가집니다.

 


이제 간단한 예제를 실습해보면서 변수를 사용해보도록 하겠습니다. 

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 1_000_000_000;      // 자릿수를 구분할 때 _를 사용합니다.
            float b = 3.1734F;          // F는 float를 의미하며 이러한 리터럴을 만들 때 사용
            double c = 3.1734;          // double 형태는 F를 넣지 않아도 에러가 생기지 않는다.
            string d = "안녕 나야";

            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(c);
            Console.WriteLine(d);

        }
    }

숫자를 사용할 때는 구분자인 '_'를 사용함으로써 사람이 보기 편하게 만들 수 있습니다.

1000000000 = 1_000_000_000 과 같이 쓰는 것이죠. 구분자를 어디에 둘지는 프로그래머가 정할 수 있지만, 통상적으로 3개의 자릿수 마다 구분자를 둡니다.

 

만약에 데이터형의 범위를 넘어가는 값을 대입하려고 한다면 컴파일러가 오류를 발생시킵니다. 

위에 코드에서 추가로

short e = 500000000;

을 넣게 되면 오류가 발생합니다. 

 

컴파일러가 잡지 못하는 오류에 대해서, 데이터형을 넘쳐서 데이터가 변형된 형태를 오버플로우라 부르며, 데이터형이 부족해서 생긴 변형을 언더플로우라 부릅니다. 

 

우리는 둘 중에서 오버플로우에 대한 예제만 살펴보도록 하겠습니다.

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            short a = 32767;      // short의 최댓값은 32,767
            a++;                  // 1만큼 증가시킨다.

            Console.WriteLine(a);

        }
    }
}

실제 실행하게 되면, 32767이 나오는 것이 아닌 -32768이 나오게 됩니다. 데이터가 저장할 수 있는 한계선을 넘어감으로써 우리가 원하는 값이 아닌 다른 데이터 값을 표현하게 된 것입니다. 이 부분에 대해서도 나중에 저장 구조()에 대해 살펴보고 그 다음에 설명드리도록 하겠습니다. 

 

위의 구조를 조금 더 바꿔보도록 하겠습니다. 바로 전에 배웠던 short.MaxValue를 활용해보도록 하겠습니다. 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            short a = short.MaxValue;      // short의 최댓값은 32,767
            a++;                  // 1만큼 증가시킨다.

            Console.WriteLine(a);

        }
    }
}

언더플로우까지 나오게 한다면, 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            short a = short.MaxValue;      // short의 최댓값은 32,767
            a++;                  // 1만큼 증가시킨다.

            Console.WriteLine(a);

            a = short.MinValue;
            a--;
            Console.WriteLine(a);
        }
    }
}

로 바꿔 볼 수 있습니다. 

 


실수를 담은 데이터 형 float, double, decimal

  지금까지는 거의 정수형에 대한 이야기를 해왔습니다. 그렇다면 소수를 표현하는 수단은 어떻게 표현해야 하는가? 바로 float, double, decimal 형태로 표현합니다. 세 개의 데이터 형의 차이점은 데이터를 어디까지 표현할 수 있는가 입니다. 

 

  가장 많은 수를 표현할 수 있는 것은 float < double < decimal의 순으로 정밀도가 높습니다. 정밀도는 소수점을 표현할 수 있는 선을 이야기합니다. C#은 기본적으로 double형을 장려합니다. float보다 더 많은 데이터를 차지하지만, 데이터 손실을 안고 가는 것보다는 double형을 쓰면서 얻을 데이터를 확보하자는 것이죠. 하지만 더 높은 정밀도를 가진 decimal은 너무 과도한 정밀도 일수도 있기에 기본으로 쓰이는 것은 double형을 사용합니다. 

 

  실제로 예제를 통해 정밀도가 어디까지 표현되는지에 대해 살펴보도록 하겠습니다. 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            float a = 3.1415926535_8979323846_2643383279_5028841971f;   // float형을 사용하려면 숫자 뒤에 f가 필요하다.
            double b = 3.1415926535_8979323846_2643383279_5028841971;   // 
            decimal c = 3.1415926535_8979323846_2643383279_5028841971m; // decimal형을 사용하려면 숫자 뒤에 m이 필요하다.

            Console.WriteLine(a);
            Console.WriteLine(b);
            Console.WriteLine(c);
        }
    }
}

 

입력한 수는 파이를 입력해보았습니다. 10자리 마다 구분지어서 넣어보았습니다. 실제 실행 결과를 보면 float과 double, decimal에 따라 소수점 아래에 숫자를 표현하는 정도가 다름을 확인할 수 있습니다. (정밀도가 다른 것이죠)

 


글이 길어지는 관계로 다음 포스팅으로 넘어가서 글을 이어가도록 하겠습니다! 

감사합니다.

 

  지난 시간에는 Visual Studio 2019 설치와 더불어 Hello, World!를 출력해봄으로써 대략적인 구조를 확인했습니다. 이번 시간에는 지난 시간에 했던 Hello, World!의 소스코드를 하나씩 확인하며 어떠한 내용이 존재하는지 그리고 어떤 의미를 지니는지 간략하게 살펴보도록 하겠습니다. 기억이 안나시는 분은 지난 시간 포스트를 확인해보고 오시기 바랍니다.

 

  앞으로도 이러한 방식으로 하나하나 살펴보도록 할 예정입니다. 힘들수도 있지만, 머릿속으로 어떤 의미인지 확인이 안된다면 주먹구구식의 프로그래밍이 될 수밖에 없습니다. 그러니 하나씩 정확하게 배워가도록 하겠습니다. 

 

using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

 

  우리는 이러한 코드를 작성해보았습니다. C#과 같이 고수준 언어의 특징은 마치 사람이 쓰는 말을 간결하게 풀어놓은 듯한 느낌을 받습니다. 실제로도 컴퓨터에게 명령하듯이 코드를 작성합니다. 예를 들면, '사용해라', '만약 아니라면 ~를 해라' 이러한 형태로 컴퓨터에게 명령한다는 느낌으로 코드를 작성합니다. 

using System;

  Visual Studio IDE는 우리의 눈을 편하게 만들어주는 역할을 해줍니다. 보라색으로 보이는 것은 키워드(Keyword)입니다. 키워드는 프로그래밍을 하기 위해서 컴퓨터에게 내리는 명령어라 생각하시면 됩니다. 내가 정한 말인지 아니면 사전에 약속된 말인지 구분이 되어야 겠죠? 그러한 구분을 해놓은 단어들을 Keyword(키워드)라 합니다. 

 

  위에 코드 상에서 using, namespace, class, static, void, string은 모두 다 사전에 정의된 키워드가 되는 것이죠!

 

그렇다면 using 키워드의 의미는 무엇인지 생각해보면, '사용한다' 겠죠? 무엇을 사용한다? System을 사용하겠다는 의미입니다. 마지막으로 ; (세미콜론)은 컴퓨터에게 명령어 한 줄 한 줄을 구분시켜주는 역할을 하는 구분자 역할을 해주는 칸막이 같은 역할을 합니다. 컴퓨터가 봤을 때 사람의 언어는 구분이 안되는 외계어처럼 보이게 될 것입니다. (물론 세미콜론을 없애고자 하는 움직임이 없었던 것은 아닙니다. 그런데 세미콜론을 남겨둠으로써 얻는 이점이 많다고 생각해서 세미콜론을 남겨둔 형태로 지금도 사용되고 있습니다.)

 

실제로 우리가 컴퓨터의 기계어를 보면 010001010100111101 의 형태로 보이는데, 우리는 이 말이 무슨 말인지 모릅니다. 그리고 컴퓨터는 알 수 있는 것이죠. 

 

뒤에 나오는 System은 클래스(class)를 담고 있는 네임스페이스(namespace)가 됩니다. 

 


 

네임스페이스

  네임스페이스는 특정 클래스라 하는 것이 어디에 속해 있는지 알려주는 역할을 합니다. A라는 네임스페이스에 add 클래스가 있고, B라는 네임스페이스에 add라는 같은 이름의 클래스가 있으면 이를 구분지어주기 위한 역할을 하는 것이 네임스페이스가 됩니다. 

 

  예를 들어, A네 자전거, B네 자전거, C네 자전거라 하면 이를 구분지어주는 역할을 하는 것이 네임스페이스가 되는 것이죠. A씨 네 자전거입니다! B씨 네 자전거입니다. C씨 네 자전거입니다. 이렇게 소속을 구분지어주는 역할을 합니다.

 

  왜 이렇게 하냐? 그 이유는 변수이름을 짓기 어렵기 때문이죠. 그래서 프로그래머들은 비슷한 이름을 쓰게 되는데, 문제는 이름들끼리 충돌하기 시작한다는 것입니다. 위에 예에서도 " 자전거다!" 라고 지칭하면 누구네 자전거? 라는 의문이 따라오는 것처럼 어디에 속해 있는지가 중요한 문제이기 때문이죠. (물론 더 다양한 문제를 해결하기 위해서 도입했지만, 대략적인 이유는 이렇습니다.)

 

그렇다면 다시 돌아와서

using System;

기존에 보았던 이 코드에서 System은 System으로 되어 있는 네이스페이스에 있는 것들을 쓰겠다는 소리가 되는 거겟죠?

 

그렇다면 이렇게 다양한 네임스페이스를 외워야 하냐? 그건 아닙니다. 기본적으로 우리에게는 찾아볼 수 있도록 준비된 사전이 있습니다.

 

docs.microsoft.com/ko-kr/dotnet/api/system?view=net-5.0

 

System 네임스페이스

일반적으로 사용되는 값과 참조 데이터 형식, 이벤트와 이벤트 처리기, 인터페이스, 특성, 예외 처리 등을 정의하는 핵심 클래스 및 기본 클래스가 포함되어 있습니다. Contains fundamental classes and b

docs.microsoft.com

우리가 궁금한 내용이 있을 때마다 Docs를 찾아보면서 쓰면 됩니다. 일단은 이러한 것이 있구나 정도로 생각하면 됩니다. 

 

위의 코드에서 using System;을 빼면

 

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine("Hello World!");
        }
    }
}

 코드가 조금 더 길어집니다. 네임스페이스를 사용하면 길어지는 현상도 줄일 수 있는 장점이 있죠.


using System;

namespace MyFirstApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

 자 다시 코드로 돌아와서 생각해보도록 하겠습니다.

이제 다음은

namespace MyFirstApp

이 부분은 이제 이해하기 쉽습니다. namespace는 소속을 정해주는 것이죠. 마찬가지로 앞으로 만들 클래스는 MyFirstApp 이라는 네임스페이스에 속하게 만들겠다는 것입니다. 

 

using System;

namespace MyFirstApp
{ 이 부분부터 들어가는 곳은 MyFirstApp의 네임스페이스에 속해있는 것입니다.
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

 

그 다음으로 

 

Class

class Program

  class란 기본적인 객체를 정의하는 하나의 틀을 의미합니다. 객체는 나중에 이야기하겠지만, 우리가 세상을 바라보는 물체를 객체라 부릅니다. 물론 물체 뿐 아니라 무형의 형태도 객체로 바라볼 수 있습니다. 객체지향에 대한 이야기는 이야기하면 이야기할 수록 많은 이야기가 필요하니 이후에 다시 이야기하도록 하겠습니다. 

 

  클래스는 이러한 기본이 되는 형태를 class라 부릅니다. 여기에는 변수메소드라 불리는 것이 정의되는 공간입니다. 클래스는 한 개만 존재할 수도 있고, 여러개가 존재할 수도 있습니다. 

 

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }

class Program 안에는 Main 이 있습니다. Main은 모든 프로그램이 흘러가는 중심이 되는 곳이라고 생각하시면 됩니다. 그래서 Main은 한 개만 있어야 하며, 두 개 이상이 되면 프로그램에서 오류가 발생합니다. 

 

Main은 실제로 프로그램이 실행되는 공간이며, 그 외에 메소드(함수)는 Main에서 불러주어야 실행이 됩니다.

 

static(정적) : static이 선언되어 있으면, 프로그램 시작시에 해당 속성이 붙어있는 클래스가 메모리에 올라가게 됩니다. 프로그램 시작과 함께 초기화되며, 메모리에 처음부터 올라가있는 상태가 됩니다. 더 자세한 이야기는 나중에 하도록 하겠습니다. 

 

  void는 자료형을 의미합니다. 컴퓨터는 자료형을 지정해줘야 합니다. 예를 들어, 12와 "12"를 보고 사람은 같은 숫자 12를 생각하지만, 컴퓨터는 이를 보고 다르게 생각합니다. 12는 숫자 12이며, "12"는 문자 12로 인식합니다. 그래서 프로그래머는 명시적으로 컴퓨터에게 어떤 자료형임을 알려주어야 합니다. 그래서 여러 자료형이 주어져 있습니다. 예를 들어, int, char, string등등 이 존재합니다. 

 

  class는 일반적으로 돌려주는 return 값이 있을 수 있습니다. 메인에서 프로그램이 실행될 때, 다양한 class를 지속적으로 호출하게 됩니다. 그러면 다른 class에 갔다가 다시 메인으로 돌와서 프로그램을 실행해야 합니다. 이러한 상황에서 다시 돌아올 때, 값을 가지고 오는 class가 있는 반면, 가지고 오는 값이 없는 class가 있습니다. 이 중에서 가지고 돌아오는 값이 없는 class에서 사용되는 것을 void라 합니다. 가지고 돌려주는 값이 정수형이면 int를 붙여서 사용합니다. (이러한 부분은 뒤에 다시 설명하도록 하겠습니다.)

 

대략적으로 설명하자면 이러한 형태가 됩니다.

  우리가 아직 많은 부분을 배우지 않아서 정확한 설명은 아니지만 대략적으로 이러한 느낌으로 흘러갑니다. Main이라는 프로그램의 큰 흐름에서 필요한 Class를 호출하고 흐름이 잠시간 넘어가는 형태로 프로그램이 진행됩니다. 이럴 때 void는 넘겨주는 값이 없는 형태이며, int는 정수를 넘겨주며, float은 실수값을 넘겨주는 것이죠. 무엇을 넘겨주는 지에 대해 알려주는 역할을 한다고 보시면 됩니다.


마지막으로 

Console.WriteLine("Hello, World!");

앞서 이야기한 Class에 대해 흐름이 넘어간다고 했죠? 여기서도 System이라는 네임스페이스에 있는 Console Class에 있는 WriteLine이라 불리는 메소드를 통해서 우리는 "Hello, World"의 문자열을 출력해줍니다. 

 

그리고 WriteLine은  출력이 끝난 후에 다음줄로 넘어갑니다. (Enter를 누르는 효과가 나옵니다.)

만약 줄 바꿈을 하고 싶지 않다면, Write라고 사용하면 됩니다.

Console.Write("Hello, World");

한번 써보신다음에 출력을 해보세요!

 


아직 static void Main(string[] args) 에서 string[] args는 이야기하지 않았습니다. 하지만 이는 나중에 이야기하도록 하겠습니다. 뒤에서 배울 내용을 먼저 배운 다음에야 이해가 됩니다. 일단은 이러한 구조를 갖는구나 생각을 하시면 됩니다. 

 

마지막 과제를 드리면서 이번 장을 마무리 짓도록 하겠습니다.

 

#1. 

안녕하세요. 저는 * * 입니다.
앞으로 우리의 프로그랭을 재밋게 해보도록 하겠습니다.
다음에 뵙겠습니다!

 

#2. 

이 줄은 첫번째 줄 입니다.

이 줄은 세번째 줄 입니다.

이 줄은 다섯번째 줄 입니다.

이 문제에 대한 답은 다음 시간에 올리도록 하겠습니다. 감사합니다.

 

 

  우리가 사용할 IDE는 Visual Studio를 활용해서 C#을 배워보도록 할 예정입니다. IDE를 없이도 충분히 사용할 수도 있지만, IDE가 가지는 편안함을 이용하기 위해서 IDE를 사용할 예정입니다. 아직은 어떤 것도 모르르는 상태이기 때문에 하나하나 따라오시면서 익혀보는 것에 관점을 두고 시작하시기 바랍니다. 

 

  Visual Studio는 마이크로소프트에서 만든 IDE로 전문가용(Professinal)을 사용하고자 한다면, 일정 금액을 내고 사용해야 합니다. 하지만 우리는 엄청난 기능까지는 필요없으므로 Community(커뮤니티)버전이면 충분합니다. 

 

링크를 타고 들어가서 다운로드를 받아보도록 합시다. visualstudio.microsoft.com/ko/downloads/

 

Windows 및 Mac용 Visual Studio 2019 다운로드

Visual Studio Community, Professional, Enterprise를 다운로드하세요. 지금 Visual Studio IDE, Code 또는 Mac을 무료로 사용해 보세요.

visualstudio.microsoft.com

* 링크가 안나올 경우, 구글에 'Visual studio 다운로드'를 타이핑 하면 다운로드 받을 수 있는 링크가 준비되어 있습니다. [잘 모르겠다 싶으시면 물어보세요!]

 

다운로드를 해주도록 합시다.

혹은 아래로 들어가서 다운로드 -> Community 2019로 다운로드 하셔도 됩니다.

visualstudio.microsoft.com/ko/vs/

 

Visual Studio 2019 | 무료 다운로드

Visual Studio에서 코드 완성, 디버깅, 테스트, Git 관리, 클라우드 배포를 사용하여 코드를 작성할 수 있습니다. 지금 Community를 무료로 다운로드하세요.

visualstudio.microsoft.com

 

  다운로드를 하는 동안 아래쪽으로 내려가면 Visual Studio Code가 있습니다. Visual Studio Code도 강력한 IDE 중 하나입니다. 필자는 Code를 더 많이 사용합니다. 하지만 Code는 완전 초보자가 처음부터 쓰기에는 너무 힘듭니다. 하나부터 열까지 자신이 커스터마이징을 할 수 있다는 점이 장점이지만, 초보자에게 너무 많은 것이 주어지면 오히려 힘들어지죠? 그래서 일단은 다른 셋팅 없이도 할 수 있는 Visual Studio Community 2019로 시작하도록 합시다! IDE는 우리의 프로그래밍을 도와주는 '수단'임을 잊으시면 안됩니다. 

 


다운로드가 완료되면 바로 실행시켜 주도록 합시다. 

실행시키면 어떤 용도로 작업할지에 대해 묻습니다. 그러면 우리가 .NET 데스크톱 개발이 우리가 하려는 C#을 만들 수 있는 것이 들어있는 패키지입니다. 

 .NET 데스크톱 개발을 체크표시하고 '설치'를 눌러주시면 됩니다. 생각보다 시간이 필요합니다. 설치 완료 이후에는 딱히 필요한 부분이 없습니다. 사용하는데는 로그인도 필요없지만, 차후 로그인하지 않고는 사용기간이 정해짐니다. 그래서 로그인을 해주고 넘어가면 편합니다. (나중에 하셔도 상관없습니다.)

 

완료하고 나면 이러한 화면이 나옵니다. 

 

새 프로젝트 만들기를 눌러줍니다. 

 

먼저, 프로그래밍 언어를 C#으로 바꾼다음 -> Console Application -> 다음 을 눌러줍니다. 

 

이 화면에서의 구성은 총 3가지 입니다. 

  • 하나는 프로젝트 이름
  • 두번째는 위치, 위치는 이 프로젝트를 저장할 위치를 선정해주는 것 입니다. 저장하고 싶은 위치를 선정해주시면 됩니다. 저는 C:\Users\one-math\Desktop\Test\ 에 저장을 하기 위해 지정해주었습니다. (저장하고자 하는 폴더에 넣으면 됩니다.)
  • 솔루션 이름

마이크로소프트의 비주얼 스튜디오는 프로젝트와 솔루션이라는 특별한 구조를 갖습니다. 이는 프로젝트 시에 관리를 용이하게 해줍니다. 

  • 솔루션 : 솔루션은 여러 프로젝트를 관리하기 위해 있는 하나의 큰 컨테이너입니다. 프로젝트와 프로젝트를 연결할 수 있는 연결 고리를 만들어주는 역할을 하는 것이지요.
  • 프로젝트 : 현재는 1개의 파일만을 가지고 실습을 진행하겠지만, 개발의 규모가 커지게 되면 파일의 갯수도 늘어나게 됩니다. 그래서 여러 소스 파일과 파생되는 여러 파일을 묶어서 관리하기 위한 것이 프로젝트입니다.

프로젝트는 여러 소스파일과 파생되는 파일을 묶어서 관리하는 개념, 이러한 프로젝트가 많아졌을 때, 이를 묶어서 관리하는 솔루션이라는 개념이라 생각하시면 됩니다. 

이러한 형태가 나오게 됩니다. 실제로 저장된 폴더에 들어가서 확인해보면,

이러한 형태로 생성이 됩니다. 확장자가 sln은 솔루션 파일, 확장자가 csproj이면 C-sharp-Project 파일이 됩니다.

 

우리가 사용하는 프레임워크는 .NET 5.0을 사용할 예정이니 .NET 5.0인지 확인하고 만들기를 누르면 됩니다. 

 

성공했다면, 이러한 화면이 나오게 됩니다. 

 


 

화면구성

기본적인 화면 구성은 코드 편집기, 솔루션 탐색기, 콘솔로 이루어져 있으며, 처음에는 3가지만 기억하고 계시면 됩니다. 

  • 코드 편집기 : 실제로 코드를 작업하는 공간이며, 코드를 작성할 공간입니다. 
  • 솔루션 탐색기 : 우리가 작업하고 있는 소스 파일과 그에 따른 종속성 프로젝트에 대해 전반적으로 보여주는 공간입니다. 기본적인 프로그램 흐름을 배울 때는 필요없지만, 나중에 규모가 큰 프로그램을 만들게 되면 자주 사용하는 공간이기도 합니다.
  • 콘솔 : 시스템 메시지가 나오는 공간으로 에러가 생기면 알려줍니다. 

이제 설치에서 프로젝트 생성까지 완료했으니, 실행을 한번 해보도록 하겠습니다. 

실행에는 두 가지 방법이 있습니다. 빌드에 의한 실행, 혹은 디버그에 의한 실행으로 두 가지가 있습니다. 빌드에 의한 방법은 실행 시키기 위해서는 조금 더 복잡하기 때문에 당분간은 디버그에 의한 실행을 사용하도록 하겠습니다.

 

 

실행

상단 메뉴에서 디버그 -> 디버그하지 않고 시작을 눌러줍니다. 혹은 Ctrl + F5를 누르시면 됩니다. 

그러면 

 

이러한 화면이 나옵니다. "Hello World!"를 확인할 수 있습니다. 

 


Hello, World의 유래

  문득 모든 프로그래밍의 시작은 Hello, World로 시작하는데, 그 이유가 궁금하지 않나요? Hello, World는 Brian W.Kernighan(브라이언 커닝헨)과 Dennis M.Richie(데니스 리치)가 쓴 저서인 "The C Programming Language"의 교재에서 첫 번째 예제가 Hello, World를 출력하는 것이었습니다. C언와 함께 유명해지면서 대부분의 프로그래밍 언어에서 첫 번째 예제로 Hello, World!를 사용하는 것이 관행처럼 굳어진 것이죠.

 

  단순히 Hello, World자체가 중요한 것은 아니고, 첫 예제를 실제로 하나하나 따라하다 보면 전반적인 프로그래밍 코드를 실행시키는 구조가 눈에 들어오기 때문에 이러한 코드를 직접 쳐보는 것이지요. 여기서 우리가 얻어야 하는 것은 한번을 직접 실행시켜보는 것이 여러번 책을 들여다 보는 것보다 중요한 점입니다. 

 

  꼭 프로그래밍을 배우실 때는 힘들더라도 직접 하나씩 만져보는 것을 추천드립니다. 

* 28가지의 다른 Hello, World!를 아래에서 확인할 수 있습니다.

excelwithbusiness.com/blog/say-hello-world-in-28-different-programming-languages/


  설치부터 시작해서 Hello World를 실행해보면서 기본적인 실행의 흐름을 따라가 보았습니다. 우리가 생각하는 것보다 프로그래밍은 복잡할순 있지만, 생각보다 그리 복잡하진 않습니다. 우리가 항상 하는 게임과 배우는 수준은 같습니다. 처음에는 하나하나 해보다 보면 어느덧 성장해 있는 우리의 모습을 확인할 수 있습니다. 하루에 하나만 배우자는 마음으로 하나씩 배워가길 바라겠습니다. 

 

  저도 항상 한번에 많은 것을 하려고 했습니다. 그러다보니 마음은 조급한데 생각보다 늘어나는 실력은 너무 작다보니 포기하는 일이 많았습니다. 우리는 분명 오늘을 달리고 있습니다. 어제보다 나은 내가 되었으며, 앞으로 조금씩 나아가면 6개월, 1년 이란 시간이 지나면 멀리 나아가 있는 우리의 모습을 볼 수 있습니다. 그러니 너무 조급해하지 마시고 '하루에 한개는 내가 꼭 알아내겠다.' 라는 목표로 꾸준히 나아가시기 바랍니다. 

 

  저는 프로그래밍을 어렵게하는 이유는 '꾸준함'이라 생각합니다. 프로그래밍은 언제나 거대한 문제를 조그만한 문제로 쪼개서 내가 먹을 수 있게 만드는데 의의가 있습니다. 하지만 하루 이틀로는 이렇게 거대한 문제를 여러번 베어먹는다고 해서 의미가 없죠. 하지만 이러한 날이 하루, 이틀이 모이면 거대한 산 같은 덩어리를 쪼개서 내가 베어 먹을 수 있게 됩니다. 

  C#(씨샵이라 말합니다.) C#은 C라고 이름붙어진 형제에서 마지막으로 나온 언어 중 하나입니다. C# 외에도 C언어, C++(씨플플이라 읽습니다.)가 앞에 존재하지만 업그레이드의 버전은 아닙니다. (어떤 의미로는 업그레이드라고도 볼 수 있지만 엄밀히 다른 부류의 언어이지 업그레이드 된 언어라 보기는 힘듭니다.) 

 

 이러한 C#은 객체지향적 언어이며, 개발자가 사용하기 쉽게끔 나왔습니다. 여러가지 특성이 존재하지만 초보자의 관점에서는 대략 이러한 느낌입니다. 프로그래밍을 접하는데 C#은 어떤가요? 라고 했을 때, C#은 충분히 처음에 배우기 편한 언어임은 분명합니다. (Python과 마찬가지로 강력한 언어이죠.) 문법적 특성은 C언어가 더 적고 사용하기 편할지 몰라도 실제로 메모리 관리나 프로그래머에게 많은 자유를 준 만큼 C언어는 프로그래머가 고려해야할 사항이 많아지는 단점이 있죠. 게다가 C언어로 100줄을 작성해야할 코드가 C#이나 파이썬으로 넘어가면 작성해야할 코드가 20줄로 끝날 정도로 간편해지기도 했습니다. (물론 상황에 따라 다르겠지만, C언어 보다 C#, 파이썬이 사람의 언어(자연어)에 가깝기 때문에 작성하기가 더욱 편리합니다.)

 

  C#을 사용하는 IDE는 여러 가지가 있지만, 대표적으로 Visual Studio와 MonoDevelop 등이 있습니다. 물론 이외에도 다양한 C#을 지원하는 IDE가 존재합니다. 앞으로의 포스팅에서는 Visual Studio를 통해 진행할 예정이지만, 설치가 힘든 분들은 웹에서 제공하는 컴파일러를 사용하셔도 괜찮습니다. 충분히 우리의 실습을 커버할 수 있습니다. OnlineGDB

 

Online C# Compiler - online editor

OnlineGDB is online IDE with C# compiler. Quick and easy way to run C# program online.

www.onlinegdb.com

 

C#에 대략적인 이야기는 이 정도만 알고 넘아가셔도 충분합니다. 다만 밑에 적혀질 이야기는 C#에 대해 조금 더 생각해보자란 의미에서 더 적어두도록 하겠습니다. 

 

1. C#


 C#이라는 이름의 유래는 C++에서 C++++ 네 개의 +를 2개씩 쌓아 올리면 # 모양이 되기 때문에 C#으로 만들어졌다.  Java는 JVM(자바 가상머신)을 활용해 어떤 플랫폼에 상관없이 사용할 수 있는 장점을 필두로 생산성 향상을 도모했다. 한번 작성하고 어디서든 사용할 수 있도록 하는 것이 큰 장점으로 다가왔다. 그래서 C# 또한 이러한 양상을 따라가기 위해 만들어졌다. 그래서 Java에서 JVM(자바 가상머신)이 필요했듯, C#은 닷넷 프레임 워크가 필요하다. (정확히는 Java를 MS에서 만들어낼 때, J#이라 만들어냈는데, 저작권 문제로 C/C++, Java의 장점을 모아서 C#으로 다시 출시하게 되었다.)

 

  그렇다면 C#, Java가 무조건 더 좋은가? 라는 질문에는 그렇다고 볼 수도 있고 아니라고 볼 수도 있다. 초기 C#, Java는 성능면에서 불리한 점이 너무나도 많았다. 물론 이는 지금도 비슷하다. C/C++ 이 더 빠른건 설계상 차이점이 생길 수 밖에 없다. 태생적 한계가 분명히 존재한다. 가상 머신을 넣는 순간 느리지는건 어쩔 수 없다. 가상머신이 없는 C/C++은 C#, Java보다는 당연히 빠르다. 하지만 가상머신이 없으므로 윈도우에서 만들어진 것을 다른 운영체제에서 사용할 수 없다. 그래서 이를 바꿔주는 작업을 해야 한다. Java는 이럴 필요가 없는 것이다. 또한 메모리 관리 측면과 자연어에 가까운 언어가 사람이 쓰기 편한 언어이다. Java와 C#은 사람이 쓰기 조금 더 편하다.

 

  그럼에도 불구하고 프로그램 언어의 인기 순에는 항상 C/C++를 빼놓고 이야기할 수 없다. 이는 하드웨어를 컨트롤할 수 있는 언어는 결국 C언어이며, C++은 메모리 관리를 직접할 수 있다는 장점이 있다. 그래서 여전히 사라지지 않고 큰 인기를 누리고 있다. (리눅스의 기반 언어는 C로 이루어져 있으므로 이를 다루기 위해서는 반드시 C를 할 수 밖에 없다.)

 

  초기에는 마이크로소프트 플랫폼에 귀속되어 있어서 사용도가 많이 떨어지기도 했지만, 이후에 개선을 거쳐서 업데이트를 통해 개선을 거쳐가는 중이다. 그래서 C#의 인기도 업데이트와 더불어 그 인기가 늘어가는 중이다. 유니티의 기본 개발 언어이기도 하다.

 

 

2. .NET (닷넷)


  C#은 기본적으로 닷넷에서 실행된다. Java가 JVM이라는 자바 가상 머신 위에서 돌아가는 것과 같은 형태이다. CLR(Common Language Runtime) - 공용 언어 런타임이라 하는 가상 실행 시스템이다. CLI(Common Language Infrastructure) - 공용 언어 인프라를 MS(마이크로소프트)에서 구현한 것이다. 

 

  C#으로 작성된 코드는 IL(Intermediate Language) - 중간 언어 라 불리는 것으로 컴파일 된다. (마이크로소프트에서 개발한 CLI를 준수하는 IL 언어로 컴파일된다고 보는 것이 정확할 것이다.) 그리고 CLR을 통해 기계가 읽어들일 수 있는 형태로 로드 된다. 

 

  C# 프로그램이 실행되면 어셈블리가 CLR에 로드되며, 이러한 CLR은 Just - In - Time으로 컴파일을 수행한 다. (우리나라 말로 그 때 그 때 마다) 

  이러한 CLR에서 나온 코드는 기계어로 바꾸어준다. (기계어는 기계가 해석할 수 언어로써 01010의 형태를 갖는 코드를 의미한다.) 0은 꺼짐, 1은 켜짐의 형태로 반도체를 껏다가 켯다가 할 수 있는 것이다.

  

  정리하면, C# 코드 -> 컴파일 -> CIL -> CLR -> 기계어 형태로 변형해주는 것이다. 

 

 

이것 외에도 CLR은 가비지 컬렉션(Garbage Collection) 자동 실행, 예외 처리, 리소스 관리 등 다양한 서비스를 제공한다. CLR에서 실행되는 코드는 관리 코드(Managed code)라 불린다. 

 

  닷넷의 주요 기능 중 하나는 언어의 상호 호환 가능성이다. C# 컴파일러에서 생성된 CIL 코드는 CTS - 공용 형식 사양)을 따르기 때문에 [한 마디로 표준화가 되어 있다.], C#에서 생성된 CIL 코드 자체는 F#의 .NET 버전과 Visual Basic, C++ 등 CTS(공용 형식 사양)을 따르는 언어와 상호 호환이 가능하다. 그래서 다른 언어로 작서된 것들도 CTS를 따른다면 같은 언어로 작성된 것처럼 서로 참조하며 사용이 가능한 점이 강점이다! 물론 이것 외에도 다양한 라이브러리를 포함하는 것은 당연하다. 

 

.NET 코어에 대해 더 자세한 이야기가 궁금하다면 .NET GitHub을 방문하도록 하자!

.NET은 Winodw, macOS, Linux, RHEL, Tizen (대표적으로 갤럭시 워치 OS) 등을 지원한다. 더 많은 지원이 있지만 이 글에서는 대략 이 정도로 정리하겠다.

 

.NET 언어는 다양한 기능을 지원하는데 

 

  • Type Safety (타입 안정성)
  • Type inference - C#, F#, Visual Basic (
  • Generic Types (제네릭 형식)
  • Delegates (대리자 - C언어나 C++에서 포인터 같은 기능)
  • Lambdas (람다)
  • Events (이벤트)
  • Exceptions (예외)
  • Attributes (특성)
  • Asynchronous code ( 비동기 코드)
  • Parallel Programming (병렬 프로그래밍)
  • Code Analyzers (코드 분석기)

등이 있다. 더욱 자세한 내용은 C#을 배워보면서 하나씩 알아가도록 하겠다.

 

+ Recent posts