Reference :  CS 공부 비서, 티스토리


Q&A

Q. 컴파일러와 인터프리터의 차이가 무엇인가요?

A. 나의 답변

* 컴파일러는 인풋언어(고급어)를 객체어(기계어)로 변환하고, 하드웨어에 종속적이다. 번역 진행 시 전체 코드를 검사한 뒤에 실행한다.
반면 인터프리터는 line by line으로 번역을 진행하고, 하드웨어에 종속되지 않는 특징이 있다. 


Best Answers

 

★ㅇ*님의 답변
컴파일러와 인터프린터는 사람이 작성한 코드(고급언어)를 컴퓨터가 이해할 수 있는 언어(기계어)로 변환하는 작업을 수행해주는 역할을 한다. 컴파일의 경우 고급언어를 한 번에 번역한다.

인터프린터의 경우 고급언어를 한 줄씩 번역을 진행하기 때문에 컴파일 보다 실행시간이 빠르다는 장점이 있다. 그러나 번역을 할 때 실행파일을 생성하지 않기 때문에 매번 실행할 때마다 같은 번역작업을 반복해서 실행해야 되는 단점이 있고, 이러한 문제 때문에 컴파일러를 사용하는 언어보다 실행속도가 느리다.
그럼에도 불구하고 인터프린터를 사용하는 이유는 모든 플랫폼에 종속되지 않는다는 장점을 갖기 때문에 호환문제에서 자유롭다.


★홍*님의 답변
<컴파일러(compiler)>
전체 파일을 스캔하여 한꺼번에 번역한다.
초기 스캔시간이 오래 걸리지만, 한번 실행 파일이 만들어지고 나면 빠르다.
기계어 번역과정에서 더 많은 메모리를 사용한다.
전체 코드를 스캔하는 과정에서 모든 오류를 한꺼번에 출력해주기 때문에 실행 전에 오류를 알 수 있다.
대표적인 언어로 C, C++, JAVA 등이 있다.

<인터프리터(interpreter)>
프로그램 실행시 한 번에 한 문장씩 번역한다.
한번에 한문장씩 번역후 실행 시키기 때문에 실행 시간이 느리다.
컴파일러와 같은 오브젝트 코드 생성과정이 없기 때문에 메모리 효율이 좋다.
프로그램을 실행시키고 나서 오류를 발견하면 바로 실행을 중지 시킨다. 실행 후에 오류를 알 수 있다.
대표적인 언어로 Python, Ruby, Javascript 등이 있다.




★최*님의 답변
컴파일러는 고급 언어로 작성된 프로그램 전체를 일괄적으로 기계어로 번역하는 도구이다. 컴파일 하는 데 시간이 소모되지만, 실행 시에는 필요한 정보들이 모두 미리 계산되어 있기 때문에 인터프리터 방식에 비해 빠르다는 장점이 있다. C, C++, 포트란, 파스칼 등의 언어가 컴파일러를 사용한다.

인터프리터는 실행문을 한 문장씩 번역하면서 실행하는 구조이다. 그에 따라서 바로 실행이 가능하지만, 전체 실행 시간은 컴파일러에 비해서 더 오래 걸린다. 추가적으로 메모리 사용도 컴파일러에 비해서 비효율적인 면이 있다. BASIC, PHP, 펄, 파이썬 등의 언어가 인터프리터를 사용한다.

이밖에도 자바같은 언어는 컴파일러와 인터프리터의 중간 형태의 언어를 사용한다고 볼 수 있다. 이를 혼합형 방식이라고 하는데, 고급 언어를 컴파일해 중간 언어로 번역하고 인터프리터에 의해 번역을 하면서 실행하는 방식을 의미한다. 자바의 경우 자바 가상 머신이 이해할 수 있는 자바 바이트코드를 생성하고, 자바 가상 머신이 이를 실행하는 식으로 구동된다.




★황*님의 답변
작성한 프로그램을 빌드 혹은 실행하는 방법으로는 컴파일러방식과 인터프리터 방식이 있다. 컴파일러와 인터프리터는 고급언어로 작성된 원시 프로그램을 목적 프로그램으로 번역하는 프로그램이며, 프로그램 번역 방식에 따라 구분된다.

"컴파일러"는 고급 언어(C, C++, JAVA)등으로 작성 된 소스 코드를 컴퓨터가 읽을 수 있는 저급 언어(기계어, 어셈블리어)로 번역해주는 프로그램이다. 컴파일러의 경우 크게 4가지 과정(전처리 - 컴파일 - 어셈블리 - 링킹)을 통해 실행 가능한 산출물로 만들어진다.

1. 전처리 
전처리기를 통해 전처리된 소스 코드로 변환하는 과정이다. 주석 제거, 헤더 파일 복사후 삽입, 매크로 치환 및 적용등을 진행합니다.

2. 컴파일
전처리된 소스 코드를 어셈블리어로 변환한다. 언어의 문법검사 정적(Data,BSS)인 영역들의 메모리 할당을 수행한다.

3. 어셈블리
어셈블리어 파일을 오브젝트 파일로 변환하는 과정이다. 오브젝트 파일은 기계어로 쓰여 있으며 보통의 포맷 종류는 PE(Window), ELF(Linux)가 존재한다.

4. 링킹 과정
컴파일러에 존재하는 링커를 통해 오브젝트 파일들을 묶어 실행 파일로 만드는 과정이다. 이 과정에서 오브젝트 파일들과 프로그램에서 사용하는 라이브러리 파일들을 링크하여 하나의 실행 파일을 만든다. 이러한 과정을 거쳐 우리가 작성한 고급언어들을 실행 가능한 파일로 만드는 것이 컴파일러가 수행하는 역할이다.


"인터프리터"는 고급언어로 작성된 프로그램을 한 줄 단위로 받아들여 번역한 뒤 번역과 동시에 프로그램을 한 줄 단위로 즉시 실행시켜 주는 프로그램이다. 줄 단위로 번역, 실행되기 때문에 시분할 시스템에 유용하며 한단계씩 테스트와 수정을 하며 진행시키는데에 적합하다.

1. 소스 코드를 직접 실행한다.
2. 첫번째 줄을 읽는다.
3. 기계어 명령어로 번역한후 CPU에 바로 돌린다.
4. 프로그램 한 줄을 실행한다.

