728x90
async vs await – 비동기 코딩, 진짜 이해하고 쓰고 있나?
처음 C#에서 비동기를 배울 때 이런 코드를 보게 된다.
public async Task<int> GetDataAsync()
{
await Task.Delay(1000);
return 42;
}
처음 보면 느낌이 좋다.
오호~ 뭔가 최신스럽고, 깔끔하고, 빨라 보인다.
근데 조금 지나면 이렇게 된다.
- async void를 남발함
- await을 안 쓰고 async만 붙임
- Task를 안 기다리고 .Result를 씀
- 데드락(deadlock)이 발생함
- UI가 멈춘다
"async와 await이 뭐가 다른 건데?"
"비동기라고 해서 썼는데 더 느린데?"
이번 챕터에선 이 둘의 개념부터 실무 팁까지, 진짜로 정리해보자.
문제 상황: 비동기로 했는데 프로그램이 멈췄다?
public async Task<int> GetValueAsync()
{
await Task.Delay(1000);
return 123;
}
int result = GetValueAsync().Result; // ❌ 데드락 가능성 있음
분명 비동기로 했는데 Result를 호출하니까 프로그램이 멈췄다.
왜 그럴까?
async는 비동기 메서드를 정의하는 키워드이고,
await은 비동기 작업(Task)을 기다리는 키워드다.
하나는 선언이고, 하나는 실행이다.
async – "비동기 메서드야!"라고 선언하는 키워드
public async Task DoSomethingAsync()
{
// 비동기 작업
}
- async는 혼자선 아무 일도 하지 않음
- 내부에 await가 없으면 경고 뜸
- 반드시 Task, Task<T>, ValueTask 리턴해야 함
public async void DoSomething() {} // ❌ 비추천
public async Task DoSomething() {} // ✅
async void는 예외 처리가 어렵고, 테스트도 안 되므로 이벤트 핸들러 외엔 쓰지 말자.
await – "비동기 작업이 끝날 때까지 기다릴게요"
await Task.Delay(1000); // 1초 쉬기
- await은 Task를 비동기적으로 기다린다
- 기다리는 동안 다른 작업(예: UI 렌더링)을 계속함
- await이 없으면 그냥 동기 함수처럼 실행됨
public async Task PrintLater()
{
Console.WriteLine("1");
await Task.Delay(1000);
Console.WriteLine("2");
}
await이 있어야 진짜 비동기처럼 동작한다.
async만 붙이고 await 안 쓰면 아무 소용 없다.
실무 예시: 비동기 API 호출
public async Task<string> GetUserNameAsync()
{
var response = await httpClient.GetAsync("https://example.com/user");
var json = await response.Content.ReadAsStringAsync();
return json;
}
- await이 연속적으로 붙는 구조를 비동기 파이프라인이라 부름
ConfigureAwait(false)
를 쓰면 스레드 컨텍스트를 안 따라가서 서버 환경에서 퍼포먼스 향상 가능
async/await 없이 비동기 호출하면?
var task = SomeAsyncMethod(); // 호출만 함
- 그냥 Task 객체만 얻고 실행은 이미 시작됨
- await하지 않으면 완료 여부, 결과, 예외 확인 불가
- 무시하면 고스트 Task 발생 → 디버깅 지옥
언제 어떤 걸 써야 할까?
구분 | async | await |
---|---|---|
기능 | 비동기 메서드 선언 | 비동기 작업을 기다림 |
필수 조건 | Task/Task 반환 | Task 또는 awaitable 대상 |
단독 사용 가능? | O (하지만 await 없으면 의미 없음) | X (항상 async와 함께 써야 함) |
주의할 점 | async void 지양 | Result, Wait() 사용 지양 |
마무리하며
비동기는 어렵지 않다. 다만 제대로 이해하지 않으면 오히려 더 위험하다.
- async는 "비동기로 만들겠다"는 약속
- await은 "비동기 작업이 끝날 때까지 기다리겠다"는 실행
"동기처럼 보이지만, 내부는 비동기"
이게 C# 비동기의 핵심이다.
그리고 절대 잊지 말자.
- async void 쓰지 마라 (예외 처리 불가능)
- .Result, .Wait() 쓰지 마라 (데드락 위험)
ConfigureAwait(false)
는 라이브러리나 서버 사이드에선 필수 고려
728x90
'C#' 카테고리의 다른 글
Dictionary vs HashSet – 비슷해 보이지만 목적이 다르다 (18) | 2025.06.08 |
---|---|
Nullable과 null 처리 전략 – null 때문에 또 터졌다고? (47) | 2025.06.06 |
object vs dynamic vs var – 언제 뭘 써야 헷갈리지 않을까? (3) | 2025.06.06 |
값 타입 vs 참조 타입 – 구조체와 클래스, 뭐가 다른데? (22) | 2025.06.05 |
ref, out, in - C# 파라미터 키워드 제대로 구분하자 (18) | 2025.06.04 |