UI 모듈화에 대한 고민

준우·2024년 3월 11일
0

Swift 이야기

목록 보기
12/19
post-thumbnail

최근 사이드 프로젝트와 리팩토링을 진행하면서 느끼게 된 부분이 있어요.
앱 UI는 개발/업데이트/리팩토링을 하다보면, 바뀌는 경우가 많잖아요.

예를 들면, 내가 만든 앱의 한 개의 버튼이 디자인 통일성을 해친다는 사용자 피드백을 받았어요.
그러면 그 사용자 피드백을 토대로 버튼의 디자인을 살펴 볼 거에요.
오랜 회의 또는 고민을 거쳐 기존 버튼을 제거하고 새로운 버튼을 생성해야 한다는 결론이 나왔어요.

그런데, 기존의 버튼 코드는 VC에서 만들었네요?
거기다가 버튼 생성/치수 코드들이 전부 VC 전체에 분포해 있군요.(잘못 건드리면 빨간 줄 지옥을 볼 수도 있음...)

그래서 어떻게 하면 UI 를 더 효율적으로 교체할 수 있을까라는 고민을 했어요.
제가 생각한 방법은 UI의 타입만 지정하고, 외부에서 버튼 UI 를 만든 후에 그냥 VC에 주입하는 방식이에요.
아래의 예시 코드를 보여드릴게요.

타입만 선언한 버튼 변수를 생성합니다. 여기서 !를 사용한 이유는 이미 우리는 버튼이 있다는 것을 알고 있기 때문에 사용했습니다.

var button: UIButton! 

먼저, 직사각형 버튼을 사용하기 위해 외부에서 만들어 보겠습니다.
여기서 UI 구성을 다 해줍니다.

class RectangleButton: UIButton {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    private func setup() {
        translatesAutoresizingMaskIntoConstraints = false

        backgroundColor = .systemOrange
        tintColor = .white

        layer.cornerRadius = 10
        layer.masksToBounds = true

        setTitle("Test Button 1", for: .normal)
        titleLabel?.font = .systemFont(ofSize: 20, weight: .bold)
        titleLabel?.adjustsFontSizeToFitWidth = true
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

그 이후, VC로 돌아와 액션동작과 치수를 조정합니다. 전 여기서, 버튼을 주입하겠습니다.(굳이 아래코드에서 주입할 필요는 없습니다.)
버튼을 등록/치수/액션 동작을 설정합니다.

private func setup() {
        /// 여기서 사용할 버튼 모듈을 button 변수에 주입
     	button = RectangleButton(frame: .init(x: 0, y: 0, width: 160, height: 80)) // 직사각형 버튼
        view.addSubview(button)

        /// 버튼 치수 조정
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        button.widthAnchor.constraint(equalToConstant: button.frame.width).isActive = true
        button.heightAnchor.constraint(equalToConstant: button.frame.height).isActive = true

        button.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
    }

그리고 실행을 해보면!!

이렇게 버튼이 생성 되었습니다.

그려면, 이번엔 원형 버튼을 만들어보겠습니다.
직사각형 버튼과 동일한 형식이지만, setup 함수만 다르게 만듭니다.

 private func setup() {
        translatesAutoresizingMaskIntoConstraints = false

        backgroundColor = .systemMint
        tintColor = .black

        layer.cornerRadius = frame.width / 2
        layer.masksToBounds = true

        setTitle("Test Button 2", for: .normal)
        titleLabel?.font = .systemFont(ofSize: 20, weight: .bold)
        titleLabel?.adjustsFontSizeToFitWidth = true
    }

그 이후, VC로 돌아와서 setup 함수 안 버튼 주입 부분을 바꿔줍니다.

//        button = RectangleButton(frame: .init(x: 0, y: 0, width: 160, height: 80)) // 직사각형 버튼
        button = CircleButton(frame: .init(x: 0, y: 0, width: 160, height: 160)) // 원형 버튼

그리고 실행을 해보면!!

원형 버튼으로 잘 바뀐 것을 볼 수 있습니다.

이 방법을 응용한다면 VC 도 바꿔끼울 수 있을 거 같네요. 이 방법은 좀 더 공부해보고 다시 글을 쓰는 것? 으로 해보겠습니다.

0개의 댓글