๐๏ธํ์ ์ ํตํ ์ฑ์ฅ ๊ณต๊ฐ, GrowingTalk
- ์ด๋ฉ์ผ ๊ธฐ๋ฐ ํ์ ์ธ์ฆ
- ์ํฌ์คํ์ด์ค(๋ฉ์ธ ํ๋ฉด) ๋ด ์ฑํ ๋ฐฉ ๊ฐ์ค ๊ธฐ๋ฅ ๋ฐ ํ์ ์ด๋ ๊ธฐ๋ฅ
- ์ค์๊ฐ ์ฑํ ๊ธฐ๋ฅ ๋ฐ ์๋ก์ด ์ฑํ ๋์ฐฉ์ ์๋ฆผ ๊ธฐ๋ฅ
- ๊ฒฐ์ ์์คํ ๊ธฐ๋ฅ ํฌํจ
๋ ์์ธํ ์คํฌ๋ฆฐ ์ท ๋ณด๊ธฐ
๐ํต์ฌ ๊ธฐ์
RxSwift
๊ธฐ๋ฐ MVVM ํจํด ์ ์ฉ์ ํตํด ๋น์ฆ๋์ค ๋ก์ง ๋ถ๋ฆฌ ๋ฐ ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ ๊ตฌํRealm
DataBase์ ๊ธฐ์กด ์ฑํ ๋ฐ์ดํฐ๋ฅผ ์ฐ๊ธฐ/์ฝ๊ธฐํ์ฌ ๋คํธ์ํฌ Reqeust ์ต์ํSocketIO
๋ฅผ ํ์ฉํ Socket ํต์ ๊ธฐ๋ฐ ์ค์๊ฐ ์ฑํ ๊ตฌํ- Payment Gateway(PG)๋ฅผ ํตํ ์ ์ฉ ์นด๋ ๊ฒฐ์ ์ง์
Modern CollectionView
ย +ยDiffableDataSource
๋ฅผ ํ์ฉํ Expandable List ๊ตฌํAsync/Await
๋ฅผ ๋์ ํย Realm Transaction ๋น๋๊ธฐ ์คํ ๊ตฌํRx operator
๋ฅผ ํ์ฉํJWT๊ธฐ๋ฐ AccessToken, Refresh Token ๊ฐฑ์ ๋ก์ง
๊ตฌํUIGraphicsImageRenderer
๋ฅผ ํตํย ์ด๋ฏธ์ง Rendering resizing- ๊ณตํต UI Component ๋ถ๋ฆฌ ๋ฐ ์บก์ํ ๊ตฌํ์ ํตํ ์ฌ ์ฌ์ฉ์ฑ ํฅ์
๐๊ฐ๋ฐ ํ๊ฒฝ
๊ฐ๋ฐ ๊ธฐ๊ฐ: 2024.01.02. ~ 03.01.
๊ฐ๋ฐ ์ธ์: 1์ธ
๊ฐ๋ฐ ์ธ์ด: Swift
Minimum Deployment: iOS 16.0+:UISheetPresentationController.Detent.custom
โ๏ธ๊ธฐ์ ์คํ
- BaseSDK:
UIKit
- Pattern:
MVVM
,Singleton
,Input-Output Pattern
- Reactive Programming:
RxSwift
- Package Management:
SPM
,CocoaPods
- CodeBaseUI:
PHPickerViewController
,SnapKit
,Then
,Toast
- Database:
RealmSwift
- Network:
Moya
,SocketIO
,Kingfisher
- Management:
FireBase Cloud Messaging
- ์ฌ์ด๋ ๋ฐ๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋, ๋ณดํธ์ ์ธ ์ฌ์ด๋ ๋ฐ ๊ตฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ง์์ด ๋๊ธด์ง ์ค๋ ๋์์์ ๋ฐ๋ผ ์ฌ์ด๋ ๋ฐ ์ง์ ๊ตฌํ์ ์ ํ.
UIView.animate()
๋ฅผ ํตํด ViewWillAppear ์์ ๊ณผ viewWillDisappear ์์ ์์์ ์ ๋๋ฉ์ด์ ์ ๊ตฌํ.UIPanGestureRecognizer
๋ฅผ ํตํด ๋ทฐ์Animate
๋ฅผ ์ ์ฉํ๊ณ View์ dismiss๋ฅผ ๊ฒฐ์ ํ ์ ์๋ค.
- ์๋ฒ์์ ์ฑํ ๋ด์ญ์ ๋ํ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ๋, ๋ชจ๋ ์ฑํ ๋ด์ญ์ ๋ฐ๊ฒ๋๋ฉด ์ฑํ ์ ํ๋ฉด ํ ์๋ก ์๋ฒ ๋ฐ ํต์ ์ ๋ํด์ ๋น์ฉ์ด ๋๋ฌด ์ปค์ง๊ฒ ๋๋ค.
- ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์๋ฒ๋ก๋ถํฐ ์ด๋ฏธ ๋ฐ์ ์ฑํ ๋ด์ญ์ ๋ํด์๋ ๋ก์ปฌ์ ์ ์ฅํ์ฌ CRDํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ ๋ค, ๋ก์ปฌ์์์ ๋ง์ง๋ง ์ฑํ ์ ๊ธฐ์ค์ผ๋ก ๊ทธ ์ดํ ์ฑํ ๋ด์ญ์ ๋ฐ๋ ๊ฒ์ผ๋ก ๋น์ฉ์ ์ ๊ฐํ ์ ์๋ค.
- ๋ก์ปฌ DB์ ์ ์ฅ๋์ด ์๋ ์ฑํ
๋ด์ญ, ์๋ฒ ํต์ ์ ํตํด ์ฑํ
๋ด์ญ์ ๋ฐ์์ค๊ณ ๋๋ฉด
Socket
์ ํตํด ์ค์๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ฑํ ์ ๊ตฌํํ๋ค.
๋ฌธ์ ์ํฉ | ์ ์ |
---|---|
![]() |
![]() |
- ์ฌ์ด๋ ๋ฐ์ ๋ฑ์ฅ ์ ๋๋ฉ์ด์ ํจ๊ณผ๋ฅผ ์ ์ฉํ๊ธฐ ์ํด ์ฌ์ด๋ ๋ฐ์ View ์ด๊ธฐ ์์น๋ฅผ ๋๋น๋งํผ ํ์ฌ View๋ก๋ถํฐ ์์ ๋ฐฉํฅ์ผ๋ก Constraints๋ฅผ viewDidLoad์์ ์ ์ค์ ํ ๋ค์, ViewWillAppear ์์ ์ Constraints๋ฅผ ํ์ฌ View๋ก ๋ง์ถฐ์ฃผ์ด UIView.animate() ๋ฉ์๋๋ฅผ ์คํํ์ผ๋, ๋ทฐ์ ์ ๋๋ฉ์ด์ ์ด X ์ขํ ๋ฟ๋ง ์๋๋ผ Y์ขํ๋ ๊ฐ์ด Animation์ด ์คํ๋๋ ๋ฌธ์ ์ ์ด ๋ฐ์
private func sideBarAppearAnimation() {
self.sideBarView.snp.updateConstraints { make in
make.leading.equalTo(self.view)
}
UIView.animate(withDuration: 0.5, delay: 0) {
self.view.layoutIfNeeded()
}
}
- ๋๋ฒ๊น ์ ์งํํ์ ๋, viewWillAppear์์ ์ ๊น์ง ์ฌ์ด๋๋ฐ View์ ์ด๊ธฐ ํฌ๊ธฐ ๋ฐ ์์น๊ฐ ๋ชจ๋ ์ ํด์ง์ง ์๋ ์ํ์์ ํ์ธ
Main event loop
์ ๊ฐ๋ ์ด ํ์ํจ.- ๋ฌด์์ Constraints๋ฅผ ์ค์ ํ๋ค๊ณ ํด์ ๋ฐ๋ก View์ Constraints๊ฐ ์ ์ฉ๋์ด ๋ทฐ์ ์์น์ ํฌ๊ธฐ๊ฐ ๊ฒฐ์ ๋๋ ๊ฒ์ด ์๋.
Main run loop
์ ์์ ์ด ๋์๋์ด์ผ ๋น๋ก์ ์ค์ง์ Constraints๊ฐ ์ ์ฉ๋์ด ๋ทฐ์ ์์น์ ํฌ๊ธฐ๊ฐ ๊ฒฐ์ ๋จ.- UIView.animate()๋ Scope๋ด์์์ View ๋ณ๊ฒฝ์ฌํญ์ ๊ทธ ์ด์ ๊ณผ ๋น๊ตํ์ฌ ์ ๋๋ฉ์ด์ ์ ์คํํ๋ ๊ตฌ์กฐ๋ก ๋์ํจ.
- ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ViewDidLoad() ์คํ ์์ ๊ณผ ViewWillAppear()๊ฐ ์คํ๋๋ ์์ ์ ์ฐจ์ด๊ฐ ๊ต์ฅํ ์งง์ ๊ฒฝ์ฐ, ์ค์ง์ ์ธ ์ด๊ธฐ Constraints๊ฐ ์ ์ฉ๋๊ธฐ ์ ์ Constratints๊ฐ ๋ฎ์ด์ฐ๊ธฐ ๋์ด ์ขํ(0, 0)๊ณผ Frame(0, 0)์ ์ํ์์ ์ต์ข ์ ๋๋ฉ์ด์ ์ด ์คํ๋๋ ๊ฒ์ด๊ธฐ์ ์ด๋ฌํ ๋ฌธ์ ๊ฐ ๋ฐ์.
- Constraints๊ฐ ๋ฎ์ด์ฐ๊ธฐ ๋๊ธฐ ์ ์
Main run loop
๋ฅผ ์์๋ก ๋์์์ผ ์ด๊ธฐ ๋ทฐ๋ฅผ ์ค์ ํด ์ค ๋ค์, Constraints๋ฅผ ๋ฐ๊พธ์ด animate๋ฅผ ์คํํ๋ฉด ํด๋น ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋จ.
private func sideBarAppearAnimation() {
self.view.layoutIfNeeded() //AutoLayout์ ํตํด ๋ทฐ์ ์ด๊ธฐ ์์น์ ํฌ๊ธฐ๋ฅผ ์ก์๊ธฐ์ ์ ๋๋ฉ์ด์
์ ํด๋น ๋ฉ์๋ ์คํ -> ๋ทฐ๊ฐ ์ค์ ๋ก ๋ณด์ฌ์ง๊ธฐ ์ ๊น์ง ์ด๊ธฐ AutoLayout์ ์คํ๋์ง ์์.
sideBarView.snp.updateConstraints { make in
make.leading.equalTo(self.view)
}
UIView.animate(withDuration: 0.5, delay: 0) {
self.view.layoutIfNeeded()
}
}
๋ฌธ์ ์ํฉ | ์ ์ |
---|---|
![]() |
![]() |
-
Left Bar Button Item์ ๊ธฐํ ๋ฐ ๋์์ธ์ ๋ง์ถ์ด ๋ฒํผ ํฌ๊ธฐ์ ์ค์ ์ด ํ์ํจ.
let workSpaceImageButton = UIButton().then { view in view.frame = CGRect(origin: .zero, size: CGSize(width: 30, height: 30)) let defaultImage = UIImage(named: "WorkSpace") view.setBackgroundImage(defaultImage, for: .normal) view.backgroundColor = .clear view.layer.cornerRadius = 8 view.clipsToBounds = true view.contentMode = .scaleAspectFit } lazy var workSpaceImageBarButton = UIBarButtonItem(customView: workSpaceImageButton) ... navigationItem.setLeftBarButton(workSpaceImageBarButton, animated: true)
-
์ด ์ํฉ์์ ๋ฒํผ์ ์ฌ์ด์ฆ๋ฅผ Constraints ํน์ Frame์ผ๋ก ํฌ๊ธฐ๋ฅผ ์ค์ ํด ์ฃผ์ด๋ ์ง์ ํ ์ฌ์ด์ฆ๋๋ก ๊ตฌํ๋์ง ์๋ ๋ฌธ์ ๋ฐ์.
-
UIButton
์์ image๋ฅผ ์ค์ ํ๋ ๊ฒฝ์ฐ, ์ค์ ํ image์ ํฌ๊ธฐ์ ๋ฐ๋ผ button๋ด ImageView์ ํฌ๊ธฐ๊ฐ ๊ฒฐ์ ๋๊ณ button์ ํด๋น imageView์ ํฌ๊ธฐ๋ณด๋ค ์๊ฒ ์ค์ ๋ ์ ์๊ธฐ ๋๋ฌธ์ ํด๋น ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ํ์ธ. -
button ๋ด image๋ฅผ ์ค์ ํ๊ณ ์ถ์ button์ ์ฌ์ด์ฆ๋ณด๋ค ์๊ฒ resizingํ์ฌ button์ ์ฌ์ด์ฆ๋ฅผ ์ค์ ํด์ฃผ๋ฉด ์ ์์ ์ผ๋ก ์ฌ์ด์ฆ ์กฐ์ ์ด ๊ฐ๋ฅ.
let workSpaceImageButton = UIButton().then { view in view.frame = CGRect(origin: .zero, size: CGSize(width: 30, height: 30)) let defaultImage = UIImage(named: "WorkSpace")?.resizingByRenderer(size: CGSize(width: 30, height: 30), tintColor: .BackgroundColor.backgroundPrimaryColor) view.setBackgroundImage(defaultImage, for: .normal) view.backgroundColor = .clear view.layer.cornerRadius = 8 view.clipsToBounds = true view.contentMode = .scaleAspectFit } lazy var workSpaceImageBarButton = UIBarButtonItem(customView: workSpaceImageButton) ... navigationItem.setLeftBarButton(workSpaceImageBarButton, animated: true)
- ์ต์ด๋ก PG์ฌ์ SDK๋ฅผ ํตํด ๊ฒฐ์ ๋ฅผ ๋ฌ ์ ์์ด, ๊ฒฐ์ ์์คํ ๊ตฌํ์ ๋ํ ๋๋ ค์์ด ํด์๋์๋ค.
- ์ด๊ฑฐํ์ RawValue๋ก ์ด๊ธฐํ ํด์ผํ๋ ์ํฉ์์ ์ถ์ํ๋ฅผ ํ๊ธฐ ์ํด ๋ง์ ๊ณ ๋ฏผ์ ๋์
RawValue Protocol
์ ์๊ฒ๋์๊ณ ์ด๋ฅผ ํตํด NetworkError์ ๊ดํด์ ์ถ์ํํ์ฌ Generic์ฌ์ฉ์ด ๊ฐ๋ฅํ๊ฒ ํ์ฌ ์ฌ์ฌ์ฉ์ฑ์ ๋์ผ ์ ์๊ฒ ๋์๋ค. - Moya์ TargetType(Router Pattern)์ DI๋ฅผ ํตํด ๋ถ๋ฆฌ๋ฅผ ํ๋ค๋ฉด ์ ์ง๋ณด์์ฑ์ด ์ข๊ณ ๊ฐ๊ฒฐํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ ๊ฒ ๊ฐ์ง๋ง ์ค์ ๋ก ์ ์ฉํ์ง ๋ชปํด ์์ฝ๋ค.