---
title: "메서드 한 줄은 네 부분으로 되어 있다"
description: "무엇을 돌려주고, 이름이 무엇이고, 무엇을 받고, 무슨 일을 하는가. 이 넷만 정하면 메서드가 됩니다."
author: "유니얼"
pubDate: 2026-09-08
category: "programming/csharp/basics"
tags: ["C#", "기초"]
canonical: https://blog.unialgames.com/posts/csharp-method-basics/
---
세 사람의 평균 점수를 구하는 코드를 씁니다.

```csharp
int sum1 = a1 + b1 + c1;
double avg1 = sum1 / 3.0;
Console.WriteLine(avg1);

int sum2 = a2 + b2 + c2;
double avg2 = sum2 / 3.0;
Console.WriteLine(avg2);
```

같은 코드가 두 번 나왔습니다. 반이 셋이면 세 번입니다.

문제는 길이가 아니라 **고칠 때**입니다.
평균을 소수점 한 자리까지만 보여주기로 하면 세 군데를 고쳐야 하고,
한 군데를 빠뜨리면 화면에 두 가지 모양이 섞여 나옵니다.
그리고 이 코드 덩어리가 무엇을 하는 것인지는 읽어 봐야 압니다.

> **한 덩어리에 이름을 붙여 두고 이름으로 부르는 것이 메서드입니다.**

## 메서드는 이렇게 생겼다

<figure class="diagram">
<svg viewBox="0 0 680 210" role="img" aria-label="메서드 정의의 네 부분. 반환 타입, 이름, 매개변수, 본문">
<g font-family="var(--font-mono)" font-size="17">
<text x="30" y="40" fill="var(--accent)">double</text>
<text x="106" y="40" fill="var(--text)">Average</text>
<text x="192" y="40" fill="var(--text-muted)">(</text>
<text x="204" y="40" fill="var(--text)">int a, int b</text>
<text x="340" y="40" fill="var(--text-muted)">)</text>
<text x="30" y="70" fill="var(--text-muted)">{</text>
<text x="62" y="100" fill="var(--text)">...</text>
<text x="30" y="130" fill="var(--text-muted)">}</text>
</g>
<g stroke="var(--border)" stroke-width="1.4" fill="none">
<path d="M60 22 L60 12 L390 12"></path>
<path d="M144 52 L144 62 L390 62"></path>
<path d="M270 52 L270 92 L390 92"></path>
<path d="M80 100 L390 100"></path>
</g>
<g font-size="13" fill="var(--text-muted)">
<text x="402" y="16">돌려줄 값의 타입</text>
<text x="402" y="66">이름. 부를 때 쓴다</text>
<text x="402" y="96">받을 것. 매개변수</text>
<text x="402" y="104">무슨 일을 하는가. 본문</text>
</g>
</svg>
<figcaption>돌려줄 것, 이름, 받을 것, 하는 일. 네 부분이 전부다.</figcaption>
</figure>

```csharp
double Average(int a, int b, int c)
{
    int sum = a + b + c;
    return sum / 3.0;
}
```

- `double` 이 메서드가 **돌려줄 값의 타입**입니다.
- `Average` 가 이름입니다. 이 이름으로 부릅니다.
- 괄호 안이 **받을 것**입니다. 여기 적은 것을 매개변수라고 합니다.
- 중괄호 안이 하는 일입니다.
- `return` 이 값을 돌려주는 자리입니다.

기계 한 대라고 보면 됩니다. 재료를 넣으면 결과가 나옵니다.
쓰는 쪽은 안에서 무슨 일이 벌어지는지 몰라도 됩니다.
**이름과 투입구, 배출구만 알면 씁니다.**

앞의 코드를 다시 쓰면 이렇습니다.

```csharp
Console.WriteLine(Average(a1, b1, c1));
Console.WriteLine(Average(a2, b2, c2));
```

이제 고칠 자리가 한 곳입니다. 그리고 `Average` 라는 이름이 무엇을 하는지 말해 줍니다.

## 정의는 만들어 두는 것, 호출은 돌리는 것

메서드를 적어 두기만 하면 **아무 일도 일어나지 않습니다.**
적어 두는 것을 정의, 실제로 부르는 것을 호출이라고 합니다.

이게 앞에서 본 선언과 할당의 관계와 닮았습니다.
정의는 "이런 기계가 있다" 고 적어 두는 것이고, 실행되는 것은 호출할 때입니다.

호출하면 흐름이 어떻게 움직이는지 보겠습니다.