둘의 차이점은
컴파일러 - 전체 단위로 번역함
인터프리터 - 한 줄 단위로 번역함

컴파일러 - 목적 프로그램을 생성함
인터프리터 - 생성하지 않음

컴파일러 - 실행속도의 경우 한번에 번역해서 실행하기 때문에 빠름
인터프리터 - 한 줄씩 읽어내기 때문에 느림

컴파일러 - 번역속도가 느림
인터프리터 - 번역속도가 빠름





★김*님의 답변
컴파일러는 프로그램 전체를 스캔하여 이를 모두 기계어로 번역한다. 
하지만 전체 실행 시간만 따지고 보면 인터프리터 보다 빠르다. 왜냐하면 컴파일러는 초기 스캔을 마치면 실행파일을 만들어 놓고 다음에 실행할때 이전에 만들어 놓았던 실행파일을 실행하기 때문이다.

인터프리터는 프로그램 실행시 한 번에 한 문장씩 번역한다. 그렇기 때문에 한번에 전체를 스캔하고 실행파일을 만들어서 실행하는 컴파일러보다 실행시간이 더 걸린다. 그럴 수 밖에 없다고 본다. 한 문장 읽고 번역하여 실행시키는 과정을 반복하는게 만들어 놓은 실행파일을 한번 실행시키는 것보다 빠르긴 힘들어 보인다. 하지만 인터프리터는 메모리 효율이 좋다.

 




★권*님의 답변
2가지의 차이를 설명하기 이전에 컴퓨터의 시작의 역사를 조금 되짚어보겠다. 흔히 알려진 컴퓨터 OS의 시작은 유닉스이다. 그리고 유닉스가 유료화가 되면서 오픈소스로 만들어진 가장 잘 알려진 리눅스가 된다.

이러한 리눅스에서는 콘솔 창에서 어떤 명령을 수행할지에 대한 명령어 처리 시스템인 셸이 존재한다. 간단하게는 디렉터리 위치 변경, 파일 목록 출력, 문자열 탐색과 같은 명령어들이 있다. 이러한 명령어 집합을 파일로 만들어서 해당 파일을 실행하면 명령어들을 순차적으로 셸에 실행시켜준다. 이를 셸 프로그래밍이라고도 하고, 이는 인터프린터이다.
프로그램 파일의 명령어를 단순히 순차적으로 실행시켜주는 것이다. 잘 알려진 프로그래밍 언어로는 자바스크립트,파이썬,파워쉘, 등이 있을 것이다.


이에 반에 컴파일러는 인터프리터의 문자열 수준의 명령어가 아닌, 기계어 수준의 명령어 집합으로 만드는 것이다. 여기서 기계어란 컴퓨터가 (CPU) 더하기 연산이나 빼기 연산, 레지스터 복사 같은 명령어들을 얘기한다. 컴파일러로 컴파일 할 경우 기계어이다 보니 인터프린터보다 속도가 훨씬 빠르다는 장점이있다. 이런 컴파일러 언어의 예로는 C언어, C++ 가 대표적이다.

참고로 C#이나 Java의 경우, 인터프린터와 컴파일러의 중간에 있다.
Java를 예로 들면, Java 개발사에는 JVM이라는 프로그램을 만들어서 배포한다. 이 JVM은 인터프린터와 같은 명령어 실행기이다. 그리고 Java를 이용하여 프로그램을 만드는 개발자의 경우 프로그래밍을 하고 코드를 실행 시 컵파일이 된다. 컴파일 시 기계어가 아닌 JVM에서 실행시켜줄 수 있는 바이트 코드가 되어 JVM에서 실행된다. 이는 한 코드로 모든 운영체제에서 실행시키려는 자바의 철학이다.
따라서 java 개발사에서는 JVM를 각 운영체제 별로 만들어야 한다. 그리고 프로그램 개발자의 경우 한 코드로 모든 운영체제에서 돌릴 수 있다. 이러한 Java C#은 굳이 따지자면 컴파일러 언어에 더 가깝다.





★박*님의 답변
1. 컴파일러
: 전체 프로그램을 스캔해 한번에 기계어로 번역한다, 코드 분석에 시간이 많이 걸리는 대신 컴파일 후 실행시간이 빠르다. 컴파일러는 기계어와 코드 사이의 중간 코드를 생성하기 때문에 더 많은 메모리가 필요하다.

2.인터프리터
: 한 번에 하나의 프로그램 명령문을 기계어로 번역한다. 소스 코드를 분석하는데 상대적으로 적은 시간이 걸리지만 코드가 실행되는 시간은 더 오래 걸린다. 중간에 기계어와 코드 사이를 연결하는 코드를 생성하지 않아 메모리를 적게 쓴다.

컴파일러는 C, C++ 등에서 쓰이고, 인터프리너틑 JS, Python등에서 대표적으로 쓰인다.





