본문 바로가기

취미로 하는 게임코딩_gameCodingAsHobby/유니티와 C# 개념 정리_Concept Summary

유니티와 C# 개념 정리_003_C# 언어의 특징과 기본 구조

이 글 부터 유니티에서 사용하는 C# 문법에 대해 정리한다.

주로 유니티와 관련한 내용을 정리할 것이다.

다루지 않은 내용은 카테고리 [프로그래밍 언어]에 있는 Kotlin(코틀린) 언어와 중복되므로 생략한다.

 

C# 언어의 특징

1. Object-Oriented Programming 언어

C#의 가장 핵심적인 특징은 Object-Oriented Programming(OOP : 개체 지향 프로그래밍) 언어이다.

OOP의 대표적인 언어는 Java, Python, C++, Ruby, C# 등이 있다.

이 개념은 Java에서 파생한 Kotlin(코틀린) 언어에서 알아보았기 때문에 생략한다.(코틀린 더파기_13)

 

참고로 Object(오브젝트)는 이전에 '객체'라고 해석했는데 '개체'라고 해야 한다는 주장이 있다.

나는 그 주장이 더 설득력있게 들려서 지금부터는 Object를 개체라고 부르기로 했다.

2. Method 기반

Method(메서드; 방법) Function(펑션; 기능, 함수)와  같은 의미이다.

OOP에서는 함수를 주로 Method 라고 부른다.

OOP에서는 함수가 개체에 연결하여 사용할 수 있기 때문에 다른 이름을 만든 것 같다.

어쨌든 메서드와 함수는 같은 뜻으로 사용해도 될 듯하다.

어떤 행위를 표현하는 Method 또는 Function은 '명령들의 묶음'을 나타내며 작업을 실행하는 기능도 같다.

 

메서드라는 기능이 만들어지면서, 이전에는 순서대로 나열만 했던 명령들을 관련된 것들끼리 묶을 수 있게 되었다.

또한 한번 만들고 나서 재사용할 수 있게 되었다.

3. Strongly Typed

변수가 모든 Type(타입)의 값을 가질 수 있도록 설계된 언어는 weakly typed(약한 타입화)를 가졌다고 한다.

반면에 C# , Java 같은 언어는 변수를 만들 때 어떤 타입으로 할 지 지정해야 하며, 이것을 Strongly typed(강한 타입화)를 가졌다고 부른다.

4. Compiled 언어

컴퓨터에게 명령을 내릴 수 있는 언어는 크게 2가지로 나눌 수 있다.

이진수(0, 1)만 사용하는 '기계어(machine language; 기계 언어)'

'사람이 읽을 수 있는 언어(authoring language; 저작 언어)'로 나눌 수 있다.

 

기계어는 컴퓨터의 두뇌인 CPU에게 직접 명령을 내릴 수 있다.

컴퓨터가 이진수 원리로 만들어졌기 때문에 당연하다.

컴퓨터가 만들어진 초창기에는 기계어를 사용했는데 힘들고 불편해서 사람이 읽을 수 있는 언어가 만들어진 것이다.

 

사람이 읽을 수 있는 언어는 작동하는 방식에 따라 Compiled(컴파일)와 Interpreted(인터프리터)로 나눌 수 있다.

둘 다 작성한 코드를 기계어로 번역하는(바꿔주는) 기능은 같은데, 간단히 말하면 모아서 한방에 하느냐(Compiled), 한 줄씩 하느냐(Interpreted)의 차이가 있다.

 

컴파일 방식은 Basic, C++, C#, Java 등이 있고,

인터프리터 방식은 Python, PHP, JavaScript 등이 있다.

5. Managed 

컴파일 방식의 언어들 중에서 초창기에 만들어진 Basic, C, C++ 등은 기계어로 직접 컴파일하는데 이런 형태를 Unmanaged(관리하지 않는) 컴파일 방식이라고 한다.

 

이후에 만들어진 C#, Java 등은 기계어로 바로 컴파일 하지 않고 CLR(공용 언어 런타임), Java는 JVM(자바 가상 머신)을 거쳐서 실행한다.

이런 형태를 Managed(관리하는) 컴파일 방식이라고 한다.

이렇게 만든 이유는 당연히 편리함 또는 효율성을 위해서이다.

 

여기까지 C#의 특징을 몇 가지 알아보았다.

이 중에서 특징 1, 2, 3은 꼭 기억해야 할 내용이다.

 

C#의 기본 구조

개체지향 프로그래밍(OOP)의 핵심은 class(클래스)이다.

 

이전 글에서 작성했던 내용을 약간 수정하여 클래스가 중심이 되는 OOP의 기본 구조를 나타낼 수 있다.

아래 코드에 기본 구조의 핵심이 모두 담겨있다.

그 외의 기능들은 프로그램을 더 편리하고 효율적으로 작성하기 위해 추가하고 확장한 개념들인것 같다.

