비동기 프로그래밍이란?
비동기 프로그래밍은 코드가 실행되는 동안 시간이 걸리는 작업(예: 네트워크 요청, 파일 읽기 등)을 기다리지 않고, 다음 코드를 계속 실행하도록 하는 방식입니다. JavaScript와 TypeScript는 비동기 처리에 매우 최적화된 언어로, Promise와 async/await 문법을 통해 효율적인 비동기 처리를 제공합니다.
타입스크립트에서 Promise 사용하기
Promise
는 비동기 작업의 완료 또는 실패를 나타내는 객체입니다. TypeScript에서는 제네릭 타입을 활용해 Promise의 반환 타입을 명확히 지정할 수 있습니다.
function fetchData(): Promise{ return new Promise((resolve, reject) => { setTimeout(() => { resolve("데이터 로딩 완료"); }, 1000); }); } fetchData().then((result) => { console.log(result); // "데이터 로딩 완료" });
이와 같이 타입이 지정되면 result
가 string 타입이라는 것을 컴파일 타임에 알 수 있어, 안전한 코딩이 가능합니다.
async/await 문법의 기본
async
함수는 항상 Promise를 반환하며, await
키워드를 사용하면 비동기 코드를 동기적으로 작성하는 것처럼 만들 수 있어 가독성이 향상됩니다.
async function load() { const data = await fetchData(); console.log(data); // "데이터 로딩 완료" } load();
동기 코드처럼 보이지만 내부적으로는 여전히 비동기적으로 작동합니다. 오류 처리도 try/catch 문을 통해 간편하게 할 수 있습니다.
비동기 함수의 타입 명시
TypeScript에서는 비동기 함수의 반환 타입을 Promise<타입>
형태로 명시할 수 있습니다.
async function getUser(): Promise<{ id: number; name: string }> { return { id: 1, name: "홍길동" }; }
이처럼 정확한 타입 정의는 실무에서 타입 안전성과 유지보수성을 높이는 데 도움이 됩니다.
실제 예제: fetch를 이용한 API 호출
TypeScript에서 fetch
API를 사용할 때도 비동기 방식으로 데이터를 요청할 수 있습니다. 응답 데이터에 대한 타입도 명확히 지정할 수 있습니다.
interface Post { id: number; title: string; body: string; } async function fetchPost(id: number): Promise{ const response = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`); if (!response.ok) throw new Error("네트워크 응답 실패"); const data = await response.json(); return data; } fetchPost(1).then(post => { console.log(post.title); });
이 예제는 네트워크 요청의 성공 여부와 JSON 파싱을 안전하게 처리하며, API 응답 타입도 명확하게 관리합니다.
비동기 처리에서의 에러 핸들링
비동기 코드에서는 try/catch
블록을 사용해 오류를 쉽게 처리할 수 있습니다.
async function safeFetch() { try { const data = await fetchData(); console.log("결과:", data); } catch (error) { console.error("에러 발생:", error); } }
실무에서는 네트워크 실패, 파싱 오류 등 다양한 문제가 발생할 수 있기 때문에 에러 처리는 필수입니다.
Promise.all과 병렬 처리
여러 개의 비동기 작업을 병렬로 처리할 때는 Promise.all
을 사용하면 효율적입니다.
async function loadAll() { const [post1, post2] = await Promise.all([fetchPost(1), fetchPost(2)]); console.log(post1.title, post2.title); }
이 방식은 동시에 여러 작업을 처리하여 성능을 향상시킬 수 있습니다.
async/await vs Promise 체이닝
.then()
체이닝 방식과 async/await
방식은 기능적으로 같지만, async/await는 가독성이 높고 에러 핸들링이 간편한 장점이 있습니다.
- then 체이닝: 짧은 코드에는 유리하지만 중첩되면 가독성이 떨어짐
- async/await: 복잡한 로직에서도 흐름을 직관적으로 파악 가능
결론: 타입스크립트에서의 안정적인 비동기 처리
TypeScript의 비동기 프로그래밍은 Promise
와 async/await
을 통해 직관적이고 안전한 코드를 작성할 수 있도록 도와줍니다. 특히 타입 명시와 에러 처리를 통해 런타임 오류를 줄이고, 안정적인 시스템을 구축하는 데 기여합니다.
실무 프로젝트에서는 응답 타입을 인터페이스로 정의하고, try/catch를 통한 예외 처리를 표준으로 삼는 것이 좋습니다. 또한 Promise.all
과 같은 병렬 처리 기술도 성능 향상에 유리하게 작용합니다.