SwiftUI View에 ViewModel 여러 개 가지기

일반적인 경우로 생각할 수 있는지는 모르겠지만, 코딩을 하다보니, 뷰 하나에 기능에 따라 ViewModel을 분기시켜서 연동되게 하고 싶은 경우가 생겼습니다. 보통 스위프트에서 이러한 문제를 풀기 위해서는 Protocol을 참조하게 하거나, Subclassing으로 해결할 수 있을 것 같습니다. 상황에 따라 다르겠지만, Subclassing의 경우에는 기본 구현을 통해 변화를 주기는 편리하지만, Overriding으로 코드가 수정되고, 기능이 추가될 수록 파악하기 어려운 점이 있어서 Protocol을 이용해서 해결해보려고 했습니다. Protocol의 경우에는 인터페이스로 정의한 것만 구현해주면 다른 클래스와의 상호 작용 문제가 없어서 장기적으로 볼 때, 더 깔끔하다고 생각합니다. Protocol을 이용해 구현 더보기…

Combine 살펴보기: Operator

Operator Methods that create downstream publishers or subscribers to act on the elements they receive. 이벤트를 받는 시점에 값에 작용을 하는 하위 퍼블리셔 또는 서브스크라이버를 만드는 메소드 오퍼레이터는 특정한 타입은 아니지만, Combine을 구성하는 주요한 3대 요소이다. Combine에서는 퍼블리셔에서 메소드 형태로 사용되는 하위 퍼블리셔나 서브스크라이버로 정의하고 있다. RX에서는 메소드 형태라고 정의한 것은 아니지만, RXSwift에 한정하면 Combine과 같다. Operator가 있으므로서 다양한 방식으로 시퀀스가 변형될 수 있다. 또한, Operator 개념은 함수형 프로그래밍의 영향을 받은 것으로 생각된다. Combine의 이름이 Combine인 것도, Operator의 영향을 받았다고 생각하는데, 실제로 합성이나 변환은 더보기…

Combine 살펴보기: Subscriber

Subscriber A protocol that declares a type that can receive input from a publisher. 퍼블리셔로부터 입력을 받을 수 있는 타입을 정의하는 프로토콜. Apple Documentation Subscriber는 Publisher를 구독하는 타입이다. RX에서는 동일한 역할을 하는 객체를 Observer라고 부르며, 경우에 따라 Watcher, 또는 Reactor라고도 부르는 것 같다. Publisher로 부터 입력을 받기 때문에 Input과 Failure를 정의해야한다. Publisher를 통해 subscribe(_:) 할 때, 내부적으로 Subscriber의 receive(subscription:) 함수가 호출되면서 Subscription을 전달받고, 구독이 시작된다. 퍼블리셔의 경우에는 용도에 따라서 이미 구현된 Convenience Publisher가 굉장히 많지만, Subscriber의 경우에는 Convenience Subscriber로 클로저를 더보기…

Combine 살펴보기: Publisher

Publisher Declares that a type can transmit a sequence of values over time. 시간이 지남에 따라 값 시퀀스를 보낼 수 있는 타입을 정의함. Apple Documentation Combine의 퍼블리셔는 Observable의 개념이다. 퍼블리셔는 실제 구현이 아닌 Protocol로 정의되어 있다. RX의 경우에는 Observable Class의 구현을 제공하는 것과 차이가 있다. 따라서, Publisher는 여러 구현체를 가질 수 있고, Future, Just, …. 와 같은 편의 퍼블리셔를 제공한다. Publisher 프로토콜을 채택하는 Publisher를 구현하기 위해서는 프로토콜 채택 후, Output, Failure: Error associatedType과 receive(subscriber:) 함수를 구현해야한다. 다만, 애플은 Publisher를 직접 더보기…

Combine 살펴보기

2019년, 애플이 WWDC에서 컴바인을 소개하면서 컴바인을 다음과 같이 정의했다. that’s what Combine is, a unified declarative API for processing values over time. Combine is written in and for Swift. 컴바인은 시간에 따른 값을 처리하기 위한 통일된 선언적 API입니다. 컴바인은 스위프트로 작성이 되었고, 스위프트를 위한 것입니다. 또한, 공식 홈페이지에서는 Combine을 다음과 같이 정의하고 있다. 위의 문장과 아래의 문장이 애플이 생각하는 Combine의 기본적 컨셉이라고 볼 수도 있을 것 같다. Customize handling of asynchronous events by combining event-processing operators. 이벤트 처리 오퍼레이터를 통해 비동기 더보기…

swift enum codable

