์๋ฌดํผ ์ค๋ผ์ ๋ฐ์ ๊ผฌ๋ผ์ค์คํฌ ํ๊ณ
๋ ์ง๊ณ !!!!!!!! ๋ ๐๊ผฌ๋ผ์ค์คํฌ ๊นํ๋ธ๐
์ด๋ฒ ํ๋ก์ ํธ๋ ํค์ค์คํฌ ์ฑ์ ๋ง๋ค๊ณ ์ฃผ์ด์ง ํ์ ๊ตฌํ์ ๋๊น์ง ์งํํ๋ ๊ฒ์ ๋ชฉํ๋ก ์ก๊ณ ์งํํ๋ค. ์ฌ์ฉ์๋ค์ด ๋งค์ฅ์ ์ง์ ๋ฐฉ๋ฌธํ์ง ์๊ณ ๋ ํธ๋ฆฌํ๊ฒ ๋ฉ๋ด๋ฅผ ์ฃผ๋ฌธํ ์ ์๋๋ก ๋์์ฃผ๋ ์ฑ์ ๊ตฌํํ๋ ค๊ณ ๋ ธ๋ ฅํ๋ค. ๋๋ ์ฅ๋ฐ๊ตฌ๋ ๊ธฐ๋ฅ๊ณผ ๊ด๋ จํ์ฌ ์ฌ์ฉ์๊ฐ ์ง๊ด์ ์ผ๋ก ์ํ์ ์ถ๊ฐํ๊ฑฐ๋ ์๋์ ๋ณ๊ฒฝํ๋ ๊ฒฝํ์ ์ ๊ณตํ๋ ๋ฐ ์ค์ ์ ๋์๋ค.
๋๋ ์ฅ๋ฐ๊ตฌ๋ ํํธ๋ฅผ UIView
, UIStackView
, UITableView
๋ฑ์ ํ์ฉํ์ฌ ๊ตฌํํด๋ณด์๋ค. ์๋ ์กฐ์ , ์ํ ์ถ๊ฐ ๋ฐ ์ญ์ ๊ธฐ๋ฅ์ ํฌํจํ ์ฅ๋ฐ๊ตฌ๋ UI๋ฅผ ๋ด๋นํ๋ฉฐ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌ์ฑํ ์ ์์๋ค. ์ด ์ธ์๋ ํ๊ณผ ํจ๊ป README
์์ฑ ๋ฑ ๋ฌธ์ํ์ ๋์์ ์ฃผ๊ณ ์ ๋
ธ๋ ฅํ์ผ๋ฉฐ, Git ์ปจ๋ฒค์
๊ณผ ๋จธ์ง ์ ๋ต์ ๋ํด ์๊ฒฌ์ ๋ง์ด ๋ํ๋ค.
๋๋ ํ์ ๊ธฐ๋ฅ ๊ตฌํ์ ๋ง์น๊ณ README
๋ฌธ์ ์์ฑ์ ์ฐธ์ฌํ์ฌ ํ๋ก์ ํธ์ ๋ฌธ์ํ๋ฅผ ์ฒด๊ณ์ ์ผ๋ก ์งํํ๋ค. ์ค๋๋ง์ ๋ฌธ์ํ ์์
์ ํ๋ฉฐ ๋ด๊ฐ ๋์ณค๋ ๋ถ๋ถ๋ค์ ๋ค๋ฌ์ ์ ์๋ ์ข์ ๊ณ๊ธฐ๊ฐ ๋์๋ค๊ณ ์๊ฐํ๋ค.
๋ Git์ ๋ํด ๋ ๊น์ด ๊ณต๋ถํ๋ฉฐ ํ์๋ค๊ณผ์ ํ์
์ ์ํํ๊ฒ ๋ง๋ค๊ธฐ ์ํด ๋
ธ๋ ฅํ๋ค. ํ์๋ค๊ณผ ๊ฐ์ด Git์ ๋ํด ํจ๊ป ๋ฐฐ์ฐ๋ฉฐ ์ฑ์ฅํ๋ ๋ชจ์ต์ ๋ณผ ์ ์์๊ณ , ์ด๋ฅผ ํตํด ํ ์ ์ฒด์ ์ญ๋์ด ์์นํ ๊ฒ์ด ๋๊ปด์ ธ ์ ๋ง ๋ฟ๋ฏํ๋ค.
์์ฌ์ด ์ ์ผ๋ก๋ ์ญ์ ์์ง ๋ด ์ค๋ ฅ์ ๋ํด ๋ถ์กฑํจ์ ๋๋ผ๋ ๊ฒ. ๋ฐฐ์ด ๋ด์ฉ์์ ๋ฒ์ด๋, ์์ ๋ก์ด ํ๋ก์ ํธ์๊ธฐ์ ๋ฐฉํฅ ์ค์ ์ด ์ด๋ ต๊ฒ ๋๊ปด์ก๋ค. ๊ทธ๋์์ธ์ง ๋๋ถ๋ถ ํ์๋ค์๊ฒ ์์กดํ๋ ์ํฉ์ด ๋ง์๋ค.
์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ํตํด ํํ๋ ์ด์ ์ค์์ฑ์ ํฌ๊ฒ ๋ฐฐ์ ๋ค. ํ์๋ค์ด ๊ฐ์ ์์ ์ ์ญํ ์ ์ถฉ์คํ ์ํํ๋ฉด์, ๋ถ์กฑํ ๋ถ๋ถ์ ์๋ก ๋ณด์ํด ๋๊ฐ๋ ๊ณผ์ ์ ํตํด ์ข์ ํ์ ์ด ๋ฌด์์ธ์ง ๋๋ ์ ์์๋ค. ํผ์๋ง์ ์์ ์ด ์๋๋ผ ํ๋ ฅ๊ณผ ์กฐ์จ์ ํตํด ์ฑ๊ณผ๋ฅผ ๋ง๋ค์ด๊ฐ๋ ๊ฒ์ด ํํ๋ ์ด์ ๋ณธ์ง์์ ์ฒด๊ฐํ๊ณ , ๊ทธ๋ก ์ธํด ๋ด๊ฐ ํ์๋ค๋ก๋ถํฐ ๋ง์ ๋ฐฐ์์ ์ป์ ์ ์์๋ค. ํ์๋ค ๊ฐ์๊ฐ ๋งก์ ์ญํ ์ ์ด์ฌํ ์ํํ๋ฉฐ ๋์์ ์ฃผ๋ ๋ชจ์ต์ ๋ณด๋ฉด์ ์ ๋ง ์กด๊ฒฝ์ค๋ฌ์ ๋ค. ๋ฌผ๋ก ๋งค์ผ ๋ฐฉ๋ฌธํด์ฃผ์๋ ํํฐ๋์ ๋์๊ณผ ์กฐ์ธ๋ ์์ ์ ์๋ค.
ํ์ฌ์์ ์ฃผ๋ก ํผ์ ์ผํ๋ ๋๋ ์ด๋ฒ ํ ํ๋ก์ ํธ๊ฐ ์ค๋๋ง์ ํ์ ์ด์๋ค. ๊ฐ์์ ์๊ฒฌ์ ๋๋๊ณ ์ต์ ์ ํด๊ฒฐ์ฑ ์ ์ฐพ์๊ฐ๋ ๊ณผ์ ์์ ๋ง์ ์ฌ๋ฏธ์ ์๋ฏธ๋ฅผ ๋๋ ์ ์์๋ค. ํนํ ํ์ด ํ๋ก๊ทธ๋๋ฐ์ ํตํด ํจ๊ป ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉฐ ์ป์ ์ฌ๋ฏธ๊ฐ ์ปธ๊ณ , ํ์๊ณผ ๊ต๋ฅํ๋ฉฐ ๋ง์ ๊ฒ์ ๋ฐฐ์ธ ์ ์์๋ค. ๋ฌธ์ ํด๊ฒฐ์ ์ํด ํจ๊ป ์์ด๋์ด๋ฅผ ๊ณต์ ํ๊ณ ๊ฐ์ ์ ์ ์ฐพ์๊ฐ๋ ๊ณผ์ ์ด ํฐ ์๋์ง๋ฅผ ์ฃผ์๊ณ , ์ด๋ฅผ ํตํด ํ์ ์ ์์ํ ์ฆ๊ฑฐ์์ ๋ค์๊ธ ๊นจ๋ฌ์๋ค.
๋ค์ ํ๋ก์ ํธ์์๋ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ ์ ๊ฒฝ ์ฐ๊ณ ์ถ๋ค. ํ์ ๊ธฐ๋ฅ ๊ตฌํ์ ์ง์คํ๋๋ผ UX๋ฅผ ์ถฉ๋ถํ ๊ณ ๋ คํ์ง ๋ชปํ ์ ์ด ์์ฌ์ ๋๋ฐ, ์ด์ ๋ ์ฌ์ฉ์ ๊ด์ ์์ ์ข ๋ ํธ๋ฆฌํ๊ณ ์ง๊ด์ ์ธ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ๊น์ด ๊ณ ๋ฏผํด๋ณด๋ ์๊ฐ์ด ์ถฉ๋ถํ์ผ๋ฉด ์ข๊ฒ ๋ค. ๋ํ, ํ์๋ค์๊ฒ ๋ ๋ง์ ๊ธฐ์ ์ ๋์์ ์ค ์ ์๋ ์ฌ๋์ด ๋๊ธฐ ์ํด ์ง์์ ์ธ ํ์ต๊ณผ ์ฃผ๋์ ์ธ ๋ฌธ์ ํด๊ฒฐ์ ๋์ ํ๊ณ ์ถ๋ค.
์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ํนํ UIKit๊ณผ ๊ด๋ จ๋ ๋ค์ํ ์์๋ค์ ๋ ๊น์ด ์ดํดํ๊ณ , ์ฌ์ฉ์ ์ธํฐํ์ด์ค(UI)๋ฅผ ๊ตฌํํ๋ ๋ฐฉ์์ ๋ํด ๋ง์ ์ฑ์ฅ์ ์ด๋ค?๋ค๊ณ ์๊ฐํ๋ค.
UIStackView์ UITableView ํ์ฉ ๋ฅ๋ ฅ +1
// UITableView์ UIStackView๋ฅผ ํ์ฉํ ์ฅ๋ฐ๊ตฌ๋ UI ๊ตฌ์ฑ
let cartTableView = UITableView()
let headerStackView = UIStackView()
// StackView์ TableView๋ฅผ ๋ทฐ์ ์ถ๊ฐ
view.addSubview(headerStackView)
view.addSubview(cartTableView)
headerStackView.axis = .horizontal
headerStackView.distribution = .fillEqually
// ์ ์ฝ์กฐ๊ฑด ์ค์
headerStackView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(16)
make.leading.trailing.equalToSuperview().inset(16)
make.height.equalTo(50)
}
cartTableView.snp.makeConstraints { make in
make.top.equalTo(headerStackView.snp.bottom).offset(16)
make.leading.trailing.bottom.equalToSuperview().inset(10)
}
UIStackView
์ UITableView
๋ฅผ ์ฌ์ฉํด ์ ๋์ ์ธ UI ๊ตฌ์ฑ ์์๋ฅผ ๋ง๋ค๋ฉด์, ๋ค์ํ ์ํฉ์ ๋ฐ๋ผ ๋ ์ด์์์ ์ด๋ป๊ฒ ์กฐ์ ํ ์ ์๋์ง ๋ฐฐ์ธ ์ ์์๋ค. ํนํ ์ฅ๋ฐ๊ตฌ๋ ํ๋ฉด์์ ์ํ์ ์ค์๊ฐ์ผ๋ก ์กฐ์ ํ ์ ์๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ฉด์, UITableView
์ ๋ฐ์ดํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฐ๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๊ฒฝํํ ์ ์์๋ค.
์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๊ตฌ์กฐํ๋ ์ค๊ณ์ ์ค์์ฑ ์ดํด
// ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ CartTableViewCell
class CartTableViewCell: UITableViewCell {
private let menuLabel = UILabel()
private let decreaseQuantityButton = UIButton()
private let increaseQuantityButton = UIButton()
private let quantityLabel = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUpCell()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setUpCell() {
// UI ์์ ์ถ๊ฐ ๋ฐ ๋ ์ด์์ ์ค์
let stackView = UIStackView(arrangedSubviews: [decreaseQuantityButton, quantityLabel, increaseQuantityButton])
stackView.axis = .horizontal
stackView.spacing = 8
contentView.addSubview(menuLabel)
contentView.addSubview(stackView)
menuLabel.snp.makeConstraints { make in
make.leading.top.equalToSuperview().offset(16)
}
stackView.snp.makeConstraints { make in
make.trailing.top.equalToSuperview().offset(16)
}
}
func configure(with menu: String, quantity: Int) {
menuLabel.text = menu
quantityLabel.text = "\(quantity)"
}
}
๊ฐ UI ์์๋ฅผ ๋ณ๋์ ์ปค์คํ
๋ทฐ๋ ์
๋ก ๋ถ๋ฆฌํ๊ณ ์ด๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ์์ ํตํด ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ์ ๋์๋ค.(?) ์๋ฅผ ๋ค์ด, CartTableViewCell
์ ํ์ฉํด ์ฅ๋ฐ๊ตฌ๋ ๋ด ์ํ์ ์ ๋ณด๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ํํํ๋ฉด์ ๋ฐ๋ณต๋๋ ์ฝ๋๋ฅผ ์ค์ผ ์ ์์๊ณ , ์
๋ด๋ถ์ ๋ฒํผ์ ํ์ฉํด ์ฌ์ฉ์ ์ก์
์ ์ฒ๋ฆฌํ๋ ๋ก์ง์ ํจ์จ์ ์ผ๋ก ์์ฑํ ์ ์์๋ค. ์ด ๊ณผ์ ์์ ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๊ตฌ์กฐํ๋ ์ค๊ณ์ ์ค์์ฑ์ ๋์ฑ ๊น์ด ์ดํดํ๊ฒ ๋์๋ค.
ํด๋ก์ ๋ฅผ ์ฌ์ฉํ ๋์ UI ์ ๋ฐ์ดํธ ๊ฒฝํ
// ํด๋ก์ ๋ฅผ ์ฌ์ฉํ ๋ฒํผ ์ก์
๊ตฌํ
class CartTableViewCell: UITableViewCell {
var minusButtonTapped: (() -> Void)?
var plusButtonTapped: (() -> Void)?
private let decreaseQuantityButton = UIButton()
private let increaseQuantityButton = UIButton()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setUpButtons()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setUpButtons() {
decreaseQuantityButton.setTitle("-", for: .normal)
decreaseQuantityButton.addTarget(self, action: #selector(handleMinusButtonTapped), for: .touchUpInside)
increaseQuantityButton.setTitle("+", for: .normal)
increaseQuantityButton.addTarget(self, action: #selector(handlePlusButtonTapped), for: .touchUpInside)
contentView.addSubview(decreaseQuantityButton)
contentView.addSubview(increaseQuantityButton)
// ๋ฒํผ ๋ ์ด์์ ์ค์ (SnapKit ์ฌ์ฉ ์์)
decreaseQuantityButton.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(16)
make.centerY.equalToSuperview()
}
increaseQuantityButton.snp.makeConstraints { make in
make.trailing.equalToSuperview().offset(-16)
make.centerY.equalToSuperview()
}
}
@objc private func handleMinusButtonTapped() {
minusButtonTapped?()
}
@objc private func handlePlusButtonTapped() {
plusButtonTapped?()
}
}
CartTableViewCell
์์ ์๋์ ์ฆ๊ฐ์ํค๊ฑฐ๋ ๊ฐ์์ํค๊ธฐ ์ํด ํด๋ก์ (minusButtonTapped
, plusButtonTapped
)๋ฅผ ์ฌ์ฉํ๋ค. ์ด ์ ๊ทผ ๋ฐฉ์์ ํตํด, ๋ฒํผ์ด ๋๋ ธ์ ๋ ์ฆ๊ฐ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๊ณ ์ด๋ฅผ UI์ ๋ฐ์ํ๋ ์ค์๊ฐ ์
๋ฐ์ดํธ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์๋ค. ํนํ ํด๋ก์ ๋ฅผ ์ด์ฉํด ๋ถ๋ชจ ๋ทฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๊ฒฐํ๊ณ ์กฐ์ํ๋ฉด์, ํด๋ก์ ์ ๊ฐ๋ ฅํจ๊ณผ ์ด์ ๋ฐ๋ฅธ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ์ค์์ฑ์ ๋ฐฐ์ฐ๊ฒ ๋์๋ค.
ํ ๋ฆฌ๋์ธ Eric๋์ ์ฝ๋ ๊ฐ๋ผ์ผ๋ฅผ 1์ด ์ง๊ดํ์ฌ ๋น๋ก์ ์ดํดํ ์ ์๊ฒ ๋ ์์
์ด๋ค.
SnapKit์ ํตํ ์ง๊ด์ ์ธ ๋ ์ด์์ ๊ด๋ฆฌ
SnapKit
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ๋ ์ด์์์ ์ง๊ด์ ์ด๊ณ ํจ์จ์ ์ผ๋ก ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ์ตํ๋ค. ์ ์ฝ ์กฐ๊ฑด์ ์ฝ๋๋ก ์ค์ ํ๋ ๊ฒ์ด ์ด๋ ค์ธ ์ ์์์ง๋ง, SnapKit
์ ํ์ฉํด ๊ฐ๋
์ฑ ๋์ ๋ ์ด์์ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์๊ณ , ํนํ ๋ค์ํ ๊ธฐ๊ธฐ์์ ๋ ์ด์์์ด ์ผ๊ด๋๊ฒ ๋ณด์ด๋๋ก ์ ์งํ ์ ์์๋ค.
๋ฐ์ดํฐ ํ๋ฆ๊ณผ ์ํ ๊ด๋ฆฌ์ ์ดํด
func updateCartData() {
tableView.reloadData()
cartHeaderStackView.updateTotalCount(newCount: cartManager.totalCount)
}
์ฅ๋ฐ๊ตฌ๋์ ์ํ ์๋์ ์กฐ์ ํ๊ณ , ์ฃผ๋ฌธ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค UI๋ฅผ ์
๋ฐ์ดํธํ๋ ์์
์ ์งํํ๋ฉด์ ๋ฐ์ดํฐ ํ๋ฆ๊ณผ ์ํ ๊ด๋ฆฌ๋ฅผ ์ฒด๊ณ์ ์ผ๋ก ์ดํดํ๋ ์๊ฐ์ ๊ฐ์ง ์ ์์๋ค. ํนํ reloadData()
๋ฅผ ํตํด UITableView
์ ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ์ํ๊ณ , CartHeaderStackView
์ ๋ผ๋ฒจ์ ์
๋ฐ์ดํธํ๋ ๊ณผ์ ์์ ์ํ ๊ด๋ฆฌ์ ์ค์์ฑ๊ณผ ์ด๋ฅผ ์ ํํ๊ฒ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ฐฐ์ ๋ค.
์ฌ์ฉ์ ์ค์ฌ์ UX ๊ณ ๋ ค
// ์ฅ๋ฐ๊ตฌ๋๊ฐ ๋น์ด ์์ ๋ ์๋ด ๋ฌธ๊ตฌ ํ์
if cartManager.orders.isEmpty {
emptyCartLabel.isHidden = false
} else {
emptyCartLabel.isHidden = true
}
์ฅ๋ฐ๊ตฌ๋๊ฐ ๋น์ด ์์ ๋ ์๋ด ๋ฌธ๊ตฌ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฑ ์ฌ์ฉ์ ๊ฒฝํ(UX)์ ๊ณ ๋ คํ UI๋ฅผ ๊ตฌ์ฑํ๋ ค๊ณ ๋ ธ๋ ฅํ๋ค. ์ฌ์ฉ์ ์ ์ฅ์์ ์ฑ์ ๋ณด๋ค ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก UI์ ์ธ๋ถ์ ์ธ ๋ถ๋ถ๊น์ง ์ ๊ฒฝ ์ฐ๋ฉด์, ์ฌ์ฉ์ ๊ฒฝํ์ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ผ๋ง๋ ์ค์ํ์ง ๊นจ๋ฌ์๋ค. ๋ค์๋ฒ์ ์ข ๋ ๊ณ ๋ฏผํด๋ณด๊ณ ์ถ๋ค!
์ข์ ํ์์ ๋ง๋๋ ๊ฒ์ด ์ผ๋ง๋ ์ค์ํ๊ฐ.
ํ์ ๋ด๊ฐ ์ ํํ ๊ฒ์ด ์๋๋ผ ๋ฌด์์๋ก ์ฃผ์ด์ง ์ด๋ช
์ด๊ธฐ์ ๋ ํฐ ์๋ฏธ๋ก ๋ค๊ฐ์๋ค. ํนํ ์ข์ ํ์๋ค๊ณผ ํจ๊ป๋ผ๋ฉด ์ด๋ ค์ด ๋ฌธ์ ๋ ํจ๊ป ํด๊ฒฐํ ์ ์๋ค๋ ์ ์ ์ฒด๊ฐํ๋ค. ์ด๋ฒ ํ๋ก์ ํธ์์ ์ข์ ํ์๋ค์ ๋ง๋ ๊ฒ์ ์ ๊ฒ ํฐ ํ์ด์ด์๊ณ , ๋๋ถ์ ํ๋ก์ ํธ๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๋ง๋ฌด๋ฆฌํ ์ ์์๋ค๊ณ ์๊ฐํ๋ค. ๊ณ์ฐํด์กฐ ํ์ ๋ง๋๊ฒ ๋ ๊ฒ์ ์ ๋ง ์๊ด์ด์์ผ๋ฉฐ, ์์ผ๋ก์ ํ์
์์๋ ํฐ ๋ฐ๊ฑฐ๋ฆ์ด ๋ ๊ฒ์ด๋ผ ํ์ ํ๋ค. ๐