cv.cm

코딩 · 프로그래밍 언어

C# 기초 입문 튜토리얼

10분 분량

핵심 답변

C#은 Microsoft가 만든 정적 타입 객체지향 언어로, Windows, macOS, Linux에서 동작하는 무료 크로스 플랫폼 런타임 .NET 위에서 실행됩니다. .NET SDK를 설치하고 dotnet new console을 실행한 뒤 dotnet run을 하면 "Hello, World!"가 출력됩니다. 핵심 개념은 클래스와 레코드, List<T>와 Dictionary<K, V> 같은 제네릭 컬렉션, LINQ 쿼리, async/await, 패턴 매칭, 예외 처리입니다.

JSON 포맷 열기

C#이란 무엇이고 어디에 쓰이는가

C#("씨 샤프"라고 읽음)은 Microsoft에서 아네르스 헤일스베르(Anders Hejlsberg)가 이끄는 팀이 설계해 2002년에 처음 공개했습니다. Ecma(ECMA-334)에서 표준화되었고 .NET과 함께 오픈 소스로 개발됩니다. C#은 웹 API와 웹사이트(ASP.NET Core), Windows 데스크톱 앱, 크로스 플랫폼 모바일·데스크톱 앱(.NET MAUI), 클라우드 서비스, 게임에 쓰입니다. Unity 엔진은 게임 스크립트에 C#을 사용합니다. 문법이 C 계열이라 자바, C++, 자바스크립트 개발자에게도 익숙합니다.

.NET 설치와 Hello, world 실행

dot.net에서 .NET SDK를 내려받고 dotnet --version으로 확인하세요. 콘솔 프로젝트를 만들고 실행합니다.

dotnet new console -o HelloApp
cd HelloApp
dotnet run
# Hello, World!

템플릿은 최상위 문(top-level statements)을 사용하는 Program.cs를 만들므로, 작은 프로그램에는 클래스나 Main 메서드가 필요 없습니다.

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

변수와 기본 자료형

모든 변수는 정적 타입을 가집니다. var를 쓰면 값을 보고 컴파일러가 타입을 추론합니다. 값 형식(숫자, bool, struct)은 데이터를 직접 저장하고, 참조 형식(string, 클래스, 배열)은 객체를 가리킵니다.

타입예시설명
intint n = 42;32비트 정수
longlong big = 10_000_000_000;64비트 정수
doubledouble x = 3.14;64비트 부동소수점
decimaldecimal price = 19.99m;10진수 기반, 금액 계산에 적합
boolbool ok = true;true 또는 false
charchar c = 'A';UTF-16 코드 단위
stringstring s = "hi";변경 불가능한 텍스트
var name = "Ada";
int count = 7;
double avg = count / 2.0;
Console.WriteLine($"{name} has {count} items, avg {avg}");  // Ada has 7 items, avg 3.5
Console.WriteLine(count / 2);                              // 3 (integer division)
Console.WriteLine(int.Parse("12") + 1);                    // 13
string? nickname = null;   // ? marks a nullable reference
Console.WriteLine(nickname ?? "none");                     // none

$"..."는 문자열 보간입니다. 새 프로젝트는 null 허용 참조 형식을 활성화하므로, null일 수 있는 값을 검사 없이 쓰면 컴파일러가 경고합니다.

제어 흐름과 메서드

int score = 72;
if (score >= 90) Console.WriteLine("A");
else if (score >= 70) Console.WriteLine("B");   // B
else Console.WriteLine("C");

for (int i = 0; i < 3; i++) Console.Write($"{Square(i)} ");  // 0 1 4
Console.WriteLine();

foreach (var fruit in new[] { "apple", "pear" }) Console.WriteLine(fruit);

string day = "SAT";
string kind = day switch
{
    "SAT" or "SUN" => "weekend",
    _ => "weekday",
};
Console.WriteLine(kind);   // weekend
Console.WriteLine(Greet("Lin"));                // Hello, Lin!