★(*님의 답변
컴파일러는 소스 코드 n줄을 기계 코드로 한 번에 변환한 후 실행 파일로 만들어 해당 실행 파일만 있으면 실행할 수 있게 하는 것이고 인터프리터는 소스 코드 한 줄 한 줄 실행되는 순간 순간에 기계 코드로 변환하여 바로 실행한다는 것이다.

한 번 컴파일 하여 생성된 실행 파일만 있으면 빨리 실행할 수 있다는 장점이 있지만 컴파일 할 때 시간이 걸린다는 단점이 있고 인터프리터는 컴파일을 하지 않기 때문에 바로 바로 코드의 결과를 확인할 수 있다는 장점이 있지만 한줄을 기계 코드로 변환 후 실행하고 다음 한 줄을 기계 코드로 변환 후 실행하기 때문에 컴파일 후 생성된 파일을 실행하는 것보다는 느리다는 단점이 있다.




★서*님의 답변
컴파일러와 인터프리터는 모두 초기 컴퓨터의 서로 다른 cpu의 서로 다른 어셈블리어를 더 나은 방식으로 통합하기 위해 만들어졌다. 즉 서로 같은 명령을 서로 다른 어셈블리어로 번역해 주기 위해 만들어진 것이다.


<컴파일러(compiler)> 

컴파일러는 프로그램 전체를 스캔하여 이를 모두 기계어로 번역한다. 전체를 스캔하기 때문에 대개 컴파일러는 초기 스캔 시간이 오래 걸린다. 하지만 전체 실행 시간만 따지고 보면 인터프리터 보다 빠르다. 왜냐하면 컴파일러는 초기 스캔을 마치면 실행파일을 만들어 놓고 다음에 실행할때 이전에 만들어 놓았던 실행파일을 실행하기 때문이다. 하지만 단점도 있다. 컴파일러는 고급언어로 작성된 소스를 기계어로 번역하고 이 과정에서 오브젝트 코드(Object Code)라는 파일을 만드는데 이 오브젝트 코드를 묶어서 하나의 실행 파일로 다시 만드는 링킹(Linking) 이라는 작업을 해야한다. 설명만 딱 봐도 뚝딱하고 번역을 하는것 같아 보이진 않는다. 이때문에 컴파일러는 통상적으로 인터프리터 보다 많은 메모리를 사용해야 한다. 또한 컴파일러는 오류 메시지를 생성할때 전체 코드를 검사한 후에 오류 메시지를 생성한다. 그래서 실행 전에 오류를 발견 할 수 있다. 대표적인 언어로 C,C++,JAVA 등이 있다.

<인터프리터(interpreter)>

컴파일러와는 반대로 인터프리터는 프로그램 실행시 한 번에 한 문장씩 번역한다. 그렇기 때문에 한번에 전체를 스캔하고 실행파일을 만들어서 실행하는 컴파일러보다 실행시간이 더 걸린다. 그럴 수 밖에 없다고 본다. 한 문장 읽고 번역하여 실행시키는 과정을 반복하는게 만들어 놓은 실행파일을 한번 실행시키는 것보다 빠르긴 힘들어 보인다. 하지만 인터프리터는 메모리 효율이 좋다. 왜냐하면 컴파일러처럼 목적코드를 만들지도 않고, 링킹 과정도 거치지 않기 때문이다. 이 때문에 인터프리터는 메모리 사용에 컴파일러 보다 더 효율적인 모습을 보인다. 인터프리터는 오류 메시지 생성과정이 컴파일러와 다르다. 인터프리터는 한번에 한문장씩 번역하기 때문에 프로그램을 실행시키고 한 문장씩 번역될때 오류를 만나게 되면 바로 프로그램을 중지한다. 그래서 프로그램을 실행해봐야지만 오류 발견이 가능하다. 대표적인 언어로 Python, Ruby, Javascript 등이 있다.





★?*님의 답변
<컴파일러>
- 프로그램 전체를 스캔하여 이를 모두 기계어로 번역
- 전체를 스캔하기 때문에 초기 스캔 시간이 오래 걸리지만 전체 실행 시간만 따지고 보면 인터프리터보다 빠름
- 프로그램 실행 전에 오류를 알 수 있음
- 대표적인 언어로 C, C++, JAVA 등이 있음

<인터프리터>
- 프로그램 실행 시 한 번에 한 문장씩 번역
- 한번에 전체를 스캔하고 실행 파일을 만들어서 실행하는 컴파일러보다 실행 시간이 더 걸림
- 프로그램 실행 후에 오류를 알 수 있음
- 대표적인 언어로 Python, Ruby, Javascript 등이 있음

Reference :  CS 공부 비서, midas님의 velog


Q&A

Q.  트랜잭션의 각 격리 수준에 대해서 설명하고, 각 수준에서 일어날 수 있는 문제에 대해 설명해주세요

A. 나의 답변

* 트랜잭션은 데이터베이스의 논리적 수행 단위라고 할 수 있는데, 가지고 있는 여러가지 특징 중 격리성에 대한 특징이 있다.
격리성이란 트랜잭션들이 동시에 실행될 때 서로 영향을 미치지 않도록 격리하는 성질을 의미한다.

* 격리 수준은 4가지로 나눌 수 있는데, 하위 단계로 갈수록 격리 수준이 높아지지만 동시처리의 성능은 떨어진다.
1) Read Uncommitted
2) Read Committed
3) Repeatable Read
4) Serializable 


Best Answers

★김*님의 답변
격리성 관련 문제점을 해결하기 위해서 ANSI 표준에서 트랜잭션의 격리성과 동시 처리 성능 사이에 Trade-off 를 두고 4단계 격리수준을 나눴다.

0 - 한 트랜잭션의 변경된 내용을 commit이나 rollback과 상관 없이 다른 트랜잭션에서 읽을 수 있다
문제점 : 더티 리드(Dirty Read) 발생 가능성 존재한다, 데이터 정합성에 문제가 많다

1 - commit이 완료된 데이터만 조회 가능하다
문제점 : Non-repeatable Read 발생 가능성 존재한다, 잠금이 발생하므로 속도나 성능에 있어서 느릴 수 있다, 트랜잭션 간 고립성을 완전히 보장하지 못한다

2 - 트랜잭션이 시작되기 전에 커밋된 내용에 관해서만 조회할 수 있다
문제점 : 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정이 불가능하다, 잠금이 적용되는 범위가 넓어져 성능과 속도가 느려진다

3 - 한 트랜잭션을 다른 트랜잭션으로부터 완전히 분리한다
문제점 : 동시처리 능력이 다른 격리수준보다 떨어지며, 성능저하 발생한다


★김*님의 답변
트랜잭션 격리 수준이란 여러 트랜잭션 동시 처리시, 서로 얼마나 고립되었는지를 나타낸 것으로, 한 트랜잭션이 다른 트랜잭션에 변경한 데이터를 볼 수 있도록 허용할 것인지 결정하는 것이다. ACID와 같은 특성으로 트랜잭션이 독립적인 수행을 하도록 Locking을 통해 다른 트랜잭션 관여 여부를 막는데, 효율적인 Locking을 위해 격리수준을 나눈다.

격리 수준 (Isolatio) 종류
레벨 0. Read Uncommitted
- Select 문장 수행 중 해당 데이터에 Shared Lock이 걸리지 않음
- 일관성 유지 불가
- 문제점 : Dirty Read
- user1이 data A 를 B로 변경하는 도중 user2가 data를 B로 읽게되는 현상 (커밋 X)

