✅ 동기(Synchronous)란?
작업이 순차적으로 진행되며, 하나의 작업이 완료되기 전에는 다음 작업으로 넘어가지 않습니다.
예시
A 작업이 끝나야만 B 작업을 시작할 수 있는 구조입니다.
주요 특징
- 순차적 실행: 하나의 작업이 끝나야 다음 작업으로 진행됨
- 직관적인 흐름: 코드 흐름이 간단하고 이해하기 쉬움
- 성능 저하 가능성: 시간이 오래 걸리는 작업이 전체 흐름을 지연시킬 수 있음
언제 사용하면 좋을까?
- 작업의 순서가 중요한 경우
- 이전 작업의 결과가 바로 다음 작업에 필요할 때
- 간단한 스크립트나 소규모 프로그램에 적합
✅ 비동기(Asynchronous)란?
작업이 서로 독립적으로 실행되며, 하나의 작업이 끝나기를 기다리지 않고 다음 작업을 수행할 수 있는 방식입니다.
예시
A 작업이 완료되기를 기다리는 동안 B 작업도 같이 수행됩니다.
주요 특징
- 병렬적인 작업 처리 가능
- 대기 시간 최소화: 사용자가 느끼는 응답 속도가 빨라짐
- 복잡한 구조: 콜백, 프로미스, 예외 처리 등으로 코드가 복잡해질 수 있음
언제 사용하면 좋을까?
- 네트워크 요청, 파일 읽기/쓰기 등 시간이 오래 걸리는 작업
- 여러 작업을 동시에 처리해야 할 때
- UI 응답성을 유지해야 할 때
- 대규모 트래픽을 처리하는 서버 애플리케이션
🔁 주요 비동기 프로그래밍 패턴
1. Callback
작업 완료 시 특정 함수를 호출하는 방식
- 장점: 간단한 구조
- 단점: 콜백 지옥(Callback Hell) 발생 가능
function getData(callback) {
setTimeout(() => {
const data = "데이터";
console.log("1. 데이터를 가져왔습니다.");
callback(data);
}, 1000);
}
function processData(data, callback) {
setTimeout(() => {
const processed = data + " → 처리됨";
console.log("2. 데이터를 처리했습니다.");
callback(processed);
}, 1000);
}
function displayResult(result) {
console.log("3. 결과:", result);
}
// 실행
getData(function(data) {
processData(data, function(result) {
displayResult(result);
});
});
--------------------------------
(1초 후) 1. 데이터를 가져왔습니다.
(1초 후) 2. 데이터를 처리했습니다.
3. 결과: 데이터 → 처리됨
🧩 설명
- getData() → 1초 후 "데이터" 반환
- 반환된 데이터를 processData()로 넘김
- 처리된 결과를 displayResult()에서 출력
2. Promise / Future
작업의 성공/실패 결과를 약속하는 객체를 사용하여 흐름 제어
- 장점: 체이닝(Chaining) 으로 가독성 향상
- 단점: 예외 처리가 복잡할 수 있음
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("데이터");
}, 1000);
});
}
getData()
.then(data => console.log(data))
.catch(error => console.error(error));
🧩 설명
- getData()는 1초 후 "데이터"를 반환하는 비동기 함수
- .then() 안의 콜백은 작업이 성공(resolve) 되었을 때 실행됩니다.
- .catch()는 작업이 실패(reject) 했을 때 에러를 처리합니다.
3. Async / Await
비동기 코드를 동기 코드처럼 작성할 수 있게 해주는 문법
- 장점: 가독성 좋고 직관적
- 단점: 구형 환경이나 일부 언어에서는 지원하지 않을 수 있음
async function main() {
try {
const data = await getData();
const processed = await processData(data);
displayResult(processed);
} catch (error) {
console.error("에러 발생:", error);
}
}
main();
⚠️ 비동기 프로그래밍 시 주의할 점
- 동시성 문제(Concurrency)
- 여러 작업이 동시에 실행되면서 예상치 못한 결과가 발생할 수 있음
- 복잡한 흐름 제어
- 예외 처리, 상태 관리가 까다로울 수 있음
- 과도한 사용은 오히려 성능 저하
- 필요하지 않은 곳에 비동기를 사용하면 오히려 디버깅이 어려워지고 CPU 리소스 낭비
- 블로킹 코드 주의
- 비동기 흐름 중 동기 함수가 전체 흐름을 막는 경우 있음
| 항목 | 동기(Synchronous) | 비동기(Asynchronous) |
| 실행 방식 | 순차적 | 병렬 가능 |
| 코드 흐름 | 단순, 직관적 | 복잡하지만 유연 |
| 성능 | 작업 지연 시 전체 지연 | 작업 병렬 처리로 성능 향상 |
| 적합한 상황 | 작업 순서 중요, 단순한 로직 | I/O, 대기 많은 작업, 대규모 처리 필요 |
'개발자 면접 노트' 카테고리의 다른 글
| Kotlin과 같은 등급은 Java인가 Spring인가? (3) | 2025.06.25 |
|---|---|
| Spring - 의존성 주입(DI)의 종류 (0) | 2025.06.25 |
| Spring - 의존성 주입(DI) (0) | 2025.06.25 |
| AJAX를 사용하는 이유 (1) | 2025.06.24 |
| 백엔드 vs 프론트엔드 (1) | 2025.06.24 |