iOS_calculator README (Joo & Lust3r)


๐Ÿงฎ ๊ณ„์‚ฐ๊ธฐ ๋™์ž‘

## ๐Ÿ—‚๏ธ ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๊ตฌ์กฐ


๐Ÿ•ต๐Ÿป ์—ญํ•  ๋ถ„๋ฐฐ

enum ์—ญํ• 
Operator Character, CalculateItem, CaseIterable์„ ์ฑ„ํƒํ•˜์˜€๊ณ , ๊ฐ ์—ฐ์‚ฐ์ž case ๋ฐ ๊ฐ ์—ฐ์‚ฐ์ž๊ฐ€ ๋“ค์–ด์™”์„ ๋•Œ ๊ทธ์— ๋งž๋Š” ์—ฐ์‚ฐ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก calculate ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜
ExpressionParser String ํ˜•ํƒœ์˜ ์ˆซ์ž ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” componentsByOperators์™€ ์—ฐ์‚ฐ์ž ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” extractOperators๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ input ๊ฐ’์„ ํŒŒ์‹ฑํ•˜๊ณ , ๊ทธ ๊ฐ’์„ ํ†ตํ•ด Formula๋ฅผ ๊ตฌ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ธฐ๋Šฅ
struct ์—ญํ• 
Formula Double ํƒ€์ž…์˜ CalculateItemQueue๋ฅผ ๊ฐ–๋Š” operands์™€ Operator ํƒ€์ž…์˜ CalculateItemQueue๋ฅผ ๊ฐ–๋Š” operators๋ฅผ ํ”„๋กœํผํ‹ฐ๋กœ ์‚ผ์€ ๊ตฌ์กฐ์ฒด. result ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๊ฐ ItemQueue์—์„œ ๊ฐ’์„ dequeueํ•˜์—ฌ ๊ฒฐ๊ณผ๊ฐ’์„ Double๋กœ ๋ฐ˜ํ™˜
CalculatorItemQueue ์ œ๋„ค๋ฆญ ํƒ€์ž…์˜ ๋ฐฐ์—ด์„ queue๋กœ ๊ฐ€์ง€๋ฉฐ, ์ธ์ž๋กœ ๋ฐ›์€ ์–ด๋– ํ•œ ํƒ€์ž…์˜ ๋ฐฐ์—ด๋„ init์—์„œ enqueue ๊ณผ์ •์„ ํ†ตํ•ด ํ•ด๋‹น ํƒ€์ž…์˜ queue๋ฅผ ์ƒ์„ฑ. queue์˜ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ์ธ enqueue์™€ dequeue, ๊ทธ๋ฆฌ๊ณ  ํ๋ฅผ ๋น„์šฐ๋Š” allClear ๋ฉ”์„œ๋“œ๋ฅผ ํฌํ•จ
protocol ์—ญํ• 
CalculateItem Operator, Double์—์„œ CalculateItem๋ฅผ ์ฑ„ํƒํ•˜์—ฌ CalculateItemQueue์˜ ์š”์†Œ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋„๋ก ์ƒ์„ฑ
extension ์—ญํ• 
Operator ์—ฐ์‚ฐ์ž๋ฅผ ์—ด๊ฑฐํ˜•์œผ๋กœ ์ •์˜. calculate ๋ฉ”์„œ๋“œ์—์„œ private ํƒ€์ž…์˜ add, substract, divide, multiply ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„. ์€๋‹‰ํ™”๋œ ์—ฐ์‚ฐ ๋ฉ”์„œ๋“œ๋“ค์€ ์ด๋ฆ„๊ณผ ๋™์ผํ•œ ๊ณ„์‚ฐํ•ด์„œ Double๊ฐ’์œผ๋กœ ๋ฐ˜ํ™˜
Double CalculateItemQueue์˜ ์š”์†Œ๋กœ ์‚ฌ์šฉ๋˜๋„๋ก CalculateItem์„ ์ฑ„ํƒ
function ์—ญํ• 
allClear ์ž…๋ ฅ๋ฐ›์•˜๋˜ ๋‚ด์šฉ๋“ค์„ ์ดˆ๊ธฐํ™”
clearEntry ์ž…๋ ฅ๋ฐ›์€ ์ˆซ์ž ํ˜น์€ ์†Œ์ˆ˜์ ์„ ์ œ๊ฑฐ
(๋‹จ, ๊ฒฐ๊ณผ๊ฐ’์€ ์‚ญ์ œ ๋ถˆ๊ฐ€)
changeSign ์ž…๋ ฅ๋ฐ›์€ ์ˆซ์ž์˜ ๋ถ€ํ˜ธ๋ฅผ ๋ณ€๊ฒฝ, ์Œ์ˆ˜๋ผ๋ฉด ์–‘์ˆ˜๋กœ ๋ณ€ํ™˜์„ ํ•˜๊ณ  ์–‘์ˆ˜๋ผ๋ฉด ์Œ์ˆ˜๋กœ ๋ณ€ํ™˜
addDecimalPoint ์ž…๋ ฅ๋ฐ›์€ ์ˆซ์ž์˜ ์†Œ์ˆ˜์ ์„ ๋ถ€์—ฌ
(๋‹จ, ์ด๋ฏธ ์ž…๋ ฅ๋ฐ›์•˜๋‹ค๋ฉด ์ž…๋ ฅ ๋ถˆ๊ฐ€)
addOperand ๊ณ„์‚ฐํ•˜๊ณ ์ž ํ•˜๋Š” ์ˆซ์ž๋ฅผ ์ž…๋ ฅ
addOperator ๊ณ„์‚ฐํ•˜๊ณ ์ž ํ•˜๋Š” ์—ฐ์‚ฐ์ž๋ฅผ ์ž…๋ ฅ, ์ˆซ์ž๋ฅผ ์ž…๋ ฅ๋ฐ›์€ ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๊ธฐ์กด์˜ ์—ฐ์‚ฐ์ž๋ฅผ ๋ณ€๊ฒฝ
calculateResult ๊ณ„์‚ฐ์„ ํ•˜๊ณ ์ž ์ถ”๊ฐ€ํ•œ ์‹๋“ค์„ ๊ณ„์‚ฐํ•˜์—ฌ ๋ฐ˜ํ™˜
addFormulaStackView ์ž…๋ ฅ๋œ operand์™€ operator๋กœ UILabel์„ ์ƒ์„ฑํ•˜๊ณ , Stack์— addArrangedSubView๋ฅผ ํ†ตํ•ด ๋‹ด์€ ํ›„ ScrollView์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ์ถ”๊ฐ€
formattingNumber NumberFormatter()๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜๋กœ, formatter ์„ค์ •์„ ํ†ตํ•ด ์†Œ์ˆ˜์  ์ž๋ฆฌ์ˆ˜ 20, numberStyle = .decimal์„ ํ†ตํ•ด ์ฒœ๋‹จ์œ„ ๊ตฌ๋ถ„ ํ‘œ์‹œ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ
convertOperand ์ •์ˆ˜๋ถ€๋ฅผ ์ฒœ๋‹จ์œ„ ๊ตฌ๋ถ„ ํ‘œ์‹œ ํ•˜๋ฉด์„œ ์†Œ์ˆ˜๋ถ€๊ฐ€ '0'์ด๋‚˜ '00'์ด์–ด๋„ ๊ฐ™์ด ํ™”๋ฉด์— ๋ณด์ผ ์ˆ˜ ์žˆ๋„๋ก operand๋ฅผ ์ •์ˆ˜๋ถ€์™€ ์†Œ์ˆ˜๋ถ€๋กœ ๋‚˜๋ˆ„์–ด ์ •์ˆ˜๋ถ€๋Š” Formatting ์ง„ํ–‰, ์†Œ์ˆ˜๋ถ€๋Š” ๊ทธ ๊ฒฐ๊ณผ์— ๋ง๋ถ™์ด๋Š” ์‹์œผ๋กœ operand๋ฅผ convert
isInitialOperand enteredOperand๊ฐ€ ์ดˆ๊ธฐ๊ฐ’์ธ '0'์ธ์ง€ ํ™•์ธ

