일반인의 Flutter 앱개발 10. Dart(비동기 프로그래밍 Asynchronous Programming, await, async, Future, CPU Thread)
간다간다숑간다2022. 10. 11. 21:50
728x90
기나긴 Class가 끝났다.
이제 얼마 안 남았나? 나도 앱 개발할 수 있는 건가?
오늘은 비동기 프로그래밍이라는 건데 아무 감도 안 온다. 이 글이 포스팅됐다면
나 같은 사람도 이해한 거니까 여러분도 할 수 있다.
CPU Thread 작동원리
이야 이런 것도 알아야 하는구나.
CPU 살 때 보면
저 네모 박스처럼 스레드라고 나오는데 이제 말하고자 하는 게 저 스레드이다
스레드는 CPU가 작업을 하는 가장 작은 유닛이다. 어떤 작업을 시키면 스레드가 하나 붙어서 그걸 작업해주는 거다.
이제 그림을 보자.
강의 일부분을 캡처했다.
CPU에서 작업을 시작하면 해당 작업이 완료될 때까지 1개의 Thread는 사용이 불가하다. 이것이 기본 작동원리다.
그런데 문제는 서버에 작업을 요청했을 때 일어난다.
Synchronous Programming
작업 1을 시작하고 서버 요청을 보내면 해당 서버에서는 작업을 하고 응답하는 신호가 돌아오게 되는데 이것은 아무리 빠른 CPU를 가진 서버라 해도 물리적으로 시간이 걸릴 수밖에 없다. 그렇게 되면 작업 1은 서버가 응답할 때까지 Thread를 하나 잡고 있게 되는데 이게 너무 아깝다 이거다. CPU입장에서는 놀아서 좋겠지만
Asynchronous Programming
Dart언어는 기본적으로 비동기 프로그래밍인데 이것도 개념을 한 번 보자.
비동기 프로그래밍은 작업 1이 서버 요청을 했을 때 CPU가 놀지 않게 그때 작업 2를 시작한다. 아주 얄짤없다.
서버가 작업 1에 대해 응답하고 CPU가 필요하면 그때 다시 Thread를 할당하고 작업 1을 완료시킨다.
그 사이 작업 2가 서버로 응답을 받아 Thread가 필요하면 다시 할당시키고 작업 2를 완료시킨다.
아주 효율적이다. 지난번에 미래 사장님이 되어 알바로 레드벨벳을 썼던 글이 있었는데
관리자의 입장에서 아주 만족스러운 작업효율이다.
Code로 비동기 프로그래밍해보기
Future 키워드는 미래에 받아올 값으로 모든 값을 바꿔줄 수 있다.
그 값은 Future.value() 안에 넣어주면 된다. 기본적으로 제공된다.
그리고 숫자를 더해주는 함수를 하나 만들어줬다.
Future에는 delayed라는 기능도 있는데 2개의 파라미터를 받는다.
하나는 지연시간을 정하는 duration과 나머지 하나는 지연시간 후 실행할 함수이다.
지금까지 우리가 배웠던 상식으로는 계산 시작-> 계산완료-> 함수 완료의 순으로 결과 값이 나와야 하는데
2초의 시간을 지연시키는 동안 그다음 작업을 해버리기에 '함수 완료'가 먼저 나와버리고 그다음 숫자를 더하는
함수를 실행한다.
정말 효율적으로 일을 잘하는 Dart다.
함수를 하나 더 추가했다. 이러면 결과가 어떨까?
컴퓨터들은 계산이 빠르기에 결과가 이렇게 나온다. 이해가 되는가?
안되더라도 걱정하지 말아라. 처음엔 다 헷갈릴 수 있다. 나도 그랬다.
처음 함수 1+1을 실행하고 2초를 기다리며 함수 완료를 출력했는데도
2초가 다 안 지나서 2+2를 실행해버린 것이다.
2+2의 2초 딜레이를 기다리는 동안 함수 완료를 출력해 버리고 나니
1+1의 2초가 지나 계산완료가 나오게 되는 순서이다.
이해 안 될 수도 있다. 차근차근 다시 읽어가며 이해하고 넘어가자.
그러나 문제가 있다. 아무리 효율적인 연산이라 해도 사람이 보기에 좋아야 할 것 아닌가?
그것에 대해 해결해보자.
Await
역시 개발자 형들은 다 준비해놨다.
괄호와 괄호 사이에 'async'를 써주고 Future 앞에 await를 써주면 된다. 참 쉽다.
1+1을 계산해보면 정확한 순서로 나오는 걸 알 수 있다.
근데 문제는 2+2까지 했을 경우다.
아주 계산식이 엉망진창 와진창이다. await를 만나면 다음 코드로 넘어가지 않고 그동안 다른 작업을 찾아서 2+2를 하는 것이다.
이런 고민에 대한 해결을 당연히 개발자 형님들이 해놓으셨다.
Main도 async를 먹여보자
main()도 함수이기 때문에 괄호 사이에 'async'를 써 줄 수 있다.
addNumber들을 await 시키고 싶으니 await를 써줬는데 에러가 나버린다.
왜냐면 await를 future를 리턴해야 하는데 addNumbers들은 void를 리턴하기 때문이다.