위 코드는 콘솔창에 "Hello World!" 라는 글귀를 출력하기 위한 목적으로 작성한 것이다.

간단하게 설명하면 다음과 같다.

빠진 부분은 나중에 정리하기로 하고 여기서는 C#의 기본 구조가 어떻게 이루어지는지만 이해하면 된다.

 

5번줄에 class(클래스)를 만들었다.

클래스 다음에 한칸 띄우고 클래스 이름은 MyClass라고 지었다.

여기서는 편의상 MyClass라고 지었지만 실제로는 클래스의 역할이나 기능을 더 잘 알 수 있도록 이름을 지어야 한다.

 

클래스 내용은 6번, 19번 줄과 같이 중괄호( { } )를 사용하여 클래스 전체를 묶는다.

즉, 7번줄에서 18번 줄까지의 내용이 MyClass라는 클래스의 내용물이며,

이것을 class member(클래스 멤버)라고 부른다.

 

클래스 멤버는 클래스 안에서 선언한 변수와 메서드를 말한다.

변수 데이터를 저장하는데 사용하고 메서드 행위(Behaviour ; ~하다)를 규정한다.

 

클래스 안에서 처음 위치인 7번 줄에 글을 저장하기 위해 string 타입의 변수를 정의하고 변수 이름은 myVariable이라고 지었다. 변수명 역시 마음대로 지을 수 있지만 나중에 보아도 무엇인지 알 수 있도록 자~알 짓는 것이 좋다.

처음에는 고수들이 어떻게 이름을 지었는 지 관찰하고 똑같이 만들다가, 숙달되면 자신만의 규칙을 정해서 이름 짓는 것이 좋을 듯하다.

 

프로그래밍에서는 문자 2개 이상의 글 String(스트링; 문자열)이라고 부른다.

이제 이 변수에는 문자열만 저장할 수 있다.

왜냐하면 string이라는 타입만 가능하다고 못을 박아 두었기 때문이다.

변수 정의가 끝나면 마지막에 세미콜론( ; )을 붙여서 명령이 끝났다는 것을 표시해야 한다.

Kotlin에는 종료 표시가 없는데 처음 C# 코드 작성할 때 이 기호를 제일 많이 빼먹었다.

 

이제 문자열을 출력하라는 명령이 필요하다.

출력과 관련된 명령들은 메서드(함수)를 만들어서 그 안에 정리한다.

14번 줄에 MyMethod라는 이름으로 메서드를 만들었다.

메서드는 메서드명 다음에 ( ) 괄호를 가지고 있다.

메서드는 클래스와 마찬가지로 중괄호( { } )를 사용해서 내용을 묶는다.

 

16번 줄에 앞에서 만든(선언한) 변수에 출력할 문자열(Hello World!)를 저장한다.

여기서 저장한다는 말은 assign(할당하다, 배정하다)이 더 정확한 표현이다.

 

17번 줄에 Console.WriteLine( ) 메서드를 사용해서 변수 이름을 전달한다.

Console.WriteLine( ) 메서드는 문자열 출력할 때 사용하라고 C#에서 미리 만들어 놓은 메서드이다.

이렇게 해서 원하는 문자열을 출력하는 행위를 할 수 있는 MyMethod라는 메서드를 완성했다.

 

이렇게 만든 MyMethod() 메서드를 실행할 수 있는 곳이 8번줄의 Main( ) 메인이라는 메서드이다.

C#에는 프로그램이 실행되면 제일 먼저 Main( )메서드를 찾아서 호출(call)하여 실행하도록 미리 코드가 작성되어 있다.

이 메서드를 프로그램의 The Entry Point(시작점, 출발점)이라고 부른다.

코틀린 글에서 들어보았던 용어이다.

 

클래스 안에 있는 메서드를 실행하기 위해서 프로그램이 그 메서드에 접근하려면 클래스의 Object(개체)를 통해서 접근할 수 있다. 

 

MyMethod메서드는 MyClass라는 클래스 안에 있기 때문에 클래스 개체를 만들기 위해서 

10번 줄에 MyClass 타입의 myClass라는 이름의 변수를 만든다.(MyClass myClass)

앞에서 변수의 타입으로 미리 정해져 있는 string 이라는 타입이 있는 반면에,

필요에 따라 MyClass처럼 내가 지정하는 타입을 만들수 도 있다.

 

그리고 변수(myClass)에 new 키워드를 사용해서 클래스 개체(인스턴스)를 만들어 저장(할당)한다. ( = new MyClass( ) )

클래스 개체(인스턴스)를 생성할 때는 new 다음에 클래스 이름을 붙이고 괄호( )를 붙인다. 

앞에서도 보았듯이 괄호( )는 변수 등을 전달하는 용도로 사용한다.

 

2021년 8월 현재 C#은 버전 9.0 이다.