레벨 1. Read Committed
- Select 문장 수행 중 해당 데이터에 Shared Lock이 걸림
- 트랜잭션 수행 중 다른 트랜잭션이 접근할 수 없어 대기
- 커밋된 트랜잭션만 조회 가능
- Non-Repeatable Read 발생
- A 트랜잭션에서 1번 데이터 조회 : 1
- B 트랜잭션에서 1번 데이터를 2로 바꾸고 커밋
- A 트랜잭션에서 1번 데이터 조회 : 2

레벨 2. Repeatable Read
- 트랜잭션 완료 전까지 SELECT 내의 모든 데이터에 Shared Lock
- 트랜잭션이 범위 내에 조회한 데이터 내용이 항상 동일함을 보장

레벨 3. Serializable
- 트랜잭션 완료 전까지 SELECT 내의 모든 데이터에 Shared Lock
- 완벽한 읽기 일관성 모드 제공



★권*님의 답변
트랜잭션의 각 격리 수준에 대해 얘기하기 이전에 몇 가지 개념을 정리하려 한다. 트랜잭션이란 데이터의 수정/읽기하는 명령을 의미한다.
커밋은 데이터의 영구적인 저장을 의미한다. 
DB의 각 격리수준이 나오는 이유는 DB가 값을 수정하고, 다른 트렌젝션이 값을 읽고 롤백할 경우 데이터의 일관성을 잃는 문제가 있다. 이런 문제들을 갖고 어떤 방법론을 쓸 건지 나눈 것이다.
예를들면 데이터를 수정할 때 데이터를 수정 전의 값 기준으로 한다. 데이터를 수정 후의 기준으로 한다. 데이터를 커밋하기 이전의 기준으로 한다. 이후로 한다. 와 같이 나눠진다.

자세히 살펴보면 다음과 같은 방법이 있다.

READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE

READ UNCOMMITTED
커밋하지 않아도 수정한 결과를 계산 값으로 쓴다. 이때 위에 말한 것처럼 롤백을 사용할 경우 데이터의 일관성을 잃는다.


READ COMMITTED
커밋한 결과만으로 값을 쓴다. 그렇다면 데이터의 일관성이 유지되지만 또 다른 문제점이 존재한다. DB가 멀티스레드로 트렌젝션을 동시에 처리할 때이다. 이럴 경우 동기화가 되지않아서 어떤 것은 수정되기 이전 값을 쓰고 이후에 커밋되어 수정된 값을 쓰고 같은 문제가 발생한다.


REPEATABLE READ
트랜잭션이 시작되면 각 트랜잭션이 발생한 시점의 데이터들을 저장한다. 그리고 연산 시 발생한 시점의 데이터만 사용한다. 발생하는 문제로데이터 업데이트할 경우 나중의 트랜잭션만 수행되고, 처음에 시작된 트랜잭션은 무시된다. 또 각 시점별 데이터를 저장하므로 용량 문제가 발생할 수 있다.


SERIALIZABLE
읽기와 수정 모두 동기화를 시켜서 엄격하게 관리한다. 이렇게 할 경우 위의 모든 문제를 해결할 수 있지만 한 작업이 길게 이어지는데 데이터를 오랫동안 사용할 경우 계산낭비가 발생한다.


★.*님의 답변
# 트랜잭션 격리수준(isolation level)이란
- 특정 트랜잭션이 다른 트랜잭션에 변경한 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것

## 격리수준
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE

### READ UNCOMMITTED
- 어떤 트랜잭션의 변경내용이 COMMIT이나 ROLLBACK과 상관없이 다른 트랜잭션에서 보여진다.
- 데이터 정합성에 문제가 많아, 격리수준으로 인정하지 않음

### READ COMMITTED
- 어떤 트랜잭션의 변경 내용이 COMMIT 되어야만 다른 트랜잭션에서 조회할 수 있다.

### REPETABLE READ
- 트랜잭션이 시작되기 전에 커밋된 내용에 대해서만 조회할 수 있는 격리수준

### REPEATABLE READ
- UPDATE 부정합: 변경을 수행할 로우에 대해 잠금이 필요하다.
- Phantom READ: 한 트랜잭션 내에서 같은 쿼리를 두 번 실행했는데, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다.

### SERIALIZABLE
- 가장 단순하고 가장 엄격한 격리수준이다.

 



★황*님의 답변
트랜잭션은 데이터의 무모순성을 보장하기 위한 기능입니다. 트랜잭션은 논리적인 작업 셋 자체가 100% 적용되거나(COMMIT) 또는 아무것도 적용되지 않아야 함(ROLLBACK)을 보장해주는 것입니다.
트랜잭션의 격리 수준이란 동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것입니다.

격리 수준은 다음과 같이 4가지로 정의할 수 있습니다.
READ UNCOMMITTED(커밋되지 않은 읽기)
READ COMMITTED(커밋된 읽기)
REPEATABLE READ(반복 가능한 읽기)
SERIALIZABLE(직렬화 가능)

1. READ UNCOMMITED
각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있습니다.

따라서 트랜잭션 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있는 DIRTY READ현상이 발생합니다.
ex: A트랜잭션에서 값을 바꿨으나 아직 커밋되지 않은 상태에서 B트랜잭션이 해당 바뀐 값을 확인할 수 있는 문제가 발생합니다.

2. READ COMMITTED
실제 테이블 값이 아닌 Undo(잘못되었을 경우 데이터가 변경되기 전의 데이터 보관하는 곳) 영역에 백업된 레코드에서 값을 가져옵니다.

하나의 트랜잭션에서 같은 쿼리를 두 번 실행하였을 때 두 실행 조회 값이 달라질 수 있습니다.

정합성 문제가 해결된 것 같지만 부정합 문제가 발생할 수 있습니다.
ex:)A트랜잭션이 작동 도중 B트랜잭션이 해당 값을 조회 한 결과 "P"라는 결과가 나옴. 그 후 A트랜잭션이 커밋이 되면 B트랜잭션에서 조회한 결과 커밋으로 바뀐 결과가 나타남

하나의 트랜잭션 내에서 똑같은 SELECT를 수행했을 경우 항상 같은 결과를 반환해야 하는 정합성 문제에 어긋납니다.

3. REPETABLE READ
트랜잭션이 시작되기 전 커밋된 내용에 대해서만 조회할 수 있는 격리수준입니다.(트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경된 것만 읽습니다.)

부정합이 발생하지 않습니다.

