|
|
## 닷넷 관련 키워드 정리
|
|
|
|
|
|
### .NET Framework
|
|
|
.NET Framework는 MS에서 발표한 응용 프로그램 개발 환경이다. 각종 응용 프로그램을 작성 및 실행 해주는 걸 도와줌으로써
|
|
|
개발자가 응용 프로그램의 비즈니스 코드에만 집중할 수 있게 도와준다. .NET의 계층구조는 다음과 같다.
|
|
|
.NET Framework는 MS에서 2000년 6월에 발표한 응용 프로그램 개발 환경이다.
|
|
|
각종 응용 프로그램을 작성 및 실행 해주는 걸 도와줌으로써 개발자가 응용 프로그램의 비즈니스 코드에만 집중할 수 있게 도와준다.
|
|
|
소프트웨어를 어느 곳에서나 수정 없이 쓰려면 호환성의 문제를 해결해야 한다. .NET은 다양한 운영체제에서 작동하는 호환성을 목표로 만들어졌으며,
|
|
|
웹 상의 어느 곳에서나 실행 가능한 프로그램을 작성하는 것이 .NET의 궁극적인 목표이다. 그래서 중간 언어와 JIT 컴파일러를 통해 플랫폼 독립성을 확보하고 언어의 상호 운용이 가능하다는 장점이 있지만 그와 동시에 2번의 컴파일을 거치기 때문에 속도가 떨어진다는 단점이 공존한다.
|
|
|
|
|
|
<br />
|
|
|
|
|
|
>>>
|
|
|
**JIT 컴파일러?**
|
|
|
managed code의 소스코드는 각 언어의 컴파일러에 의해서 IL코드와 실행에 필요한 정보들을 갖고 있는 메타데이터로 이루어진 managed module로 생성 된다.
|
|
|
|
|
|
이 모듈이 실행될 경우 JIT컴파일러에 의해 실행에 필요한 부분이 곧바로 Native code로 컴파일되어 실행된다. 당연히 매번 실행시마다 JIT컴파일러에 의해 컴파일되어 실행되는 것은 아니고 한번 컴파일 된 부분은 재 사용하는 등의 최적화 과정을 통해 CLR의 코드는 실행된다.
|
|
|
>>>
|
|
|
|
|
|
<br />
|
|
|
.NET의 계층구조는 다음과 같다.
|
|
|
<br />
|
|
|

