전공자가 아닌 취준생에게는 검증을 위한 추가의 과정을 거치는 경우가 꽤 있다.
그 사람이 CS(Computer Science)에 대한 기본적인 지식을 알고 있는지 질문을 하게 되는데,
답변을 흐지부지하게 하게 되면 마이너스가 될 수 있다는 것은 누구나 아는 사실..
물론 회사에 따라서는 기초적인 것을, 혹은 심화를 물어보기는 한다.
나의 경우 초반의 생각보다? 쉬운 질문으로 면접을 진행한 지라 별 다른 대비를 하고 있지 않다가,
후반에 왕창 깨진 적이 있어서 대비의 중요성을 몸소 깨닫게 되었다..
그럼 질문들 중에 본인이 좀 모른다 싶은 것,
헷깔려 하는 것을 위주로 정리를 해볼까 한다.
동기와 비동기에 대한 개념
동기를 영어로 하면: synchronous(동시에 일어나는)
비동기를 영어로 하면: asynchronous(동시에 일어나지 않는)
이다. 영어 단어만 봐서는 뭔가 비동기가 동시에 일어나지 않으니까 순서대로 작동한다라고
의미를 생각할 수 있고, 처음에는 나도 그랬지만, 실제로는 그 의미와 전혀 다르다!
동기의 동시에 일어난다는 의미는 동시에 똑같이 진행된다는 의미,
그러니까 웹으로 치자면 Request(요청)와 Response(응답)가 동시에 진행된다는 의미이다.
아이폰의 동기화를 생각하면 이해가 쉽다.
물론 엄밀히 말해 통신에는 주체되는 것 간의 오고 가는 행위에 시간이 걸리는 것은 엄밀한 사실이니,
Request 이후 Response에 시간이 걸리기는 한다. 이를 도표로 쉽게 나타낸 것을 찾았는데,
아래를 보시면 좀 더 쉽게 이해가 되리라 생각한다.

통신에서 하나의 작업은 요청과 응답이 상호작용해야 수행된다고 할 수 있다.
동기적 통신은 좌측 그림과 같이 한 번의 요청이 왔을 경우, 해당 요청에 대한 응답이 수신되어서
하나의 작업이 수행 완료가 되어야 다음 요청이 진행될 수 있다.
하지만 비 동기식 통신방법은 이러한 순서가 보장되지 않는다.
요청을 받은 상대가 응답을 늦게 하든 빠르게 하든, 지속적으로 요청을 계속 하게 된다.
하나의 작업이 수행 완료가 되지 않아도, 다음 요청을 계속 보낸다고 생각하면 된다.
시간의 흐름을 기준으로 이해를 하면 두 통신간의 차이는 명확해진다
순서가 보장되는 동기적(Synchronous)의 각 비즈니스 로직(요청)의 통신을 나타내면 좌측 그림과 같다.
한꺼번에 요청이 진행되지 않고, 차례대로 하나의 작업이 완료 될 때마다 차례대로로 진행된다.
반대로 비동기적(Asynchronous)는 각 요청하는 비즈니스 로직이 동시다발적으로 진행된다.

이 그림을 통해 아마 동기 그리고 비동기 통신 간의 장단점도 찾으실 수 있을 것이다.
비동기 통신은 한꺼번에 많은 작업을 짧은 시간안에 처리할 수 있다는 점이다.
그럼 시간이 더 걸리는 동기적 통신을 하는 이유가 뭘까?
모든 기술에는 이유가 있는 법.
Javascript로 작성한 한 비즈니스 로직을 보면서 이해를 하면 더 쉬울 거라 생각이 들어 예시를 들겠다.
아래는 퀴즈 맞추기 게시판에서 본인이 등록한 글을 수정하는 한 비즈니스 로직이다.
해당 스크립트에서는 "동기적" 작용을 하기 위해 작성된 몇몇 메소드를 찾을 수 있는데,
async() => { } 라는 커다란 함수 내에 = await prisma 와 같은 구문이 중간 중간에 있는 모습을 관찰할 수 있다.
async() 는 비동기 함수를 정의하는 것으로 이 안에서는 비동기로 작업이 수행이 된다.
그러나!!
await가 들어간 구문은 예외적으로 동기적으로 작동하며,
해당 구문이 작업 완료되기 전 까진 아래 코드로 넘어가지 않게 된다.
router.patch('/quizzes/:quizId', upload.single('image'), memberMiddleware, async (req, res, next) => {
const { title, content } = await checkQuizzes.validateAsync(req.body) // body로부터 수정된 title과 content을 받음
const { quizId } = req.params; // URL에서 quizId를 추출
const userId = req.member.userId // 로그인 된 사용자 id
// 게시된 퀴즈가 있는지 존재 여부를 확인
let quiz = await prisma.quizzes.findUnique({
where: { quizId: +quizId },
});
if (!quiz) throw { name: "NoneData" } // 수정
// 퀴즈 수정을 위한 데이터 준비
const updateQuiz = {
title: title || quiz.title, // 새로운 제목을 입력하면 사용하고, 그렇지 않다면 이전 제목을 유지
content: content || quiz.content, // 새로운 내용을 입력하면 사용하고, 그렇지 않다면 이전 내용을 유지
};
// 퀴즈를 업데이트
quiz = await prisma.quizzes.update({
where: { quizId: +quizId },
data: updateQuiz,
});
// 클라이언트에게 응답
return res.status(200).json({ message: "퀴즈를 수정하였습니다.", data: quiz });
});
한 게시글이 수정되는 로직 순서를 간단히 생각해보자. 먼저,
1. 사용자가 수정입력한 내용을 받아온 다음,
2. 서버 DB내 기존 게시글을 찾아내야 한다.
3. 그리고 수정입력한 내용을 제목과 내용 등으로 분리한 다음,
4. 서버 DB에 이를 넣어서 업데이트 하면..
된다. 사람마다 순서가 조금 씩 다를 수는 있어도,
DB내에서 데이터를 가져오고 수정해야 한다는 것은 모두 같을 것이다.
문제는, DB에서 가져오고 수정하는 과정은 시간이 꽤 걸린다는 것!
만약 DB에서 기존 게시글을 가져오지도 못한 상태에서, 다음 로직으로 넘어간다고 가정해 보자.
그럼, 수정을 해야할 게시글의 위치를 모르므로, 제목과 내용 모두 넣지 못해 붕 떠버리고 만다.
이렇게 될 경우 경로를 찾지 못해 에러가 발생하게 된다.
따라서 반드시 먼저 수행이 완료되어야 할 로직이 존재한다면,
동기라는 조건을 걸어줘야 한다.
'TIL' 카테고리의 다른 글
| 세션(Session)과 토큰(Token)의 차이를 알아보자 (0) | 2024.08.01 |
|---|---|
| 프로세스와 스레드(thread)의 차이, 그리고 멀티 스레드란? (5) | 2024.07.24 |
| 기술 면접 예상 질문 대비: DI와 의존성 주입 (10) | 2024.07.20 |
| DP(Dynamic Programing: 동적 계획법)에 대해 이해해보자 (0) | 2024.07.09 |
| "Index가 뭐에요?" 라는 질문에 깨진 기념으로 (0) | 2024.07.06 |