그러나, PHANTOM READ(한 트랜잭션 안에서 일정범위의 레코드를 두번 이상 읽을 때, 첫 번째 쿼리에서 없던 유령 레코드가 두번째 쿼리에서 나타나는 현상)은 여전히 발생합니다.

고립화 수준을 높여 LOCK을 통해 다른 트랜잭션 시점에 다른 데이터가 추가되는 것을 막을 수 있습니다. 그러나 동시성이 저하됩니다.
(오라클은 Lock을 전혀 사용하지 않은 상태서 서로 다른 쿼리를 SCN 확인 과정을 통해 하나의 시점에 존재했던 대상으로만 집계를 수행하는 방법을 사용합니다. 동시성 저하를 하지 않으면서 일관성 유지)


4. SERIALIZABLE
새로운 트랜잭션이 읽은 데이터를 다른 트랜잭션이 갱신하거나 삭제하지 못하게 하고 중간에 새로운 레코드를 삽입 하는것을 막아줍니다.

이 Level에서는 Insert까지 막아줍니다. 다른 트랜잭션에서 이 레코드 변경을 하지 못하게 되기 때문에 동시처리 능력이 떨어지고, 성능 저하, 속도 저하 등이 발생하게 됩니다.



★정*님의 답변
트랜잭션이란, DB에 이루어지는 작업을 의미합니다. 몇 개의 작업이 한 단위를 이룰 수 있고, 이 작업들의 격리 정도를 트랜잭션의 각 격리 수준이라고 합니다.

트랜잭션의 격리 수준은 아래와 같이 4개의 단계가 있습니다.
1. Read Uncommitted
2. Read Commmitted
3. Repeatable Read
4. Serializable

1. Read Uncommitted
커밋되지 않은 트랜잭션까지 읽을 수 있는 격리 수준입니다. 사실상 격리의 개념이 존재하지 않는다고 볼 수 있습니다.


2. Read Committed
커밋된 트랜잭션을 읽을 수 있습니다. 일부 DB에서는 기본적으로 read committed가 기본 격리 단계로 사용됩니다. 데이터를 수정할 때는 수정이 완료될 때까지 lock이 적용되며, 데이터를 읽을 때는 lock이 해제됩니다. 따라서 데이터를 읽는 도중에 데이터가 변경될 수 있는 위험성이 존재합니다.


3. Repeatable Read
데이터가 수정될 때, 조회될 때 모두 lock을 겁니다. 일부 RDBMS의 기본 격리 수준으로 사용되고 있습니다. Phantom read라는 문제점이 발생할 수 있는데, 반복 조회 시 결과 집합이 달라지는 현상을 phantom read라고 합니다.


4. Serializable
가장 엄격한 단계의 격리 수준으로, 완벽한 격리 수준을 나타냅니다. 데이터를 읽거나 쓸 때, 완료될 때까지 lock을 걸게 됩니다. 하지만 이로 인하여 동시성 처리 성능이 떨어지는 문제점이 존재합니다.


★겨*님의 답변
트랜잭션의 격리 수준은 네개로 나눌 수 있다.
1. READ UNCOMMITTED
2. READ COMMITED
3. REPEATABLE READ
4. SERIALIZABLE


아래로 내려갈수록 트랜잭션 간의 고립 정도가 높아지며 성능이 떨어진다. READ UNCOMMITTED 격리수준에서는 어떤 트랜잭션의 변경내용이 Commit 이나 Rollback 과 상관없이 다른 트랜잭션에서 보여진다. 여기선 한 데이터의 값을 변경 후 커밋을 하지 않았는데 다른 트랜잭션에서 해당 데이터를 조회했을 때 변경된 값이 조회되는 더티리드 현상이 발생할 수있다.

READ COMMITTED는 어떤 트랜잭션의 변경 내용이 COMMIT 되어야만 다른 트랜잭션에서 조회할 수 있는데 이는 현재 오라클 DBMS에서 기본으로사용하고 있다.
해당 격리 수준에서는 하나의 트랜잭션 내에서 똑같은 Select 명령을 수행했을 경우 항상 같은 결과를 반환해야 한다는 Repeatable Read 정합성에 문제가 나타날 수 있다. 이를 Non-Repeatable Read 부정합 문제라고 한다.

REPEATABLE READ는 트랜잭션이 시작되기 전에 커밋된 내용에 대해서만 조회할 수 있는 격리 수준이다. MySQL DBMS에서 기본으로 사용하고 있는데, 이는 자신의 트랜잭션 번호보다 낮은 트랜잭션 번호에서 변경된(커밋된) 데이터만 보게 된다. 해당 격리 수준에서는 Update 부정합과 Phantom Read 라는 문제가 발생할 수 있다.

SERIALIZABLE은 가장 단순하고 엄격한 겨리수준이다. 해당 격리 수준에서는 읽기 작업에도 공유 잠금을 설정하게 되고, 다른 트랜잭션에서 해당 레코드를 변경할 수 없다. 이러한 특성 때문에 동시처리 능력이 다른 격리수준보다 떨어지고 성능저하가 발생하게된다.


★서*님의 답변
트랜잭션의 격리 수준이란 동시에 여러 트랜잭션이 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것으로 네가지로 정의됩니다.


1. READ UNCOMMITTED(커밋되지 않는 읽기)
2. READ COMMITED(커밋된 읽기)
3. REPEATABLE READ (반복 가능한 읽기)
4. SERIALIZABLE(직렬화 가능)


순서대로 1의 수준이 가장 낮고, 4인 직렬화 가능 단계의 수준이 가장 높습니다. 

READ UNCOMMITTED 격리 수준에서는 위 그림처럼 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 보여지게 됩니다. 하지만 이러한 수준은 트랜잭션에서 처리한 작업이 완료되지 않았음에도 불구하고 다른 트랜잭션에서 볼 수 있게 되는 현상을 야기하고, 이를 더티 리드(Dirty Read) 라고 합니다.

READ COMMITTED 격리 수준은 오라클 DBMS에서 기본적으로 사용되고 있으며 온라인 서비스에서 가장 많이 선택되는 격리 수준입니다. 이 레벨에서는 위 READ UNCOMMITTED 수준에서 발생할 수 있는 더티 리드(Dirty Read)와 같은 현상은 발생하지 않습니다. 어떠한 트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있기 때문입니다. 하만 READ COMMITTED 격리 수준에서도 "NON-REPEATABLE READ"라는 부정합 문제가 존재합니다. 즉, 하나의 트랜잭션내에서 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 "REPEATABLE READ" 정합성에 어긋나게 됩니다.