|
|
|
<br />
|
|
|
이 그림을 간단히 설명하자면 .NET은 CLR + 부가 구성요소로 되어있다. CLR은 밑에서 설명할 것이고, 주요 부가 구성요소는 다음과 같다.
|
|
|
|
|
|
|
|
|
1. BCL(Base Class Library)
|
|
|
MS에서 특정 기능들을 바로 쓸 수 있게 구현해 놓은 클래스들이다.
|
|
|
MS에서 특정 기능들을 바로 쓸 수 있게 구현해 놓은 클래스들이다. 아래는 BCL에 포함된 클래스의 목록과 기능들이다.
|
|
|
* 기본 타입에 대한 정보 제공
|
|
|
* 배열, 연결리스트 , 큐 등의 컬렉션 클래스
|
|
|
* 스레드와 동기화 클래스
|
|
|
* 각종 컨트롤
|
|
|
* 파일 입출력
|
|
|
* 네트워크 프로그래밍
|
|
|
* 데이터베이스 액세스
|
|
|
2. 실행파일
|
|
|
.NET은 기본적으로 C#, VB.NET의 컴파일러를 제공하고, 각종 유틸리티 성격의 실행 파일을 포함하고 있다.
|
|
|
3. GAC(Global Assembly Cache)
|
... | ... | @@ -18,19 +38,90 @@ MS에서 특정 기능들을 바로 쓸 수 있게 구현해 놓은 클래스들 |
|
|
|
|
|
|
|
|
### CLR
|
|
|
CLR(Common Language Runtime)은 CLI 사양을 따르는 가상 머신이다. CLR은 주 기능은 다음과 같다.
|
|
|
1. IL 코드를 JIT 컴파일러를 이용해 기계어로 바꿔준다.
|
|
|
2. 가비지 콜렉터를 이용해 동적 메모리 할당 및 회수를 한다.
|
|
|
CLR(Common Language Runtime)은 CLI 사양을 따르는 가상 머신이다. CLT가 하는 일은 다음과 같다.
|
|
|
1. IL 코드를 기계어로 컴파일
|
|
|
2. 동적 메모리 관리
|
|
|
3. 보안
|
|
|
4. 예외처리
|
|
|
등의 일을 한다.
|
|
|
|
|
|
여기서 가장 주 된 업무인 1번과 2번이다.
|
|
|
|
|
|
1번 업무인 IL 코드를 기계어로 컴파일하는 것은 CLR 내의 JIT(Just In Time) 컴파일러가 담당한다. CLR과 CLS의 존재로 인해서 .NET 호환 언어에 한해서 언어의 종류에 구애받지 않고 .NET Framework를 기반으로 작동하는 프로그램을 만들 수 있다.
|
|
|
<br />
|
|
|
2번 업무인 동적 메모리 관리는 가비지 컬렉터가 담당한다. C 또는 C++로 프로그래밍을 하다보면 메모리 관리때문에 복잡한 경우가 많은데, C#에서는 가비지 컬렉터가 메모리 관리를 대신해주기 때문에 편하게 프로그래밍을 할 수 있다.
|
|
|
하지만 이 가비지 컬렉터 또한 CPU와 메모리를 사용하기 때문에 가비지 컬렉터가 최소한으로 자원을 사용하게 한다면 프로그램의 성능을 높일 수 있다.
|
|
|
가비지 컬렉터의 메커니즘을 파악하면 프로그래밍을 할때의 코딩지침을 세울 수 있다.
|
|
|
<br />
|
|
|
**가비지 컬렉터의 작동 메커니즘**
|
|
|
C#으로 작성한 프로그램을 실행하면 CLR은 프로그램을 위한 일정 크기의 메모리를 확보한다. C-runtime 처럼 메모리를 쪼개는 일을 하지 않고 그냥 일정 메모리 공간을 확보해서 하나의 관리되는 힙(Managed Heap)을 마련한다.
|
|
|
객체를 할당하게 되면 메모리에 순서대로 할당하게 된다.
|
|
|
|
|
|
참조 형식의 객체가 할당될 때는 스택 영역에는 힙의 메모리 주소를, 힙 영역에 실제 값이 할당된다.
|
|
|
그럼 객체가 할당된 코드블록이 끝나면 스택 영역의 메모리가 회수되고, 힙 영역의 값을 참조하던 객체가 사라졌으므로 그 값은 쓰레기가 된다.
|
|
|
여기서 회수된 스택의 객체를 루트(Root) 라고 부른다.
|
|
|
.NET 응용 프로그램이 실행되면 JIT 컴파일러가 이 루트들을 목록으로 만들고 CLR은 이 루트 목록을 관리하며 상태를 갱신하게 된다.
|
|
|
방법은 다음과 같다.
|
|
|
|
|
|
>>>
|
|
|
가비지 컬렉터는 힙영역의 임계치에 다다르게 되면
|
|
|
1. 모든 객체가 쓰레기라고 가정한다.( 루트 목록 내의 어떤 루트도 메모리를 가리키지 않는다고 가정 )
|
|
|
2. 루트 목록을 순회하면서 참조하고 있는 힙 객체와의 관계 여부를 조사한다. 즉 어떤 루트와도 관계가 없는 힙의 객체들은 쓰레기로 간주된다.
|
|
|
3. 쓰레기가 차지하고 있던 메모리가 회수되면, 인접 객체들을 이동시켜 차곡차곡 채워서 정리한다.
|
|
|
>>>
|
|
|
|
|
|
CLR의 메모리도 구역을 나누어 메모리에서 빨리 해제될 객체와 오래 있을 것 같은 객체를 따로 담아 관리한다.
|
|
|
구체적으로 CLR은 메모리를 0세대, 1세대, 2세대 3가지로 분리하고, 0세대는 빨리 사라질 객체, 2세대는 오래 남아있을 것 같은 객체들을 위치시킨다.
|
|
|
그 방법은 다음과 같다.
|
|
|
|
|
|
>>>
|
|
|
응용 프로그램을 실행하면 0세대부터 할당된 객체들이 차오르기 시작한다.
|
|
|
1. 0세대 가비지 컬렉션 임계치에 도달하면 0세대에 대해 가비지 컬렉션을 수행한다. 여기서 살아남은 객체는 1세대로 옮겨진다.
|
|
|
2. 1번 과정을 계속 반복하다보면, 1세대 가비지 컬렉션이 임계치에 도달하게 되고, 1세대에 대해 가비지 컬렉션을 수행한다. 여기서 살아남은 객체는 다시 2세대로 옮겨진다.
|
|
|
3. 2번 과정도 지속되다보면 2세대 가비지 컬렉션이 임계치에 도달한다.
|
|
|
2세대 가비지컬렉션이 임계치에 도달하면 0,1,2 세대 전체 가비지컬렉션(Full Garbage Collection) 을 수행한다.
|
|
|
>>>
|
|
|
|
|
|
<br />
|
|
|
|
|
|
프로그램이 오래 살아남는 객체들을 마구 생성하면, 2세대 힙이 가득차게 될 것이다.
|
|
|
2세대 힙이 가득차게 되면 CLR은 응용프로그램의 실행을 멈추고 전체 가비지 컬렉션을 수행하면서 메모리를 확보하려 하기 때문에 응용 프로그램이 차지하는 메모리가 많을 수록 프로그램이 정지하는 시간도 그만큼 늘어나게 된다.
|
|
|
|
|
|
<br />
|
|
|
|
|
|
**코딩지침**
|
|
|
가비지 컬렉터의 메커니즘을 바탕으로 효율적인 코드를 작성하기 위한 방법이 있다.
|
|
|
|
|
|
>>>
|
|
|
- 객체를 너무 많이 할당하지 않는다.
|
|
|
* 필요 이상의 객체들이 생성되면 가비지 컬렉션이 자주 일어난다.
|
|
|
- 너무 큰 객체 할당을 피한다.
|
|
|
* CLR은 85KB 이상의 대형 객체를 할당하기 위한 대형 객체 힙 (Large Object Heap ; LOH) 을 따로 유지한다. LOH는 해제된 공간을 인접 객체가 채우는 것이 아니라 그대로 둔다. 대형 객체는 복사하여 옮기는 비용이 비싸기 때문이다. 이로 인해 큰 공간 사이사이의 메모리 조각이 SOH에 비해 많이 발생하게 된다.
|
|
|
- 너무 복잡한 참조 관계는 만들지 않는다.
|
|
|
* 참조 관계가 많은 객체는 가비지 컬렉션 후에 살아남았을 때가 문제다. 살아남은 객체는 세대를 옮기기 위해서 메모리 복사를 진행하는데, 참조 관계가 복잡할 경우 객체를 구성하고 있는 각 필드 객체간의 참조관계를 다 조사해서 메모리 주소를 수정해야하기 때문에 탐색과 수정의 오버헤드가 발생한다.
|
|
|
- 루트를 너무 많이 만들지 않는다.
|
|
|
* 가비지 컬렉터는 루트 목록을 돌면서 쓰레기를 수거하기 때문에 적을 수록 성능에 유리하다.
|
|
|
>>>
|
|
|
|
|
|
<br />
|
|
|
|
|
|
**CLR이 중요한 이유 :**
|
|
|
그 어떤 .NET 호환 언어를 사용해서 코드를 작성하더라도, CLS 규격을 만족한다면 다양한 언어의 결과물 끼리 상호 호출이 가능하다. 컴파일러가 IL코드로 변환하여 CLR에서 실행하기 때문이다. CLR은 윈도우용 CLI 구현체이고, 리눅스의 경우에는 Mono를 쓴다. CLS 규격을 만족한다면 플랫폼 독립적인 IL코드로 변환하여 각 플랫폼의 CLI구현체를 거쳐 다양한 플랫폼에서 작동하는 프로그램을 만들 수 있다.
|
|
|
그 어떤 .NET 호환 언어를 사용해서 코드를 작성하더라도, CLS 규격을 만족한다면 다양한 언어의 결과물 끼리 상호 호출이 가능하다. 컴파일러가 IL코드로 변환하여 CLR에서 실행하기 때문이다. CLR은 윈도우용 CLI 구현체이고, 리눅스의 경우에는 Mono를 쓴다. CLS 규격을 만족한다면 플랫폼 독립적인 IL코드로 변환하여 각 플랫폼의 CLI구현체를 거쳐 다양한 플랫폼에서 작동하는 프로그램을 만들 수 있다.
|
|
|
|
|
|
### CTS
|
|
|
CTS(Common Type System)은 .NET 호환 언어들이 지켜야 할 Type과 표준 규격을 정의한 것이다.
|
|
|
CTS(Common Type System)은 .NET 호환 언어들이 지켜야 할 Type과 표준 규격을 정의한 것이다.
|
|
|
|
|
|
CTS에는 값 형식(Value Type)과 참조 형식(Reference Type)이 있다.
|
|
|
|
|
|
>>>
|
|
|
* 값 형식 : 값을 변수에 넣는 데이터 형식
|
|
|
* 참조 형식 : 변수에 대한 위치(메모리 위치)를 담는 데이터 형식
|
|
|
>>>
|
|
|
|
|
|
- - -
|
|
|
|
|
|
<br />
|
|
|
|
|
|
***
|
|
|
**CLI, CTS, CLS, CLR의 정의와 관계를 다시 한 번 정리하면**
|
|
|
CLI(Common Language Infrastructure) : 공용 언어 기반구조
|
|
|
CTS(Common Type System) : 공용 타입 시스템
|
... | ... | @@ -46,7 +137,7 @@ CLR(Common Language Runtime) : 공용 언어 런타임 |
|
|
어셈블리(Assembly)는 .NET에서의 실행파일(주로 EXE, DLL 파일)을 말한다.
|
|
|
|
|
|
어셈블리는 1개 이상의 모듈로 구성되는데, 모듈 하나당 한 개의 파일이 대응된다. 하지만 여러개의 파일이 어셈블리를 구성한다면 이 파일들의 목록을 관리하는 데이터가 필요하다. 그 때문에 이 모듈 중의 하나는 다른 모듈의 목록을 관리하는 매니페스트(Manifest) 데이터를 갖고있다.
|
|
|
메니페스트를 포함하고 있지 않은 모듈은 확장자가 netmodule이고, 메니페스트를 경우에는 확장자가 DLL(또는 EXE)이다.
|
|
|
메니페스트를 포함하고 있지 않은 모듈은 확장자가 netmodule이고, 메니페스트를 포함하는 경우에는 확장자가 DLL(또는 EXE)이다.
|
|
|
|
|
|
>>>
|
|
|
EXE 와 DLL의 차이
|
... | ... | @@ -63,7 +154,7 @@ Managed Process를 그림으로 나타내면 다음과 같다. |
|
|