Step1 - Queue ํƒ€์ž… ๊ตฌํ˜„

PR #13 | Step1 - Queue ํƒ€์ž… ๊ตฌํ˜„

๊ตฌํ˜„ ๋‚ด์šฉ

  • Queueํƒ€์ž…์œผ๋กœ ๊ตฌํ˜„์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ enqueue, dequeue๋ฅผ ํ•„์ˆ˜ ๊ตฌํ˜„
  • Queue์˜ ์š”์†Œ์—์„œ ์‚ฌ์šฉ๋  ํƒ€์ž…์„ CalculateItem์œผ๋กœ ์ฑ„ํƒ

Step2 - ๊ณ„์‚ฐ ํƒ€์ž… ๋ฐ ์ฃผ๋ณ€ ํƒ€์ž… ๊ตฌํ˜„

PR #21 | Step2 - ๊ณ„์‚ฐ ํƒ€์ž… ๋ฐ ์ฃผ๋ณ€ ํƒ€์ž… ๊ตฌํ˜„

๊ตฌํ˜„ ๋‚ด์šฉ

  • UML์— ๋งž๊ฒŒ ๊ฐ ๊ตฌ์„ฑ์š”์†Œ ๊ตฌํ˜„
    • CalculateItem ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๋Š” extension Double, Enum Operator ๊ตฌํ˜„
    • input๊ฐ’์„ ํŒŒ์‹ฑํ•˜๋Š” ์—ญํ• ์˜ parse์™€, ์ˆซ์ž์™€ ์—ฐ์‚ฐ์ž ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•  componentsByOperators, extractOperators๊ตฌํ˜„
    • ๋‘ ๊ฐœ์˜ CalculateItemQueue๋ฅผ ๊ฐ–๋Š” struct Formula ๊ตฌํ˜„