따라서 세번 째 수준인 REPEATABLE READ는 MySQL의 InnoDB 스토리지 엔진에서 기본적으로 사용되는 격리 수준입니다. 이 격리 수준에서는 READ COMMITTED 격리 수준에서 발생하는 "NON-REPEATABLE READ" 부정합이 발생하지 않습니다. 하지만 이러한 격리수준에서도 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안보였다가 하는 현상인 PHANTOM READ(PHANTOM ROW)이 발생할 수 있습니다. 

이때문에 네번째 격리수준인 SERIALIZABLE로 설정되면 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야 하며, 동시에 다른 트랜잭션은 그러한 레코드를 변경할 수 없습니다. 즉, 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없습니다. 이는 팬텀리드 현상을 해결합니다.



★김*님의 답변
격리 수준은 READ UNCOMMITTED(커밋되지 않은 읽기), READ COMMITTED(커밋된 읽기), REPEATABLE READ(반복 가능한 읽기), SERIALIZABLE(직렬화 가능) 으로 정의할 수 있습니다. 순서대로 READ UNCOMMITTED의 격리 수준이 가장 낮고 SERIALIZABLE의 격리 수준이 가장 높습니다.

READ UNCOMMITTED 격리 수준에서는 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 보여지게 됩니다. 이를 Dirty Read라고 합니다. READ COMMITTED 격리 수준에서는 어떤 트랜잭션에서 변경한 내용이 커밋되기 전까지는 다른 트랜잭션에서 변경 내역을 조회할 수 없습니다.


REPEATABLE READ는 UNDO 영역에 백업된 이전 데이터를 통해 동일한 트랜잭션 내에서는 동일한 결과를 보여줄 수 있도록 보장합니다. 이에 어긋나는 현상을 NON-REPEATABLE READ라고 합니다. 트랜잭션의 격리 수준이 SERIALIZABLE로 설정되면 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없습니다.

PHANTOM READ는 한 트랜잭션내에서 동일한 쿼리를 두 번 수행했는데, 첫 번째 쿼리에서 존재하지 않던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상입니다. 이는 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ에서 나타날 수 있습니다.


★용*님의 답변
트랜잭션을 T라고 하고 T1의 단위중 갱신구문이 있을때,


READ UNCOMMITTED는
변경된 레코드를 커밋과 롤백 여부에 상관없이 T2에서 조회할 수 있습니다.
이는 해당 격리수준이 언두로그를 활용하지 않고, 디스크에 바로 반영하기 때문입니다.

READ COMMITTED는
변경된 레코드를 커밋되기 전까지 T2에서 조회할 수 없습니다.
이는 해당 격리수준이 언두로그를 활용해 갱신이전 레코드를 유지하기 때문입니다.

REPEATABLE READ는
트랜잭션마다 ID를 부여하여 현 ID보다 작은 ID에서 갱신한 레코드의 갱신 전 레코드를 조회할 수 있게 합니다.

SERIALIZABLE은
동시에 레코드를 조회함은 가능하지만, 갱신은 불가능하며
T1이 조회하면서 T2가 갱신하는 상황도 불가합니다.

다음은, 문제를 나열하고 어떤 수준에 일어나는지 기술하겠습니다.
DIRTY READ는
T2가 T1의 롤백 이전에 레코드를 조회하는 경우에
재개된 T1의 트랜잭션이 커밋되어 T2의 조회가 온전한 조회일수도
커밋되지 않아 온전한 조회가 아닐 수도 있는 현상입니다.
READ UNCOMMITTED에만 발생합니다.

NON-REPETABLE READ는
T2가 여러번 조회하는 사이 T1이 갱신이후 커밋됬다면 T2의 마지막 조회가 일관되지 않은 현상입니다.
T1의 커밋이전까지는 T2가 언두로그를 바라보지만,
T1의 커밋이후 T2가 디스크를 바라보게 되기때문입니다.
READ UNCOMMITTED와 READ COMMITTED에서 발생합니다.
REPEATABLE READ가 극복할 수 있었던 이유는
현 ID보다 작은 ID에서 갱신한 레코드의 갱신전 레코드는 언두로그에 남아있기 때문입니다.

PHANTOM READ는
T2가 여러번 조회하는 사이 T1이 갱신을 했다면
레코드가 변하지는 않지만 추가되거나 삭제될 수 있는 현상입니다.
SERIALIZABLE을 제외한 모든 격리수준에서 발생합니다.
단, InnoDB엔진의 default 수준인 REPEATABLE READ에는 발생하지 않는데,
Gap lock을 사용해 레코드의 일정 구간 자체에 락이 걸려 T1의 갱신 행위가 이뤄지지 않기 때문입니다.

카카오톡 플러스 친구에 좋은 채널이 있어 추가하였다. 하루에 한 개씩 CS 공부를 할 수 있도록 질문을 보내주고 , 답변자에 한하여 그 날이 마무리될때쯤 베스트 답변을 취합하여 다시 알려주는 좋은 채널이라 덕분에 나도 틈날때마다 개념을 정리하려 한다.

Reference : CS 공부 비서, 동기와 비동기의 개념, 동기와 비동기의 개념과 차이


Q&A

Q.  동기(Synchronous)와 비동기(Asynchronous), 블로킹(Blocking)과 논-블로킹(Non-blocking)에 대해 설명해주세요

A. 나의 답변

* 동기는 요청을 보내는 동시에 결과값을 받을 수 있도록 동시에 일어나는 것에 초점을 맞춘 방식이다. 비동기는 반대로 요청과 결과가 동시에 일어나지 않는다.

* 블로킹은 원래는 스포츠(농구)용어인데 수비수가 공격수로부터 방어하는 것을 의미한다. 컴퓨터용어로 사용하게 되며 비슷한 듯 다른 의미로 변경되었다. 블로킹은 호출함수가 호출당한 함수에게 제어에 대한 권한을 넘기는 것이다. 호출당한 함수의 작업이 끝나야 돌려받을 수 있기 때문에 호출함수는 그동안은 아무것도 할 수 없다. 논블로킹은 호출함수가 호출당한 함수를 호출은 하지만, 제어 권한을 넘겼다가 바로 돌려받기 때문에 호출함수는 다른 작업을 할 수 있다.

 

 


