C#과 .NET 정리

C#이란 무엇인가

C#은 마이크로소프트 .NET Framework 플랫폼 전용으로 설계된 언어이며, 발음은 “씨 샤프(See Sharp)”입니다.

마이크로소프트는 구식 개발 기술의 여러 단점을 해소할 통일되고 완전한 객체지향 통합 개발 프레임워크가 필요했고, 이를 위해 새로운 코드 실행 환경과 개발 툴 체인을 구축하기 시작했습니다.

20여 년간의 발전을 거쳐 C#은 예전 윈도우 단독 지원 언어에서 여러 플랫폼을 아우르는 크로스플랫폼 언어로 변화했습니다.

현재 C#과 .NET은 완전한 크로스플랫폼 개발 솔루션을 이루고 있으며 윈도우, 맥OS, 리눅스, 안드로이드 앱 제작에 활용할 수 있습니다. 또한 대부분의 클라우드 시스템에서 가장 선호하는 실행 환경으로 사용됩니다.

마이크로소프트의 적극적인 지원 덕분에 C# 업그레이드 주기가 매우 빠릅니다. 2022년 7번째 버전이 출시되었고, C#은 20년 전 작성한 오래된 코드와 호환성을 유지하면서도 신버전은 문법이 더 간결하고 정돈되며 구조가 간소화되었습니다. 2026년 기준 최신은 15번째 버전입니다.

C# 버전 발전 연표 (일부 발췌)

  • C# 1.0 (2001):정식 공개 출시
  • C# 2.0 (VS2005):제네릭, 이터레이터, 익명 메서드
  • C# 3.0 (VS2008):확장 메서드, 람다 표현식, LINQ(언어 통합 쿼리)
  • C# 4.0 (2010):명명 매개변수/옵션 매개변수, 동적 타입 dynamic, TPL 병렬 작업 라이브러리를 제공해 멀티코어 프로세서 성능을 최대한 활용
  • C# 5.0:async/await 기본 탑재로 비동기 작업 지원
  • C# 6.0:문자열 보간, 식 본문 멤버, 속성 간결 표기법
  • C# 7.0~7.3:튜플을 활용한 다중 반환값, out 매개변수 축약 문법, 패턴 매칭, 비동기 Main 메서드
  • C# 8.0/9.0/10.0:레코드(불변 참조 타입), 최상위 문장(Main 함수 불필요), 기본 인터페이스 메서드, 정적 지역 함수, 비동기 해제 가능 타입, 언어 전역 패턴 매칭
  • C#11 (.NET7):원시 문자열, 제네릭 수학 연산, required 속성
  • C#12 (.NET8):주 생성자, 컬렉션 약식 표기, 인라인 배열
  • C#13 (.NET9):부분 속성, 확장 인덱서, 이터레이터 ref 지역 변수
  • C#14 (.NET10):제네릭 별칭, 심층 컬렉션 매칭, SIMD 문법 설탕

윈도우는 여전히 C#의 핵심 플랫폼이지만 .NET 런타임을 기반으로 리눅스 등 다른 운영체제에서 코드를 직접 실행할 수 있어 한 번 작성하면 여러 운영체제에 배포하는 것이 가능합니다.

.NET 프레임워크

.NET Framework는 2002년 최초로 공개되었습니다.

.NET Framework는 이전 세대 개발 기술의 불편한 점들을 해결하며 다음과 같은 핵심 장점을 가지고 있습니다.

  1. 다기기 플랫폼 지원:서버, PC, PDA, 스마트폰 등 다양한 하드웨어 환경에서 구동 가능;
  2. 업계 표준 준수:XML, HTTP, SOAP, JSON, WSDL 같은 범용 통신 프로토콜을 기본으로 지원;
  3. 보안 샌드박스:출처가 불확실한 코드를 실행할 때 격리 공간을 제공해 안전한 실행을 보장.