enum에서 codable을 채택하면 바로 안 되고, 뜨는 상황이 발생한다. 이유는 enum이 rawValue로 String 또는 Int를 채택하지 않아서 그렇다. (json 데이터라고 생각하면 당연한 것 같다.) 별도의 인자가 없는 경우에는 아래와 같이 수동으로(?) 인코딩, 디코딩을 해주면 된다. (사실 그냥, 문제가 없다면 rawValue를 채택하는 게 좋아보인다.) 만약 enum의 case에서 인자를 받았다면 아래의 stackoverflow를 참조하여 codingKey를 이용해서 case 별로 받은 인자를 추가적으로 인코딩, 디코딩해주면 좋을 것 같다. (container(keyedBy: CodingKey.Protocol) 사용.) https://stackoverflow.com/questions/44580719/how-do-i-make-an-enum-decodable-in-swift-4/44582674

SwiftUI View Paging

iOS 14 이상 스위프트UI의 신기능으로 TabView를 이용해서 페이징을 할 수 있는 기능이 추가되었다. 아래 동영상처럼 UICollectionView의 isPagingEnabled의 대체 기능이다. ScrollView를 horizontal로 설정하고, TabView를 만든 후에 안에서 View들을 생성한다. 이때, 모디파이어를 이용해서 tabViewStyle을 PageTabViewStyle()로 해주면 간단하게 만들 수 있다. (…근데 왜 이게 TabView로 기능이 들어간걸까?… 이름을 보면 매칭이 되긴하는데… 뭔가 흠…) 버그?: TabView안의 Foreach 문을 이용해서 뷰를 만들 때, 변수나 뷰 모델을 이용해서 만들고 특정 시점에 업데이트 해주고 싶을 수 있다. 그런데, 나의 경우에는 하단의 인디케이터 수만 변하고, 실제 뷰들은 업데이트가 더보기…

j4105 jellyfin transcoding이 잘 안되는 경우

J4105 하드웨어 성능이 크게 나쁘지 않아서 동영상 한 두개 정도는 소프트웨어로도 실시간 트랜스코딩을 할 수 있다. 다만, cpu 점유율이 너무 높기 때문에 기본으로 제공되는 하드웨어 트랜스코딩을 이용하면 더 쾌적하게 이용할 수 있다. 젤리핀, 우분투 20.04 환경에서 하드웨어 트랜스코딩을 VAAPI로 설정하면 한 번에 잘 되지 않는데 두 가지 이유가 있는 것 같다. https://www.clien.net/service/board/cm_nas/14528256첫 번째로 윗 글에서처럼 자유 드라이버가 아닌 드라이버가 설치되어 있지 않아서 인코딩 형식이 제한된다. 따라서 위 글에서 설명해주는 것 처럼 intel-media-va-driver-non-free, i965-va-driver-shaders을 설치해주면 지원되는 파일이 늘어난다. 다만, 나의 경우에는 더보기…

vscode server reverse proxy 설정

vscode server를 설치하고 reverse proxy를 이용해서 SSL이 적용된 도메인으로 접근하려고 했는데, 잘 안 됐다. 이유는 websocket 연결 때문이었다. vscode를 https 모드로 활성화한 후에 공인 인증서가 아니어도 프록시가 작동하게 하는 모듈(vscode에서 기본 제공하는 인증서가 공인인증서가 아니므로), 그리고 websocket을 rewrite하는 코드와 apache2의 proxy_wstunnel을 활성화하면 잘 작동한다. 전체적으로 아래와 같은 설정을 자신의 설정에 포함시키면 된다. a2enmod로 프록시 관련 모듈인 proxy, proxy_http, proxy_wstunnel을 활성화 시킨 후 apache2를 재로드하면 잘 작동하는 것을 볼 수 있다. 참고 :https://github.com/cdr/code-server/issues/282

왜 CNAME은 ROOT에서 쓸 수 없는가? PTR 레코드란 무엇인가?

개요 도메인 등록 회사를 구글 도메인으로 바꾸면서 도메인의 루트에 CNAME을 등록할 수 없었다. 나는 집에서 DDNS을 이용해서 서버를 돌리고 있기 때문에, ip주소를 등록하는 A 레코드는 이용하기 어려웠다. 구글 도메인 레코드 등록 중에 도메인을 받는 레코드인 PTR 레코드가 있어 DDNS 도메인을 등록해봤다. CNAME이 아닌 PTR로 DDNS 주소를 등록하니 잘 동작했다. CNAME 레코드는 왜 루트에 등록될 수 없을까? 그런데 왜 구글 도메인에서는 도메인의 루트에 CNAME을 등록할 수 없는 걸까. DNS 표준 규칙에 의하면 다음과 같은 도메인 제약 사항이 있다. SOA와 NS 레코드는 더보기…