Step3 - ๊ณ„์‚ฐ๊ธฐ UI ์—ฐ๋™

PR ๋Œ€๊ธฐ | Step3

๊ตฌํ˜„ ๋‚ด์šฉ

  • ์‚ฌ์šฉ์ž์˜ ํ„ฐ์น˜ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•˜์—ฌ ๊ทธ ์ด๋ฒคํŠธ๋กœ ๋ฐœ์ƒํ•˜๋Š” ์ˆซ์ž์™€ ์—ฐ์‚ฐ์ž์˜ ์—ฐ์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๊ธฐ ์œ„ํ•ด ๊ฐ ๋ฒ„ํŠผ์„ ์—ฐ๊ฒฐํ•˜๊ณ , ํ„ฐ์น˜ ์ด๋ฒคํŠธ ์ˆ˜์‹ ์‹œ ์‹คํ–‰ํ•  ๊ธฐ๋Šฅ์„ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.
    ์ž…๋ ฅ๋œ ๋‚ด์šฉ์€ ๊ฒฐ๊ณผ๊ฐ’ ์œ„์ชฝ ๊ณต๊ฐ„์— ์Šคํฌ๋กค์ด ๊ฐ€๋Šฅํ•˜๋„๋ก stack์ฒ˜๋ฆฌํ•˜์˜€๊ณ , ๊ทธ ๋‚ด์—ญ์ด ์ƒ๋‹จ ๊ณต๊ฐ„์„ ๋„˜์–ด ์ด์–ด์ง€๋Š” ๊ฒฝ์šฐ์—๋Š” ์Šคํฌ๋กค์ด ํ•˜๋‹จ์œผ๋กœ ์ž๋™์œผ๋กœ ์ด๋™ํ•˜์—ฌ ์ตœ๊ทผ ๋‚ด์—ญ์„ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๐Ÿ““ ํ•™์Šต๋‚ด์šฉ ์š”์ 

1. generic function

์ œ๋„ค๋ฆญ ํ˜•์‹์˜ ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜ ์ด๋ฆ„ ๋’ค์— ๊บฝ์‡  ๊ด„ํ˜ธ์•ˆ์˜ ์ž๋ฆฌ ํ‘œ์‹œ์ž ํ˜•์‹(the placeholder type name) <T>๊ฐ€ ๋“ค์–ด์˜ต๋‹ˆ๋‹ค.