.NET Framework의 3대 핵심 구성 요소

  1. CLR 공통 언어 런타임(실행 환경) 프로그램 전 생명주기 실행을 통제합니다. 메모리 관리와 가비지 컬렉션, 코드 보안 검증, 스레드 스케줄링, 예외 처리 업무를 전담합니다.
  2. 개발 툴 세트 통합 개발 환경, 다중 언어 .NET 컴파일러(C#/VB.NET/F# 등), 디버거, ASP.NET/WCF 웹 백엔드 기술을 포함합니다.
  3. BCL 기본 클래스 라이브러리(FCL 프레임워크 클래스 라이브러리라고도 부름) 방대한 기본 제공 범용 클래스가 탑재되어 개발자가 별도 구현 없이 바로 호출해 사용할 수 있습니다.

기존 윈도우 개발 방식 대비 .NET의 주요 개선점

통일된 객체지향 체계

CLR, BCL, C#이 긴밀하게 연동해 통일된 OOP 모델을 제공합니다. 데스크톱, 모바일, 웹, 분산 프로그램에서 동일한 개발 패턴을 사용할 수 있으며 기기마다 문법과 로직이 일관됩니다.

자동 가비지 컬렉션 GC

CLR에 기본 탑재된 가비지 컬렉터가 사용하지 않는 객체 메모리를 자동으로 반납합니다. 개발자가 직접 메모리를 해제하거나 메모리 누수 문제를 찾을 필요가 없어 운영 유지보수 부담이 크게 줄어듭니다.

다방면 상호 운용성
  1. .NET 언어 간 상호 호출:서로 다른 .NET 언어로 작성한 클래스끼리 호출하고 상속할 수 있어 플랫폼이 특정 언어에 종속되지 않음;
  2. P/Invoke 플랫폼 호출:순수 Win32 C 언어 DLL 인터페이스를 직접 호출 가능;
  3. COM 호환성:.NET 컴포넌트와 기존 COM 컴포넌트를 양방향으로 호출할 수 있음.

배포 절차 간소화:레지스트리에 의존하지 않아 최소 구성에서는 파일만 복사하면 프로그램 실행이 가능함;

병렬 어셈블리:단일 기기에 여러 버전의 DLL을 공존시킬 수 있으며 각 프로그램은 빌드 당시 연결된 라이브러리 버전에 묶여 DLL 버전 충돌 문제가 해결됨.

타입 안전성 검증 CLR(공통 언어 런타임)이 매개변수와 데이터 타입을 강제로 검사하며 다른 언어 컴포넌트가 연동할 때도 타입 안전성을 보장해 불법 메모리 접근을 차단합니다.

풍부한 BCL 기본 클래스 라이브러리

다양한 범용 유틸리티 클래스를 기본 제공

  • 파일 처리, 문자열 가공, 암호화 보안 등 기본 유틸리티;
  • 리스트, 딕셔너리, 해시 테이블 등 컬렉션 컨테이너;
  • 멀티스레드, 동기화 병렬 처리 도구;
  • XML 문서 읽기/쓰기 처리 클래스
  • 그 외 다수 기능

범용 기본 로직이 모두 미리 구현되어 있으므로 개발자는 업무 고유 로직만 작성하면 되고 기존 완성된 도구를 재사용해 중복 개발을 줄일 수 있습니다.

.NET 프로그램 실행 흐름도입니다. 개발자가 작성한 코드는 중간 언어 IL로 컴파일되고, IL은 BCL에서 제공하는 라이브러리를 호출한 뒤 마지막으로 CLR에 전달되어 실행됩니다.

C#과 .NET의 관계

.NET Framework:완전한 개발 & 실행 플랫폼으로 두 가지 핵심 컴포넌트로 구성됩니다

  1. CLR(공통 언어 런타임):코드 메모리 관리, 실행 통제, 보안 검증 담당
  2. BCL(기본 클래스 라이브러리):파일, 네트워크, UI, 병렬 처리 등 방대한 범용 유틸리티 코드 집합

C#프로그래밍 언어로 .NET 플랫폼 전용 설계되었으며 CLR 위에서 실행할 코드를 작성하는 데 사용합니다

C# 외에도 .NET을 지원하는 다른 프로그래밍 언어가 있으며 대표적으로 F#, VB.NET이 있습니다.

.NET 프레임워크의 개발 목표는 크로스플랫폼과 크로스언어 지원입니다. 크로스플랫폼은 여러 운영체제에서 구동하는 것을 의미하고, 크로스언어는 서로 다른 언어로 개발한 모듈이 서로 접근할 수 있음을 뜻합니다.

공통 중간 언어(CIL)로 컴파일

.NET 계열 언어의 컴파일러는 소스 코드 파일을 읽어 어셈블리(assembly)라는 결과물 파일을 생성합니다

어셈블리는 두 종류로 나뉘며 실행 파일(exe) 혹은 동적 링크 라이브러리(DLL)입니다

어셈블리 내부 코드는 CPU가 직접 인식하는 네이티브 기계어가 아닌 공통 중간 언어(Common Intermediate Language, CIL)라는 중간 코드로 기록됩니다.

하나의 어셈블리는 주로 다음 내용을 포함합니다.

  1. 프로그램의 CIL 명령 코드
  2. 프로그램 내 모든 타입에 대한 메타데이터
  3. 외부 다른 어셈블리 참조 관계에 대한 메타데이터

중간 언어 약자는 .NET이 발전하며 명칭이 변경되어 자료마다 표기가 다릅니다. 중간 언어(IL), 마이크로소프트 중간 언어(MSIL) 모두 CIL을 지칭하는 용어입니다.

네이티브 코드로 변환 후 실행

CIL은 미리 네이티브 기계어로 변환되지 않고 프로그램 실행 시 CLR이 아래 3단계를 처리합니다.

  1. 어셈블리 보안 정보 검증
  2. 실행용 메모리 할당
  3. JIT 컴파일러에 전달해 구간별로 네이티브 코드로 컴파일
JIT 수요 기반 컴파일 방식

실제 호출되는 코드만 컴파일한 뒤 캐시로 저장해 재사용하며 호출되지 않는 코드는 컴파일하지 않고 동일한 코드 구간은 한 번만 변환합니다.

어셈블리(CIL + 타입 정보) → CLR(JIT 컴파일러) → 네이티브 코드 → 운영체제 서비스

CLR 관리 업무

CIL이 네이티브 코드로 변환된 후 CLR은 가비지 메모리 회수, 배열 범위 초과 검사, 매개변수 타입 검증, 예외 처리를 자동 관리합니다.

관리 코드와 비관리 코드
  • 관리 코드:.NET 계열 언어로 작성한 코드로 CLR의 실행 통제를 받음
  • 비관리 코드:CLR 통제를 받지 않는 코드로 순수 C/C++ Win32 DLL 등이 해당됨

현재 마이크로소프트에서 AOT 컴파일을 지원해 C# 코드를 미리 기계어로 빌드할 수 있습니다. C++처럼 별도 .NET 런타임 설치 없이 exe 파일을 직접 실행하는 것이 가능합니다.

NGen 도구

오프라인 상태에서 어셈블리를 미리 컴파일해 네이티브 이미지를 생성하며 실행할 때 JIT 컴파일 단계를 건너뛰어 앱 시작 속도를 높입니다.

.NET Core AOT는 차세대 사전 컴파일 방식으로 런타임 의존성이 없는 독립적인 네이티브 실행 파일을 생성할 수 있습니다.

Assembly (타입 정보, CIL)
        ↓
JIT 컴파일러
        ↓
네이티브 코드
        ↓
운영체제 서비스

원본 소스 코드가 어떤 언어로 작성되었든 동일한 컴파일 및 실행 흐름을 따릅니다.

각 언어마다 전용 컴파일러가 존재하는데 VB.NET은 VB용 컴파일러, C#은 C#용 컴파일러가 있습니다. 모든 컴파일러는 각 언어 코드를 CIL로 변환하고 CIL은 다시 JIT를 거쳐 네이티브 코드가 되어 CPU에서 실행됩니다. 이것이 .NET으로 제작한 소프트웨어를 구동하기 위해 .NET 환경 설치가 필요한 이유이며 Java가 JRE 설치를 요구하는 원리와 같습니다.

flowchart TD
    subgraph 컴파일 타임
        A[C# 소스] --> B[C# 컴파일러]
        B --> C[어셈블리 CIL]
        D[VB 소스] --> E[VB 컴파일러]
        E --> C
        F[기타 .NET 소스] --> G[해당 언어 컴파일러]
        G --> C
    end

    subgraph 실행 타임
        C --> H[JIT 컴파일러]
        H --> I[네이티브 코드]
        I --> J[운영체제 서비스]
    end

위 그림은 여러 언어의 컴파일부터 실행까지 전 과정을 보여주는 흐름도입니다.

공통 언어 런타임(CLR)

.NET Framework의 핵심 컴포넌트가 CLR로 운영체제 상단에 위치하며 프로그램 실행 전 과정을 관리합니다.

  • 자동 가비지 컬렉션(GC)
  • BCL을 통한 보안 검증 및 신원 인증
  • 웹 서비스, 데이터 서비스 등 풍부한 프로그래밍 기능 제공
flowchart TD
    subgraph 비관리 코드
        A[비 .NET 프로그램] --> OS[운영체제]
    end

    subgraph 관리 코드
        B[어셈블리] --> CLR[공통 언어 런타임]
        C[어셈블리] --> CLR
        D[어셈블리] --> CLR

        subgraph CLR[공통 언어 런타임]
            M[메모리 관리] --- E[예외 처리]
            G[가비지 컬렉션] --- R[리플렉션 서비스]
            J[JIT 컴파일러] --- L[클래스 로더]
            S[보안 서비스]
        end

        CLR --> OS
    end

공통 언어 기반 구조(CLI)

모든 프로그래밍 언어에는 정수, 부동소수점, 문자 등 데이터를 표현하는 기본 원시 타입이 내장되어 있습니다.

공통 언어 기반 구조(CLI)는 일련의 표준 규격 집합으로 .NET Framework의 모든 구성 요소를 통일되고 호환 가능한 하나의 체계로 묶어줍니다.

예를 들어 정수형이 차지하는 비트 길이는 모든 지원 언어에서 동일하게 통일되어 있습니다.

flowchart TD
    subgraph CLI[공통 언어 기반 구조]
        CLR[공통 언어 런타임] --- CLS[공통 언어 규격]
        BCL[기본 클래스 라이브러리] --- MDS[메타데이터 정의 & 의미 규칙]
        CTS[공통 타입 시스템] --- CIL[공통 중간 언어]
    end

개발자 대부분은 CLI 전체 규격을 깊이 파악할 필요는 없지만 CTS 공통 타입 시스템CLS 공통 언어 규격은 필수로 숙지해야 합니다.

CTS 공통 타입 시스템

  • 규격화된 기본 데이터 타입 집합을 제공하며 각 타입의 속성은 고정됨;
  • 각 .NET 언어 고유 타입은 모두 이 표준 타입 하위 집합으로 매핑됨;
  • 모든 타입은 최상위 클래스 object를 상속함;
  • 통일 표준 덕분에 시스템 기본 타입과 사용자 정의 타입이 어떤 .NET 언어 간에서도 상호 사용 가능.

CLS 공통 언어 규격

.NET과 호환되는 언어가 준수해야 하는 통일된 규칙을 정의하며 데이터 타입, 클래스 생성자, 매개변수 전달 등 언어 간 상호작용 제약 사항을 포함합니다.

.NET과 .NET Framework의 차이점

.NET은 마이크로소프트의 최신 크로스플랫폼 개발 플랫폼이고 .NET Framework는 초기 버전으로 윈도우에서만 구동하는 런타임 및 라이브러리 묶음입니다. 신기능 개발은 오직 .NET에서만 진행되며 .NET Framework는 유지보수 단계로 진입해 보안 업데이트만 제공됩니다.

.NET은 크로스플랫폼을 지원하며 현재 마이크로소프트의 주력 개발 플랫폼입니다. 이후 설명은 .NET을 중심으로 다룹니다.

특성.NET.NET Framework
플랫폼 지원크로스플랫폼(윈도우, 리눅스, 맥OS, 컨테이너, MAUI 기반 모바일)윈도우 전용
개발 상태지속 업데이트(.NET 5 → .NET 10 매년 출시, LTS 장기 지원 제공)유지보수 모드(4.8이 마지막 버전, 보안 패치만 배포)
성능시작 속도 빠름, 처리량 높음, 가비지 컬렉션 최적화성능이 낙후되며 윈도우 API에 종속
활용 시나리오신규 프로젝트: 웹 API, 마이크로서비스, 클라우드 네이티브, 크로스플랫폼 데스크톱/모바일레거시 프로젝트: 웹 폼, WCF, 윈도우 워크플로우 등
배포 방식Docker, 컨테이너, 클라우드 환경 완전 지원컨테이너 미지원, 윈도우 서버 의존
지원 언어C#, F#, VB.NET(크로스플랫폼 지원)C#, VB.NET(윈도우 한정)

.NET과 .NET Framework의 차이는 크지 않습니다. 둘 다 C#, F#, VB.NET 등 언어를 사용하며 핵심 문법은 동일합니다. 대부분의 경우 동일한 C# 코드를 .NET Framework와 .NET(Core/5/6/7/8…) 양쪽에서 컴파일하고 실행할 수 있습니다.

차이는 문법이 아닌 사용 가능한 클래스 라이브러리에 있습니다.

.NET Framework에 탑재되었던 WCF, Web Forms, Windows Workflow는 최신 .NET에서 삭제되거나 대체 기술로 교체되었습니다.

최신 .NET에는 Span<T>, ValueTask, Records 등 현대적인 API가 추가되었으며 구식 .NET Framework에서는 사용할 수 없습니다.

.NET Framework는 윈도우 단독 플랫폼이고 .NET은 크로스플랫폼이므로 윈도우에만 존재하는 일부 라이브러리가 .NET에서 제거되었습니다. 예를 들어 System.Drawing은 윈도우에서 사용 가능하지만 크로스플랫폼 .NET에서는 윈도우 전용 API로 분류됩니다. .NET에서 그림 처리 라이브러리를 사용해야 한다면 System.Drawing 대신 구글의 SkiaSharp 같은 서드파티 라이브러리를 활용해야 합니다.

참고로 위 차이는 프레임워크 계층의 차이이며 C# 같은 언어 레벨에서는 거의 차이가 없습니다. 작성하는 C# 문법은 두 환경에서 완전히 동일합니다. 진정한 차이점: 클래스 라이브러리와 실행 환경, 즉 사용 가능한 API 집합이 다르다는 점입니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다