Best Answers


★ㅇ*님의 답변
동기식 - submit
: 리로드 방식. 로딩을 계속 하는 것.
동기는 요청과 결과가 동시에 일어난다는 약속인데, 요청을 하면 시간이 얼마나 걸리던지 요청한 자리에서 결과가 주어져야 합니다. = 그 동안 다른 처리를 할 수 없음.

비동기 - ajax
: 로딩을 하지 않는 상태로 데이터만 이동
화면은 고정적으로 있고 데이터만 이동하며, 호출한 화면으로 다시 돌아감.
비동기는 동시에 일어나지 않는다는 의미로 요청한 결과가 반환되지 않은 상태에서도 다른 작업을 처리할 수 있습니다.

비동기식은 동기식보다 설계가 더 복잡하지만 자원을 효율적으로 사용할 수 있다는 장점을 가지고 있습니다.

——

블로킹과 논블로킹의 차이는 처리되어야 하는 작업이 전체적인 작업의 흐름을 막느냐 안막느냐의 관점의 차이로 즉, 제어권이 누구에게 있느냐로 판단합니다.

블로킹은 호출한 함수에게 제어권을 넘겨주어 해당 함수의 작업이 끝나 다시 제어권을 돌려주기 전까지 실행을 멈춥니다.

논블로킹은 함수를 호출해도 제어권은 그대로 유지한 상태로 계속 실행할 수 있습니다.


★한*님의 답변
동기 (Synchronous)   

- 요청과 결과가 동시에 일어남
- 요청을 했을 경우 시간이 얼마나 걸리던지에 상관없이 요청한 자리에서 바로 결과값을 받아야 함
- 설계가 매우 간단하고 직관적임
- 결과가 주어질 때까지 아무것도 못하고 대기하면서 결과를 기다려야 함

비동기(Asynchronous) 
- 요청과 결과가 동시에 일어나지 않음
- 요청했을 경우에 지금 바로 혹은 당장 응답받지 않아도 됨 
- 동기에 비해 설계가 복잡함
- 결과가 주어지는데 시간이 걸리더라도 기다리는 시간동안 다른작업을 진행할 수 있으므로 자원을 효율적으로 사용

제어권   
- 함수를 실행시킬 수 있는 권리 

결과값 
- 함수의 리턴 값

블로킹(blocking)
- 요청자(부모함수) 는 요청한 작업이 끝날 때까지 다른 작업을 하지 않고 기다림
- 다른 함수를 호출할 때, 제어권도 함께 넘겨주며 그 작업이 끝난 후에 돌려받기 때문 (제어권이 없는상태)
- 요청받은 함수는 모든 실행을 마치고 최종 결과값을 돌려줌

논블로킹(non-blocking) 
- 요청자(부모함수) 는 요청한 작업이 수행되는 동안 다른작업을 진행할 수 있음
- 다른함수를 호출할 때, 제어권을 넘겨주지만 바로 돌려 받음 
- 제어권을 바로 돌려받기 때문에 다른 작업을 진행할 수 있음


★민*님의 답변
블로킹 Blocking
A 함수가 B 함수를 호출 할 때, B 함수가 자신의 작업이 종료되기 전까지 A 함수에게 제어권을 돌려주지 않는 것

논블로킹 Non-blocking
A 함수가 B 함수를 호출 할 때, B 함수가 제어권을 바로 A 함수에게 넘겨주면서, A 함수가 다른 일을 할 수 있도록 하는 것.

동기 Synchronous
A 함수가 B 함수를 호출 할 때, B 함수의 결과를 A 함수가 처리하는 것.

비동기 Asynchronous
A 함수가 B 함수를 호출 할 때, B 함수의 결과를 B 함수가 처리하는 것. (callback)


★박*님의 답변
동기: 요청-응답이 하나로 묶여서 기다리는 방식, 가령 A라는 작업과 A에 대한 A’ 라는 응답이 있고, B,C,D가 같은 형태로 있다면 갹각의 응답 결과 뒤에 다음 작업들을 요청한다.
비동기: 요청을 응답을 기다리지 않고 실행한다. 요청들은 응답이 오면 별도의 방식으로 순서와 상관없이 처리되어 반환된다. 응답 결과를 확인하는 방식은 비동기를 처리하는 부분을 구현하는 것에 따라 다르다.

블로킹: 특정 작업 동안 프로세스 자원을 점유하며 다른 작업을 하지 못하게 막는다. 가령 파일입출력 같은 작업동안 별도의 커맨드를 수행하지 못하게 한다거나 하는 부분이 이에 해당한다.
논블로킹: 특정 요청이 프로세스 자원을 다른 커맨드에서 활용하는 것을 막지 않는다. 프로세스/스레드 어느쪽 자원이든 커맨드가 실행되고 해당 작업이 종료되지 않아도 다른 작업들을 실행할 수 있게 한다.


★조*님의 답변
[동기 비동기]
- 작업 수행 순서가 직렬로 이어지냐(동기), 병렬로 동시에 진행되냐(비동기)에 대한 문제
동기 : 작업을 순차적으로 진행, 한 작업이 끝날 때까지 다음 작업은 대기하고 있다가 실행된다. 혹은 기존 작업에서 계속 다른 작업의 실행이 끝났는지를 확인하며 체크해야함
비동기 : 스레드 다수개를 이용해 작업을 동시에 병렬로 작업 후, 한 작업이 끝나면 callback 을 받아서 해당 작업을 요청했던 스레드를 호출하는 식으로 동작함.

[블로킹/논블로킹]
- 작업 중간중간에 쉴 때 계속 본인이 점유하고 있을지(블로킹), 혹은 다른 작업에게 주도권을 넘겨줄지(논블로킹)에 대한 문제
블로킹 : 본인의 작업이 끝날 때까지 다른 작업들은 모두 대기함(말 그대로 block, 막고 서있는 느낌). 가령 스레드 A가 일을 하다가 B를 호출했다면, B의 작업이 끝날 때까지 계속 대기하거나 B의 작업 종료를 본인이 함
논블로킹 : 본인의 작업이 끝나지 않았더라도, 다른 작업을 수행해야하거나 작업이 종료되어 콜백이 들어오면 해당 작업이 진행됨. 가령 스레드 A가 일을 하다가 B를 호출했다면, A는 일을 하다가 유휴 상태가 되면 B에게 주도권을 넘겨줄 것임.

