create_task()가 반환하는 태스크 인스턴스는 최소 하나의 변수에 할당돼야 하며, 변수는 태스크가 종료될 때까지 살아있어야 합니다. 그렇지 않으면 코루틴이 실행되고 있는 와중에 태스크 인스턴스가 가비지 컬렉트 당할 위험이 있습니다.
위와 같이 태스크를 생성하는 함수가 곧 종료되는 경우라면, 태스크 인스턴스를 리턴하거나, 전역 변수에 할당하거나, 인스턴스 변수에 할당하는 등의 방법을 사용해야 합니다.
P.S)
리턴값이 굳이 필요하지 않고, 코루틴이 단시간 내에 끝날 거라는 확신이 있더라도, 태스크 인스턴스에 대해서는 언젠가는 await을 걸어 주도록 짜는 게 좋습니다. 그게 싫다면 태스크로 작동할 코루틴마다 예외 처리를 빡세게 걸어서 로그 메시지를 빈틈없이 띄울 구조를 마련하거나요. 그러지 않으면 태스크가 아무리 큰 사고를 치더라도 Exception이 처리되지 않고 silently fail하는 경우가 생기게 됩니다.
제가 밥벌이로 개발/관리하는 프로젝트에서 수십 개의 모듈이 각자 while self.ok(): cmd = await self.cmd_queue.get(); await self.process(cmd); 이런 식의 태스크를 하나씩 생성해서 계속 돌리는 패턴을 설계했었거든요. 예외처리 패턴 확립하기 전까지는 문제 하나 터질때마다 제 멘탈도 같이 터져나가는 진귀한 경험을 했더랬죠 ㅎ
Async/Await 패턴의 원조(?)라 할 수 있는 C#을 쓰는 회사에 다니는 입장에서 봐도 1번 실수와 같이 await를 단순하게 순서대로 줄줄이 늘어놓는 형태의 잘못된 코드가 보일 때가 꽤 많더군요.
그런 코드를 보면 뭐랄까 공통적으로 async 메소드 호출 앞에서는 await 키워드를 써야 한다는 것만 알고 그 이상의 비동기 실행 순서에 대한 부분은 별로 생각하지 않아서 이런 코드가 나오는 것 같다는 느낌은 있습니다.
여러 개의 await가 나올 때 어떤 건 바로 아래에서 결과가 쓰이니까 그 앞에서 Task<T> 객체의 await 결과값을 받도록 하고, 어떤 건 꽤 뒤에서나 쓰일 테니까 Task<T>만 받아서 나중에 await하고 이런 식으로 비동기 흐름을 고려하여 코드를 작성하는 건 그만큼 머리를 쓰는 작업이니까요.
적어도 저는 비동기로 선언된 메소드에서는 이렇게 처리 흐름을 고려해서 코드를 작성하고 있긴 한데, 어떨 때 기존 유지보수 중인 퇴사자의 코드를 보면 ‘나는 그냥 단순하게 동기 코드를 작성하고 싶은데 중간에 써야 할 메소드가 비동기 타입밖에 없으니까 그냥 이렇게 작성한다’는 느낌이 들 때도 있더군요.
Abliteration 으로 LLM 무삭제 검열 해제하기
AI가 주도한 최초의 사이버 첩보 작전 차단
저것들이 불필요한 일이라고 주장하는 게 아니라, 저런 준비동작을 하면서 일을 했다고 착각하는 현상을 경계하는 것 아닐까요?
'멀티스레딩은 오버헤드가 부담스럽기 때문에 차선책으로 싱글스레드를 쪼개어 병렬처리를 해결한다'라는 개념으로 접근해야 하는 것 같아요. 그렇기 때문에, 기본적으로 멀티스레딩보다 때에 따라서는 더욱 신경을 써야 하는 게 맞는 것 같고요.
컴파일 언어로 가는 게 아니라면, 성능이 크게 차이가 나나요? 멀티스레딩이라면야 GIL의 존재로 인해 큰 차이가 생기겠지만, 어차피 이벤트 루프가 작동하는 비동기 구조라면 언어에 따른 차이가 어떤 게 생기는지 궁금하네요.
실행이 중요하긴 하지만, 공유와 준비 역시 임팩트를 줄 수 있기에 공감안갑니다
주커버그가 변화에 대응하는 부분이 많은 것 같아요.
일 외에 여러가지 불필요한 일들이 있겠지만 필요한 일들도 껴있는 것 같아 공감이 잘 안되네요.
최근 읽은 것 중에 가장 공감되지 않는 글
https://varlock.dev 와 비교했을 때 어떤 장점이 있나요?
그것도 그렇죠.
제대로 된 비동기 코드라는 건 본질적으로 신경을 많이 써야만 하는 코드인 것 같습니다.
사실 파이썬 비동기를 최적화할 정도의 프로젝트면 다른 언어로 작성하는게 성능도 안정성도 훨씬 좋습니다.
어그로 끄는 제목과 정독하지 않은 독자가 결합된 결과 같네요
1번이 항상 독립적이면 저렇게 하는게 좋긴 한데,
코드 수정했다가 독립적이지 않게 되면 저 함수를 사용하는 곳을 전부 검수하며 수정해야하는 불편함도 있는 것 같네요.
시간이 엄청 오래걸리지 않는 작업이면 직렬로 await 하는게 코드관리면에서 더 나을지도
아 등록하기에 있군요..ㅋㅋ 등록을 직접 해본적이 없어서 몰랐네요;
https://news.hada.io/show
Show 등록하기 버튼 바로 옆에 있습니다..
해당 내용은 어디에 있나요? 사이트 이용법이나 FAQ에는 없군요.
추가되면 좋을 것 같네요.
출처 영상은 확인해 보지 않았지만, 실수 4에 대한 해결책 코드는 잘못된 코드입니다.
create_task()가 반환하는 태스크 인스턴스는 최소 하나의 변수에 할당돼야 하며, 변수는 태스크가 종료될 때까지 살아있어야 합니다. 그렇지 않으면 코루틴이 실행되고 있는 와중에 태스크 인스턴스가 가비지 컬렉트 당할 위험이 있습니다.위와 같이 태스크를 생성하는 함수가 곧 종료되는 경우라면, 태스크 인스턴스를 리턴하거나, 전역 변수에 할당하거나, 인스턴스 변수에 할당하는 등의 방법을 사용해야 합니다.
P.S)
리턴값이 굳이 필요하지 않고, 코루틴이 단시간 내에 끝날 거라는 확신이 있더라도, 태스크 인스턴스에 대해서는 언젠가는 await을 걸어 주도록 짜는 게 좋습니다. 그게 싫다면 태스크로 작동할 코루틴마다 예외 처리를 빡세게 걸어서 로그 메시지를 빈틈없이 띄울 구조를 마련하거나요. 그러지 않으면 태스크가 아무리 큰 사고를 치더라도 Exception이 처리되지 않고 silently fail하는 경우가 생기게 됩니다.
제가 밥벌이로 개발/관리하는 프로젝트에서 수십 개의 모듈이 각자
while self.ok(): cmd = await self.cmd_queue.get(); await self.process(cmd);이런 식의 태스크를 하나씩 생성해서 계속 돌리는 패턴을 설계했었거든요. 예외처리 패턴 확립하기 전까지는 문제 하나 터질때마다 제 멘탈도 같이 터져나가는 진귀한 경험을 했더랬죠 ㅎAsync/Await 패턴의 원조(?)라 할 수 있는 C#을 쓰는 회사에 다니는 입장에서 봐도 1번 실수와 같이
await를 단순하게 순서대로 줄줄이 늘어놓는 형태의 잘못된 코드가 보일 때가 꽤 많더군요.그런 코드를 보면 뭐랄까 공통적으로
async메소드 호출 앞에서는await키워드를 써야 한다는 것만 알고 그 이상의 비동기 실행 순서에 대한 부분은 별로 생각하지 않아서 이런 코드가 나오는 것 같다는 느낌은 있습니다.여러 개의
await가 나올 때 어떤 건 바로 아래에서 결과가 쓰이니까 그 앞에서Task<T>객체의await결과값을 받도록 하고, 어떤 건 꽤 뒤에서나 쓰일 테니까Task<T>만 받아서 나중에await하고 이런 식으로 비동기 흐름을 고려하여 코드를 작성하는 건 그만큼 머리를 쓰는 작업이니까요.적어도 저는 비동기로 선언된 메소드에서는 이렇게 처리 흐름을 고려해서 코드를 작성하고 있긴 한데, 어떨 때 기존 유지보수 중인 퇴사자의 코드를 보면 ‘나는 그냥 단순하게 동기 코드를 작성하고 싶은데 중간에 써야 할 메소드가 비동기 타입밖에 없으니까 그냥 이렇게 작성한다’는 느낌이 들 때도 있더군요.
알려주셔서 감사합니다.
FAQ에 관련한 설명이 없어서 올려도 되는줄 알았습니다