func makeQueue<T>(from elements: Array<T>) -> CalculateItemQueue<T> {

ํ•จ์ˆ˜์˜ ์ œ๋„ค๋ฆญ ๋ฒ„์ „์—์„œ๋Š” ์‹ค์ œ ํ˜•์‹ ์ด๋ฆ„(์˜ˆ: IntString ๋˜๋Š” Double) ๋Œ€์‹  ์ž๋ฆฌ ํ‘œ์‹œ์ž ํ˜•์‹ ์ด๋ฆ„(์ด ๊ฒฝ์šฐ T๋ผ๊ณ  ํ•จ)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ž๋ฆฌ ํ‘œ์‹œ์ž ์œ ํ˜• ์ด๋ฆ„์€ T๊ฐ€ ๋ฌด์—‡์ด์–ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ์•„๋ฌด ๋ง๋„ ํ•˜์ง€ ์•Š์ง€๋งŒ T๊ฐ€ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ด๋“  a์™€ b ๋ชจ๋‘ ๋™์ผํ•œ ์œ ํ˜• T์—ฌ์•ผ ํ•œ๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค

์ฐธ๊ณ  : ๊ณต์‹ ๋ฌธ์„œ

2. enum method

Type Methods ์‹ค์ œ Object๋ฅผ ์ƒ์„ฑํ•  ํ•„์š” ์—†์ด ๋‚ด๋ถ€์˜ (ํ”„๋กœํผํ‹ฐ), ๋ฉ”์†Œ๋“œ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ

enum ExpressionParser {
    static func parse(from input: String) -> Formula {
        // ...
        let operatorQueue: CalculateItemQueue<Operator> = makeQueue(from: operators)
    }
    static func makeQueue<T>(from elements: Array<T>) -> CalculateItemQueue<T> {
        // ...
    }
}
ExpressionParser.parse(from: "+13-7+12*5+9")

ํ˜•์‹ ๋ฉ”์„œ๋“œ์˜ ๋ณธ๋ฌธ ๋‚ด์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ •๊ทœํ™”๋˜์ง€ ์•Š์€ ๋ฉ”์„œ๋“œ ๋ฐ ์†์„ฑ ์ด๋ฆ„์€ ๋‹ค๋ฅธ ํ˜•์‹ ์ˆ˜์ค€ ๋ฉ”์„œ๋“œ ๋ฐ ์†์„ฑ์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. ํ˜•์‹ ๋ฉ”์„œ๋“œ๋Š” ํ˜•์‹ ์ด๋ฆ„์„ ์ ‘๋‘์‚ฌ๋กœ ์ถ”๊ฐ€ํ•  ํ•„์š” ์—†์ด ๋‹ค๋ฅธ ํ˜•์‹ ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์œผ๋กœ ๋‹ค๋ฅธ ํ˜•์‹ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๊ตฌ์กฐ ๋ฐ ์—ด๊ฑฐํ˜•์˜ ํ˜•์‹ ๋ฉ”์„œ๋“œ๋Š” ํ˜•์‹ ์ด๋ฆ„ ์ ‘๋‘์‚ฌ ์—†์ด ํ˜•์‹ ์†์„ฑ์˜ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ ํ˜•์‹ ์†์„ฑ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ  : ๊ณต์‹ ๋ฌธ์„œ

3. compactMap

์‹œํ€€์Šค์˜ ๊ฐ ์š”์†Œ๋กœ ์ง€์ •๋œ ๋ณ€ํ™˜์—์„œ nil์ด ์•„๋‹Œ ๊ฒฐ๊ณผ์˜ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋Š” compactMap์„ ์ด์šฉํ•ด์„œ ๊ฐ„๋žตํ•ด์ง„ ์ฝ”๋“œ๋กœ Double ํƒ€์ž…์˜ ๊ฐ’๋“ค์„ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

let splittedStringArray = "+13-7+12*5+9".components(separatedBy: "+-*/")
let doubleArray= splittedStringArray.compactMap { Double($0) }

์ฐธ๊ณ  : ๊ณต์‹ ๋ฌธ์„œ

4. CharacterSet

๊ฒ€์ƒ‰ ์ž‘์—…์— ์‚ฌ์šฉํ•  ์œ ๋‹ˆ์ฝ”๋“œ ๋ฌธ์ž ๊ฐ’ ์„ธํŠธ. ๋ณธ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” String ๋‚ด์—์„œ Operator Character๋ฅผ CharacterSet์œผ๋กœ ๋งŒ๋“ค์–ด ๊ฒ€์ƒ‰์ž‘์—…์„ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

static func componentsByOperators(from input: String) -> [String] {
    let operators: String = String(Operator.allCases.map { $0.rawValue })
    let operatorSet: CharacterSet = CharacterSet(charactersIn: operators)
    return input.components(separatedBy: operatorSet)
}

์ฐธ๊ณ  : ๊ณต์‹ ๋ฌธ์„œ

5. UIScrollView / UIStackView

์Šคํฌ๋กค ๋ทฐ ๊ตฌ์กฐ๋ฅผ ๋ณด๋‹ˆ ์—ฐ์‚ฐ๋‚ด์—ญ์ด ๋‹ด๊ธด ์Šคํƒ๋“ค์„ ๋‹ด์€ ์Šคํƒ์ด ์žˆ๋Š” ๊ตฌ์กฐ์—ฌ์„œ (ScrollView > StackView > StackView/StackView) ๊ทธ ๊ตฌ์กฐ์— ๋งž๊ฒŒ ์—ฐ์‚ฐ์ž์™€ ์ˆซ์ž๋ฅผ ๋‹ด์„ Label์„ ์ƒ์„ฑํ•œ ํ›„, StackView์— ๋‹ด์•„ ์—ฐ์‚ฐ๋‚ด์—ญ์ด ๋‹ด๊ธด ์Šคํƒ๋“ค์„ ๋‹ด์€ ์Šคํƒ์— ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

private func addFormulaStackView(`operator`: String, operand: String) {
    let formulaStackView = UIStackView()
    let enteredOperatorLabel = UILabel()
    let enteredOperandLabel = UILabel()
    //...
    formulaStackView.addArrangedSubview(enteredOperatorLabel)
    formulaStackView.addArrangedSubview(enteredOperandLabel)

    formulaStackViews.addArrangedSubview(formulaStackView)
}

์ฐธ๊ณ  1 : ๊ณต์‹ ๋ฌธ์„œ ์ฐธ๊ณ  2 : ๊ณต์‹ ๋ฌธ์„œ

6. NumberFormatter

์†Œ์ˆ˜์  ์•„๋ž˜ 20์ž๋ฆฌ ํ‘œ์‹œ, ์ •์ˆ˜๋ถ€ ์ฒœ๋‹จ์œ„ ํ‘œ์‹œ๋ฅผ ์œ„ํ•ด NumberFormatter๋ฅผ ์ด์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค. numberStyle = .decimal์„ ํ†ตํ•ด ์ฒœ๋‹จ์œ„ ํ‘œ์‹œ๋ฅผ ํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , maximumFractionDigits = 20์„ ํ†ตํ•ด ์ตœ๋Œ€ ์†Œ์ˆ˜์  ์ž๋ฆฌ๋ฅผ 20์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

private func formattingNumber(_ number: String) -> String {
    let formatter = NumberFormatter()
    formatter.maximumFractionDigits = 20
    formatter.numberStyle = .decimal
    return formatter.string(for: Double(number)) ?? number
}

์ฐธ๊ณ  : ๊ณต์‹ ๋ฌธ์„œ


๐Ÿงจ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

  1. [Step 1] ์œ ๋‹›ํ…Œ์ŠคํŠธ ์‹œ XCTAssertEqual์„ ์‚ฌ์šฉํ•  ๋•Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ queue์— ๋“ค์–ด๊ฐ€๋Š” Item์— Equatable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜์—ฌ ํ•ด๊ฒฐํ•˜์˜€์Šต๋‹ˆ๋‹ค
  2. [Step 1] Unit Test๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ dequeue๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด isEmpty๊ฐ€ false์ธ ์ƒํ™ฉ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์ง€๋งŒ true์ผ ๋•Œ๋Š” warning์ด ๋ฐœ์ƒํ•˜์—ฌ @discardableResult๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  3. [Step 2] UML์—์„œ ์š”๊ตฌํ•œ split์—์„œ๋Š” Character๋ฅผ target์œผ๋กœ ํ•˜๊ธฐ์—๋Š” ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š์•„ components(separatedBy: CharacterSet)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ๋ถ„์ž์— ๋งž์ถฐ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  4. [Step 3] AC์˜ ๋ฒ„ํŠผ์˜ ๊ฒฝ์šฐ, scrollView๋‚ด์— ์กด์žฌํ•˜๋Š” subViews์˜ ๊ฐ์ฒด๋“ค์„ ์‚ญ์ œํ•˜๊ธฐ ์œ„ํ•ด์„œ removeArrangedSubview์„ ์‚ฌ์šฉํ•˜์˜€์œผ๋‚˜ ์‚ญ์ œ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ removeFromSuperview๋„ ์‚ฌ์šฉ์„ ํ•˜์—ฌ์„œ ๋‚ด๋ถ€์— ์กด์žฌํ•˜๋Š” subViews๋ฅผ ์‚ญ์ œํ•˜์˜€์Šต๋‹ˆ๋‹ค.