조합 소식

공지사항

콜백 서비스 문자 앱 아톡 PR 메시지 후기

페이지 정보

profile_image
작성자 Cassandra
댓글 0건 조회 4회 작성일 25-03-18 11:31

본문

2025.02.03 콜백 작성2025.02.23 수정​Rust의 라이프타임 시스템이 어렵고 난해하다고 하지만, 사실 일반적인 경우에서는 그렇게 벽을 느낄만한 경우가 많지는 않다. 단순하게 함수에 참조를 넘기거나 하는 경우는 문제가 될 경우가 잘 없다.​하지만 참조에 async가 붙고 콜백도 엮인다면 머리가 아파지기 시작한다.​​​문제 없는 경우 ​async가 아니라면 뒷면에서의 코드 생성이 거의 일어나지 않기도 하고, 대체로는 별 문제가 없다. 콜백함수를 받아서 실행하는 retry 함수를 만든다고 하면, 이런 식으로 할 수 콜백 있을 것이다. 잘 동작한다. ​그러면 콜백에 가변 참조 같은 값을 파라미터로 넘기면 어떨까? 참조라서 문제가 생길까? 동기 코드에서는 별다른 문제가 없다. ​​​문제: async callback과 참조 전달​문제가 생기는건 보통 async를 쓸때부터다. 하지만 콜백이 파라미터를 받지 않는다면 이 또한 문제는 없다. ​문제가 생기는건, async 콜백이 참조 파라미터를 받을때부터다 async 자체가 문제라기보단, async가 trait으로 확장되는 과정에서 미묘한 뭐시기들이 생기는 것이다. 이런 식으로 짜면 ​사용할때 콜백 lifetime 관련 오류가 돌출되기 시작한다. ​이러한 오류 메세지는 관련해서 아는게 없다면 직관적으로 받아들이기 어렵다. 저기서 문제가 된건 클로저인데, 하나씩 까보자. 일단 클로저의 파라미터 타입이 (context: &'1 mut Context)로 해석된다. 그리고 클로저의 반환 타입 (여기서는 async block)이 라이프타임 '2로 암시된다. ​타입 시그너처로 표현하면 이렇게 풀린다고 보면 된다. 이것도 어지럽긴 하다. ​아무튼 여기서 rust가 말하는건, '1 참조가 '2보다 오래 살아있다는 보장이 없다는 것이다. 콜백 ​사실 로직상으로는 별다른 문제가 없긴 한데, parameter와 return Future 사이의 이 미묘한 간극을 rust 컴파일러가 완벽히 추적을 하지는 못해서 생기는 문제다. 어떤 식으로라든 이 부정교합을 해결해야 컴파일이 될 것이다. 여기엔 2가지 정도의 방법이 있었는데, 1.85부터 깔끔한 방법이 생겼다. ​​​Best - async 클로저와 AsyncFn 트레잇 (since 1.85)​만약 이걸 보는 당신이 1.85 버전 이상을 쓴다면, async 클로저를 사용하는게 가장 깔끔한 해결책이다. Fn 대신 콜백 AsyncFn 같은 async 함수용 트레잇으로 함수 타입을 정의하고 ​클로저를 넘길 때도 async 클로저를 넘기는 것이다. ​그럼 아주 깔끔하게 동작한다. ​​​​Legacy - 해결책 1: Pin Box​가장 일반적인 해결책은, 클로저가 반환하는 Future 값 자체를 Box로 묶고 Pin으로 고정하는 것이다. 현재로서는 클로저를 받아서 동작할 수 있게 하려면 이 방법을 선택해야 한다. Future를 generic으로 반환하지 않고, Box에 감싸고 Pin으로 고정해서 반환토록 한다. ​그리고 클로저를 넣을 콜백 때도 그 반환값이 Pin;가 되도록 해야한다. 보통 이렇게 async 블럭을 pin으로 걸면 된다. ​그러면 잘 동작할 것이다. ​참고로 futures crate에 있는 BoxFuture가 이 Pin;에 대한 숏컷이다. 귀찮으면 그거 쓰면 된다. ​​​Legacy - 해결책 2: callback 전용 trait 정의​굳이 클로저 말고 함수로 받아도 되고, Box 없이 처리하고 싶다면 조금 우회적인 방법이 있다. ​결국 parameter와 return Future 사이의 lifetime을 어떻게 잘 엮고 연결해주기만 콜백 하면 되는 건데, 그게 안돼서 이 난리가 벌어진 것이다. 그걸 표현하려면 현재로서는 trait을 하나 따야 한다. HRTB도 써야 한다. 이런 식으로 정의해주고 ​그걸 콜백 타입으로 받으면 된다. ​그럼 잘 동작할 것이다. 다만 이건 클로저를 쓰지 못한다는게 단점이다. ​​​참조A general solution is BoxFuture in futures::future - Rust Rust Playground A way to avoid Box is to use a trait to express the 콜백 lifetime connection between the input argument and return Fut: Rust PlaygroundBecause you annotate 'tr on the function, which means the variable tr in the body needs to live for that long. So a HRTB, i.e. Fun: forFut, is required to express we want a tr with any lifetime in the body instead of one with a specified lifetime outside the...​

댓글목록

등록된 댓글이 없습니다.