|
|
|
|
|
|
### Unmanaged
|
|
|
Managed와 달리 IL 코드 같은 중간 언어를 거치지 않고 컴파일 이후 바로 실행이 되는 머신 코드를 만들어 내는 것을 말한다. 속도에는 장점을 가지지만 보안, 메모리 관리 등을 직접 해줘야 하기 때문에 확장성에 한계가 있다.
|
|
|
Managed와 달리 IL 코드 같은 중간 언어를 거치지 않고 컴파일 이후 바로 실행이 되는 머신 코드를 만들어 내는 것을 말한다. 때문에 속도에 장점을 가진다.
|
|
|
|
|
|
Unmanaged Process를 그림으로 나타내면 다음과 같다.
|
|
|
|
... | ... | @@ -86,5 +177,23 @@ C#, Visual Studio, .NET과의 버전 간의 상관 관계는 다음과 같다. |
|
|
|2012년 8월|C# 5.0 | .NET Framework 4.5 | Visual Studio 2012~2013 |
|
|
|
|2015년 7월|C# 6.0 | .NET Framework 4.6 | Visual Studio 2015 |
|
|
|
|
|
|
//BCL에 대한 간략한 정리추가, 문장이 어색한지 다시 한 번 점검, 책 다시 리뷰하면서 흐름상 중요한 부분 삽입. jit컴파일러
|
|
|
// 문장이 어색한지 다시 한 번 점검, 책 다시 리뷰하면서 흐름상 중요한 부분 삽입.
|
|
|
|
|
|
```csharp
|
|
|
using System;
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
namespace Ex_2_4
|
|
|
{
|
|
|
class Program
|
|
|
{
|
|
|
static void Main(string[] args)
|
|
|
{
|
|
|
|
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
|
TimeSpan time;
|
|
|
String str = String.Empty;
|
|
|
|
|
|
stopWatch.Start();
|
|
|
```
|
|
|
|