C#9.0에서는 10번 줄과 같이 new 클래스명( ) 을  new( )로 줄여서 표현할 수 있도록 업그레이드 되었다.

10번줄의 마지막에 // (슬래시) 2개는 '주석'을 나타내며 설명하는 메모를 적었다.

주석은 코드에 영향을 미치지 않는다.

 

이제 MyClass타입의 변수에 클래스 개체를 생성해서 저장했다.

더 정확하게는 myClass라는 변수는 개체를 저장하고 있는 것이 아니고 개체가 저장된 위치를 참조(reference)한다.

어쨌든 클래스의 메서드에 접근하기 위해 방금 만든 클래스 개체를 이용한다.

 

myClass.MyMethod( ) 는 myClass라는 변수가 참조하고 있는 개체(MyClass로 만든 인스턴스) 안에 있는 MyMethod( )라는 메서드를 호출하라는 뜻이다.

 

과정을 요약하면 다음과 같다.

 

  1. 프로그램이 시작되면 Main( ) 메서드를 찾아서 안에 있는 코드를 순서대로 실행한다.
  2. 클래스 개체가 만들어지고
  3. MyMethod( ) 메서드를 호출한다.
  4. 호출된 MyMethod메서드는 자신의 행위를 실행한다.
  5. 변수에 Hello World!를 넣어서 출력 메서드에 전달한다.
  6. C#에 정의되어 있는 Console.WriteLine( ) 메서드는 전달받은 변수가 가리키는 위치에 있는 내용을 불러와서 콘솔창에 출력한다.

 

Console.WriteLine( ) 를 보면

myClass.MyMethod( ) 와 구조나 형태가 비슷하다.

이미 개체가 만들어져 있다는 걸 알 수 있다.

그런데 어떻게 호출해서 사용할 수 있지?

 

WriteLine( )는 System 이라는 namespace(네임스페이스) 안에 Console(콘솔) 이라는 클래스 안에 들어있다.

MyMethod( )가 MyProgram 이라는 namespace 안에 MyClass 라는 클래스 안에 만든것과 같은 구조이다.

C#에서 미리 만들어 놓은 namespace(네임스페이스)에 접근하려면 1번 줄 처럼 using 키워드 다음에 네임스페이스 이름을 적으면 된다.

 

namespace(네임스페이스)는 간단히 말해서 class(클래스)를 정리하기 위해 만들어졌다.

예를 들어 어떤 프로그램을 만든다고 했을 때 그 안에는 많은 클래스가 만들어 진다.

또 다른 프로그램을 만들면 그 안에도 역시 많은 클래스가 만들어 진다.

 

만약 수 백, 수 천개의 프로그램들이 있다고 하면 당연히 어떤 기준에 따라 분류하고 정리할 필요가 생긴다.

윈도우즈를 사용하면서 폴더를 만들어 정리하고 관리하는 것과 같다.

위에서 사용한 Console 클래스도 .Net Core(닽넽 코어)라는 프레임워크의 System이라는 namespace 안에 들어있다.

그러므로 덩치가 큰 프로젝트를 만들 때 처럼 클래스들을 정리할 필요가 있을 때 namespace를 사용하면 된다.

 

마지막으로 궁금한 점에 대해 알아보자.

위 코드에서 Main( )메서드와 MyMethod( ) 둘 다 MyClass 안에 들어있는 메서드이다.

Main메서드에서 MyMethod 메서드를 호출(사용)하기 위해 클래스 타입의 Object(개체)를 생성한 후 호출할 수 있었다.

 

그런데 Console이라는 클래스는 내가 new 키워드로 개체를 만들지도 않았는데 어떻게 호출할 수 있었지?

그 비결은 static 이다.

static(스태틱)은 '고정된'이라는 뜻이다.

 

검색창에 C# Console로 검색하거나 C# 문서를 찾아보면 아래와 같이 static class로 정의된 것을 확인할 수 있다.

이렇게 클래스가 static으로 선언되어 있으면 인스턴스(개체)를 만들지 않고도 접근할 수 있다.

위에서 Main( )메서드에 static을 붙인 이유를 이제 알게 되었을 것이다.

프로그램의 시작점인 Main( )메서드가 어느 클래스 안에 들어있더라도 컴파일러가 즉시 호출할 수 있도록 한 것이다.

더 자세한 내용은 다음에 다루기로 한다.

 

지금까지 C# 코드가 어떻게 구성되어 있는 지 기본적인 구조를 살펴보았다.

C#은 현재 버전 9.0까지 업그레이드 되었지만,

공부해 보면 위의 OOP(개체 지향 프로그래밍)의 기본 구조 형태에서 출발하여 추가로 필요하거나 더 편리한 방법을 연구해서 계속 업그레이드 된다는 것을 알 수 있다.

 

 

끝.

Wraven...