★노*님의 답변
### 블로킹(Blocking)

A함수가 B함수를 호출하면 A함수의 제어권을 B함수에 넘긴다.
B에게 제어권이 넘어가면 A는 함수 실행을 멈춘다.
B의 실행이 끝나면 제어권을 A에게 돌려준다.

### 논-블로킹(Non-blocking)

A함수가 B함수를 호출해도 제어권을 A가 가지고있다.
A함수는 B함수를 호출한 이후에도 A함수의 코드를 계속 실행한다.

### 동기(Synchronous)

요청과 응답이 동시에 일어남.
요청이 들어오면 결과가 주어지기까지 다른 요청을 받을 수 없음.

### 비동기(Asynchronous)

요청과 응답이 동시에 일어나지 않음.


★이*님의 답변
동기는 어떤 함수를 호출했을 때 호출된 함수가 완료상태를 전달하기 전까지는 호출한 함수는 다른 작업을 수행할수 없다. 즉, 2개의 함수가 시간을 맞춰 수행하는것.

비동기는 호출된 함수가 콜백함수를 반환하여 자신의 일이 완료가 되지 않아도 호출한 함수가 다른일을 수행할 수 있으며 호출된 함수가 결과를 반환하면 호출한 함수는 해당 결과값을 가지고 관련된 작업을 수행한다. 즉, 2개의 함수가 시간에 맞춰 수행하지 않고 서로의 작업을 수행하는것이다.

블로킹은 호출된 함수가 완료상태가 될때까지 제어권을 호출한 함수에게 넘겨주지 않는것이다.

논블로킹은 호출된 함수가 완료상태가 되지 않아도 제어권을 호출한 함수에게 넘겨주어 다른 작업을 할 수 있게 하는것이다.

동기,비동기와 블로킹,논블로킹의 차이점은 전자는 호출되는 함수의 완료여부를 누가 신경쓰는지에 초점을 맞추고 후자는 호출된 함수가 리턴을 바로하는지 아닌지에 초점을 맞추고 있다.


★정*님의 답변
1. 동기/비동기 -> 응답을 받는 순서
2. 블로킹/논블로킹 -> 응답을 받는 타이밍

1.1 동기
한 번에 하나씩 작업하는 것. 작업 순서가 보장된다.
CPU가 점유되지만 실행되고있지않은 블로킹(waiting time)이 생길 수 있다.

1.2 비동기
여러 작업을 동시에! 작업순서보장x
목적: 동기 작업중 cpu속도차로 생기는 블로킹영역의 효율적 사용
:o:독립적 작업
:x:상호의존적작업, 대규모연산 요구되는 작업


2.1 블로킹
작업 완료 후 응답결과를 받는다.
작업완료 전까지 cpu는 점유되지만 실행되지않는다.
해당 쓰레드는 Waiting Queue에 들어감.
비동기모델이라면, 블로킹영역에 수행할 다른 작업을 명시적으로 지정해줘야함.

2.2 논블로킹
응답결과를 기다리지않고 cpu가 다음작업을 계속한다.


:question:더 공부할 점)
- I/O 작업이란?
- kernel이란?
- user space란?
- 쓰레드란?? 멀티쓰레드?
- 웨이팅 큐??


★민*님의 답변

### 동기와 비동기
동기 : 메인업무가 서브업무 작업 완료 후의 결과값을 기다린다.
비동기 : 메인업무는 서브업무의 작업 완료를 신경쓰지 않는다.

### 블로킹과 논블로킹
블로킹은 서브업무에 제어권을 넘기기 때문에 메인업무는 잠시 실행을 멈추고 서브업무 종료 후 실행된다.
논블로킹은 메인업무가 여전히 제어권을 가지고 있기 때문에 서브업무 실행 후에도 메인업무가 계속 실행된다.


### 조합
동기 & 블로킹 : 메인업무가 서브업무 결과값이 필요해서 서브업무 종료 시까지 실행을 멈춘다.
동기 & 논블로킹 : 메인업무가 서브업무의 결과값을 지속적으로 확인하며 실행을 계속한다.
비동기 & 블로킹 : 메인업무가 서브업무의 결과와 상관없는데도 서브업무 종료 시까지 실행을 멈춘다.(거의 없음)
비동기 & 논블로킹 : 메인업무가 서브업무 응답을 기다리지 않고 실행을 계속한다. 서브업무는 업무 종료시 메인업무로 콜백된다.

★염*님의 답변
- 동기 작업이란, 한번에 하나씩 수행되는 것을 의미합니다.
즉, 해당 작업이 끝나기 전까지 현재 진행중인 작업 외의 다른 작업을 수행할 수 없습니다.
ex) HTTP 요청을 하면 무조건 응답을 받음. 동기적이라고 할 수 있다.

- 비동기 작업이란, 한 번에 하나 이상이 수행될 수 있음을 의미합니다
즉, 현재 작업을 진행중이더라도 다른 작업을 수행할 수 있습니다. 또한 작업의 결과를 바로 원하지 않습니다.
ex) 이메일을 보내는 작업은 상대방이 바로 답장하기를 원해 보내는 작업이 아님

- 블로킹은 자신이 Waiting(Blocking) 된 것을 의미합니다.
쓰레드가 블로킹 된다는 것은 CPU 가 점유되어 실행되지 못함을 의미합니다.
요청한 작업이 모두 완료되어 응답과 결과를 반환 받습니다. 그동안 CPU 를 점유합니다.

- 논블로킹은 Wait 하지 않고 그냥 수행합니다.
자신이 호출되었을때, 제어권을 바로 자신을 호출한 쪽으로 넘기며
자신을 호출한 쪽에서 다른 작업을 할 수 있도록 하는것을 의미합니다.
자신은 그대로 작업을 이어나갑니다. 쓰레드가 Waiting 하지 않으므로 CPU 제어는 그대로입니다.

 

위의 답변만 잘 읽어도 개념 정리가 잘 될 것 같다!

+ Recent posts