static int Square(int x) => x * x;
static string Greet(string name, string greeting = "Hello") => $"{greeting}, {name}!";

switch 식과 or 패턴은 C# 패턴 매칭의 일부입니다. 메서드에는 기본 매개변수 값, 명명된 인수(Greet(name: "Lin")), =>를 쓰는 식 본문을 사용할 수 있습니다.

클래스, 속성, 레코드

클래스에는 필드, 속성(get과 set 로직을 가진 필드), 메서드가 있습니다. record는 값을 기준으로 동등성을 판단하는 타입으로, 불변 데이터에 적합합니다.

var acc = new Account("Ann");
acc.Deposit(50);
Console.WriteLine($"{acc.Owner}: {acc.Balance}");   // Ann: 50

var p1 = new Point(3, 4);
var p2 = p1 with { Y = 5 };                         // copy with one change
Console.WriteLine(p1);                              // Point { X = 3, Y = 4 }
Console.WriteLine(p1 == new Point(3, 4));           // True

public class Account
{
    public string Owner { get; }
    public decimal Balance { get; private set; }

    public Account(string owner) => Owner = owner;

    public void Deposit(decimal amount)
    {
        if (amount <= 0) throw new ArgumentException("amount must be positive");
        Balance += amount;
    }
}

public record Point(int X, int Y);

형식 선언은 같은 파일에서 최상위 문 뒤에 와야 합니다. 클래스는 단일 상속(class Savings : Account)과 여러 개의 인터페이스를 지원합니다.

컬렉션과 LINQ

System.Collections.Generic의 제네릭 컬렉션은 일상적으로 쓰는 자료구조입니다. LINQ(Language Integrated Query)는 모든 컬렉션에 Where, Select, OrderBy, GroupBy 같은 메서드를 더해 줍니다.

var nums = new List<int> { 3, 1, 2, 5 };
nums.Add(4);
nums.Sort();
Console.WriteLine(string.Join(", ", nums));      // 1, 2, 3, 4, 5

var ages = new Dictionary<string, int> { ["ann"] = 31, ["bob"] = 25 };
ages["cy"] = 40;
if (ages.TryGetValue("bob", out int bobAge)) Console.WriteLine(bobAge);  // 25

var evenSquares = nums.Where(n => n % 2 == 0).Select(n => n * n).ToList();
Console.WriteLine(string.Join(" ", evenSquares)); // 4 16

var oldest = ages.OrderByDescending(kv => kv.Value).First();
Console.WriteLine(oldest.Key);                    // cy

그 밖의 흔한 컬렉션으로 중복 없는 항목을 위한 HashSet<T>, Queue<T>, Stack<T>, 그리고 int[] 같은 고정 크기 배열이 있습니다.

대표 기능: async와 await

C#은 이후 많은 언어가 채택한 async/await 모델을 도입했습니다. async 메서드는 Task를 반환하며, 웹 요청이나 파일 읽기처럼 오래 걸리는 작업을 스레드를 막지 않고 await할 수 있습니다.

using System.Net.Http;

using var http = new HttpClient();
var sizes = await Task.WhenAll(
    GetLengthAsync(http, "https://example.com"),
    GetLengthAsync(http, "https://example.org"));
Console.WriteLine($"downloaded {sizes.Sum()} characters");

static async Task<int> GetLengthAsync(HttpClient http, string url)
{
    string html = await http.GetStringAsync(url);
    return html.Length;
}

Task.WhenAll은 두 요청을 동시에 실행하고 둘 다 끝나기를 기다립니다. using var 선언은 스코프가 끝날 때 HttpClient를 해제합니다.

예외 처리

오류는 예외입니다. 구체적인 타입을 먼저 잡고, 정리 작업에는 finally나 using을 사용하세요. 잘못된 입력이 흔한 경우에는 TryParse 패턴으로 예외를 피할 수 있습니다.