<x-flow>
<script type="application/json">
{
  "label": "부르고, 돌아온다",
  "dwell": 1.4,
  "lines": [
    "double Average(int a, int b)",
    "{",
    "    return (a + b) / 2.0;",
    "}",
    "",
    "double x = Average(80, 90);",
    "Console.WriteLine(x);"
  ],
  "cases": [
    {
      "label": "Average(80, 90)",
      "state": "x = (아직 없음)",
      "path": [
        { "line": 5, "why": "여기서 메서드를 부릅니다. 80 과 90 을 들려 보냅니다.", "state": "a = 80 · b = 90" },
        { "line": 0, "why": "받는 자리로 들어옵니다. a 와 b 에 값이 담깁니다." },
        { "line": 2, "why": "계산하고 return 으로 값을 들고 나갑니다.", "state": "돌려줄 값 = 85" },
        { "line": 5, "why": "부른 자리로 돌아옵니다. 그 값이 x 에 담깁니다.", "state": "x = 85" },
        { "line": 6, "why": "그다음 줄로 이어집니다.", "out": "85" }
      ],
      "skip": [1, 3],
      "note": "정의는 위에 적혀 있지만 실행은 호출한 순간에만 일어납니다."
    }
  ]
}
</script>
</x-flow>

**부른 자리로 돌아옵니다.** 이게 중요합니다.
메서드는 위에서 아래로 흘러가는 코드를 잠깐 다른 데로 보냈다가 제자리로 데려옵니다.
갈라지기도 되돌아가기도 아닌 세 번째 움직임입니다.

호출한 자리에는 돌려받은 값이 남습니다.
그래서 `Average(80, 90)` 은 계산이 끝나고 나면 그냥 `85` 라는 값입니다.
앞에서 식은 값 하나로 줄어든다고 했는데, 메서드 호출도 식입니다.

## 돌려줄 것이 없으면 void

출력하고 끝나는 일에는 돌려줄 값이 없습니다. 이때 반환 타입 자리에 `void` 를 적습니다.

```csharp
void PrintLine()
{
    Console.WriteLine("--------");
}

PrintLine();
```

`void` 는 "돌려주는 것이 없다" 는 표시입니다. `return` 을 안 써도 됩니다.

돌려주는 것이 없으니 값으로 쓸 수도 없습니다.

```csharp
int n = PrintLine();     // 컴파일 에러: void 는 값이 아닙니다
```

`Console.WriteLine` 도 `void` 입니다. 그래서 그 결과를 변수에 담을 수 없습니다.

## 이름은 하는 일로 짓는다

메서드 이름은 **무엇을 하는지**가 드러나야 합니다. 그게 메서드를 쓰는 이유의 절반입니다.

```csharp
double Calc(int a, int b, int c)      // 무엇을 계산하는지 모릅니다
double Average(int a, int b, int c)   // 평균이라는 것을 압니다
```

C# 에서는 메서드 이름을 대문자로 시작합니다. 변수는 소문자로 시작합니다.
문법이 강제하는 것은 아니지만 거의 모든 코드가 이렇게 되어 있어서,
지키지 않으면 읽는 사람이 걸립니다.

값을 돌려주는 메서드는 명사나 명사구로(`Average`, `GetPrice`),
하고 끝나는 메서드는 동사로(`PrintLine`, `Save`) 짓는 편이 읽힙니다.

## 언제 메서드로 묶나

**같은 코드가 두 번 보이면** 묶을 때가 된 것입니다. 이건 분명합니다.

한 번밖에 안 쓰는 코드도 묶을 이유가 있습니다. **이름을 붙이려고** 묶습니다.

```csharp
if (age >= 19 && !isStudent && hasTicket && !isBanned)
```

앞에서 이 조건에 `bool canEnter` 라는 이름을 붙였습니다. 같은 이야기입니다.
긴 코드 덩어리에 이름을 붙이면 읽는 사람이 그 덩어리를 한 단어로 넘어갈 수 있습니다.

## 정리

- 메서드는 코드 덩어리에 이름을 붙여 두고 이름으로 부르는 것입니다.
- 반환 타입, 이름, 매개변수, 본문 네 부분으로 되어 있습니다.
- 정의는 적어 두는 것이고, 실행은 호출할 때 일어납니다.
- 호출하면 그리로 갔다가 **부른 자리로 돌아옵니다.** 그 자리에 돌려받은 값이 남습니다.
- 메서드 호출도 식입니다. 값 하나로 줄어듭니다.
- 돌려줄 것이 없으면 `void` 입니다. 값으로 쓸 수 없습니다.
- 같은 코드가 두 번 보이거나, 덩어리에 이름을 붙이고 싶을 때 묶습니다.