try
{
    int age = int.Parse("abc");
}
catch (FormatException ex)
{
    Console.WriteLine($"not a number: {ex.Message}");
}
finally
{
    Console.WriteLine("done");
}

if (!int.TryParse("41", out int parsed)) parsed = 0;
Console.WriteLine(parsed);   // 41

작은 완성 프로그램: 단어 빈도 세기

콘솔 프로젝트의 Program.cs를 이 코드로 바꾼 뒤 dotnet run -- notes.txt로 실행하세요.

using System.Text.RegularExpressions;

if (args.Length != 1)
{
    Console.Error.WriteLine("usage: dotnet run -- FILE");
    return 1;
}

try
{
    string text = File.ReadAllText(args[0]).ToLowerInvariant();
    var top = Regex.Matches(text, "[a-z']+")
        .GroupBy(m => m.Value)
        .Select(g => (Word: g.Key, Count: g.Count()))
        .OrderByDescending(t => t.Count)
        .Take(5);

    foreach (var (word, count) in top)
        Console.WriteLine($"{count,5}  {word}");
    return 0;
}
catch (FileNotFoundException)
{
    Console.Error.WriteLine($"file not found: {args[0]}");
    return 1;
}

최상위 문에서는 명령줄 args를 읽고 종료 코드를 반환할 수 있습니다. System.IO, System.Linq, System.Collections.Generic은 새 프로젝트의 암시적 using을 통해 자동으로 임포트됩니다.

초보자가 자주 하는 실수

  • 금액에 double을 쓰는 경우. 이진 반올림 오류를 피하려면 decimal을 사용하세요.
  • null 허용 경고를 무시하는 경우. 결국 실행 시점의 NullReferenceException이 됩니다.
  • 같은 리스트를 foreach로 순회하는 도중에 List<T>를 수정하는 경우. InvalidOperationException이 발생합니다.
  • 오래 실행되는 앱에서 요청마다 새 HttpClient를 만드는 경우. 인스턴스 하나를 재사용하거나 IHttpClientFactory를 사용하세요.
  • LINQ 쿼리가 지연 실행된다는 점을 잊는 경우. ToList()를 호출하지 않으면 열거할 때마다 쿼리가 다시 실행됩니다.

다음 학습 단계

Microsoft Learn에 언어 둘러보기와 대화형 튜토리얼을 포함한 공식 C# 문서가 있습니다. 그다음 웹 API용 ASP.NET Core, 데이터베이스용 Entity Framework Core, 게임용 Unity를 배우고, 테스트에는 xUnit이나 NUnit을 사용하세요. Visual Studio, C# Dev Kit을 설치한 VS Code, JetBrains Rider가 흔히 쓰는 편집기입니다.

자주 묻는 질문

C#은 Windows 전용인가요?

아닙니다. 현대 .NET은 Windows, macOS, Linux에서 실행되고 C# 앱을 Linux 서버와 컨테이너에 배포할 수 있습니다. WPF와 Windows Forms 같은 일부 데스크톱 UI 프레임워크만 Windows 전용입니다.

C#과 .NET은 무엇이 다른가요?

C#은 프로그래밍 언어입니다. .NET은 C# 코드(그리고 F#과 Visual Basic)를 컴파일하고 실행하는 런타임과 라이브러리입니다.

C#은 자바와 비슷한가요?

네, 여러 면에서 그렇습니다. 둘 다 정적 타입, 가비지 컬렉션, 객체지향 언어이며 C 스타일 문법을 씁니다. C#은 속성, LINQ, async/await, 값 형식 구조체, 레코드 같은 기능을 더했습니다.

C#은 게임 개발에 좋은가요?

네. 가장 널리 쓰이는 게임 엔진 중 하나인 Unity가 게임 스크립트에 C#을 사용하고, Godot 엔진도 C#을 지원합니다.

코딩 튜토리얼 전체