์๋ ํ์ธ์. ์ค๋์ Swift์ ๊ณ ๊ธ ์ฐ์ฐ์์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ๊ธฐ๋ณธ ์ฐ์ฐ์๋ณด๋ค ๋ ๋ณต์กํ ๊ฐ์ ์กฐ์ํ ์ ์๋ ๋นํธ ์ฐ์ฐ์, ์ฌ์ฉ์ ์ ์ ์ฐ์ฐ์, ๊ทธ๋ฆฌ๊ณ ๊ฒฐ๊ณผ ๋น๋๊น์ง Swift๊ฐ ์ ๊ณตํ๋ ๋ค์ํ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๐ ๋นํธ ์ฐ์ฐ์ (Bitwise Operators)
๋นํธ ์ฐ์ฐ์๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ ๋ด์ ๊ฐ๋ณ ๋นํธ๋ฅผ ์ง์ ์กฐ์ํ ์ ์๊ฒ ํด์ฃผ๋ ๋๊ตฌ์ ๋๋ค. ์ ์์ค ํ๋ก๊ทธ๋๋ฐ, ๊ทธ๋ํฝ ์์ , ๋๋ฐ์ด์ค ๋๋ผ์ด๋ฒ ๊ฐ๋ฐ ๋ฑ์ ํนํ ์ ์ฉํฉ๋๋ค.
๋นํธ NOT ์ฐ์ฐ์ (~)
๋นํธ NOT ์ฐ์ฐ์๋ ๋ชจ๋ ๋นํธ๋ฅผ ๋ฐ์ ์ํต๋๋ค. 0์ 1๋ก, 1์ 0์ผ๋ก ๋ฐ๊ฟ๋๋ค.
let initialBits: UInt8 = 0b00001111 // ์ด์ง์๋ก 00001111 (์ญ์ง์ 15)
let invertedBits = ~initialBits // ์ด์ง์๋ก 11110000 (์ญ์ง์ 240)
๋นํธ AND ์ฐ์ฐ์ (&)
๋นํธ AND ์ฐ์ฐ์๋ ๋ ์ซ์๋ฅผ ๋น๊ตํด ๋ ๋นํธ๊ฐ ๋ชจ๋ 1์ผ ๋๋ง ๊ฒฐ๊ณผ ๋นํธ๋ฅผ 1๋ก ์ค์ ํฉ๋๋ค.
let firstSixBits: UInt8 = 0b11111100
let lastSixBits: UInt8 = 0b00111111
let middleFourBits = firstSixBits & lastSixBits // 0b00111100 (์ญ์ง์ 60)
๋นํธ OR ์ฐ์ฐ์ (|)
๋นํธ OR ์ฐ์ฐ์๋ ๋ ์ซ์๋ฅผ ๋น๊ตํด ์ด๋ ํ์ชฝ์ ๋นํธ๋ผ๋ 1์ด๋ฉด ๊ฒฐ๊ณผ ๋นํธ๋ฅผ 1๋ก ์ค์ ํฉ๋๋ค.
let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedBits = someBits | moreBits // 0b11111110 (์ญ์ง์ 254)
๋นํธ XOR ์ฐ์ฐ์ (^)
๋นํธ XOR ์ฐ์ฐ์(๋ฐฐํ์ OR)๋ ๋ ์ซ์๋ฅผ ๋น๊ตํด ๋ ๋นํธ๊ฐ ๋ค๋ฅผ ๋๋ง ๊ฒฐ๊ณผ ๋นํธ๋ฅผ 1๋ก ์ค์ ํฉ๋๋ค.
let firstBits: UInt8 = 0b00010100
let otherBits: UInt8 = 0b00000101
let outputBits = firstBits ^ otherBits // 0b00010001
๋นํธ ์ด๋ ์ฐ์ฐ์ (<< ๋ฐ >>)
๋นํธ ์ด๋ ์ฐ์ฐ์๋ ๋ชจ๋ ๋นํธ๋ฅผ ์ง์ ๋ ์๋งํผ ์ผ์ชฝ์ด๋ ์ค๋ฅธ์ชฝ์ผ๋ก ์ด๋์ํต๋๋ค.
๋ถํธ ์๋ ์ ์์ ์ด๋
let shiftBits: UInt8 = 4 // 0b00000100
shiftBits << 1 // 0b00001000 (8)
shiftBits << 2 // 0b00010000 (16)
shiftBits << 5 // 0b10000000 (128)
shiftBits << 6 // 0b00000000 (0, ์ค๋ฒํ๋ก์ฐ๋จ)
shiftBits >> 2 // 0b00000001 (1)
๋นํธ ์ด๋์ ์์ ๊ฐ ์ฒ๋ฆฌ ๊ฐ์ ์์ ์ ๋งค์ฐ ์ ์ฉํฉ๋๋ค:
let pink: UInt32 = 0xCC6699
let redComponent = (pink & 0xFF0000) >> 16 // 0xCC (204)
let greenComponent = (pink & 0x00FF00) >> 8 // 0x66 (102)
let blueComponent = pink & 0x0000FF // 0x99 (153)
๋ถํธ ์๋ ์ ์์ ์ด๋
๋ถํธ ์๋ ์ ์๋ 2์ ๋ณด์ ํํ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ด๋ ๋์์ด ์กฐ๊ธ ๋ค๋ฆ ๋๋ค. ์ค๋ฅธ์ชฝ ์ด๋ ์ ๋น ๊ณต๊ฐ์ ๋ถํธ ๋นํธ๊ฐ ์ฑ์์ง๋๋ค(์ฐ์ ์ด๋).
๐ ์ค๋ฒํ๋ก์ฐ ์ฐ์ฐ์ (Overflow Operators)
Swift์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ด ํ์ ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ํ์ง๋ง ์ค๋ฒํ๋ก์ฐ๋ฅผ ํ์ฉํ๋ ํน์ ์ฐ์ฐ์๋ฅผ ์ ๊ณตํฉ๋๋ค:
- ์ค๋ฒํ๋ก์ฐ ๋ง์ (&+)
- ์ค๋ฒํ๋ก์ฐ ๋บ์ (&-)
- ์ค๋ฒํ๋ก์ฐ ๊ณฑ์ (&*)
var unsignedOverflow = UInt8.max // 255
unsignedOverflow = unsignedOverflow &+ 1 // 0 (255๋ฅผ ๋์ด์ 0์ผ๋ก ์ํ)
var unsignedOverflow2 = UInt8.min // 0
unsignedOverflow2 = unsignedOverflow2 &- 1 // 255 (0์์ ์๋๋ก ๋ด๋ ค๊ฐ 255๋ก ์ํ)
๋ถํธ ์๋ ์ ์์์๋ ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค:
var signedOverflow = Int8.min // -128
signedOverflow = signedOverflow &- 1 // 127 (์ค๋ฒํ๋ก์ฐ๋ก ์ต๋๊ฐ์ผ๋ก ์ํ)
๐ ์ฐ์ ์์์ ์ฐ๊ด์ฑ (Precedence and Associativity)
์ฐ์ฐ์ ์ฐ์ ์์๋ ์ด๋ค ์ฐ์ฐ์๊ฐ ๋จผ์ ๊ณ์ฐ๋๋์ง๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. ์ฐ๊ด์ฑ์ ๊ฐ์ ์ฐ์ ์์์ ์ฐ์ฐ์๋ค์ด ์ด๋ค ์์๋ก ๊ณ์ฐ๋๋์ง(์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ, ๋๋ ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ)๋ฅผ ๊ฒฐ์ ํฉ๋๋ค.
2 + 3 % 4 * 5 // 17
// ์ฐ์ ์์์ ๋ฐ๋ผ ๋ค์๊ณผ ๊ฐ์ด ๊ณ์ฐ๋ฉ๋๋ค:
// 1. 3 % 4 = 3 (% ์ฐ์ฐ์ด + ๋ณด๋ค ์ฐ์ ์์๊ฐ ๋์)
// 2. 3 * 5 = 15 (% ์ *๋ ๊ฐ์ ์ฐ์ ์์์ด๋ฉฐ ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ผ๋ก ์ฐ๊ด)
// 3. 2 + 15 = 17
๐ ์ฐ์ฐ์ ๋ฉ์๋ (Operator Methods)
Swift์์๋ ํด๋์ค์ ๊ตฌ์กฐ์ฒด๊ฐ ๊ธฐ์กด ์ฐ์ฐ์์ ๋์์ ์์ ๋ง์ ๋ฐฉ์์ผ๋ก ๊ตฌํํ ์ ์์ต๋๋ค. ์ด๋ฅผ "์ฐ์ฐ์ ์ค๋ฒ๋ก๋ฉ"์ด๋ผ๊ณ ํฉ๋๋ค.
์ดํญ ์ฐ์ฐ์ ๊ตฌํ
struct Vector2D {
var x = 0.0, y = 0.0
}
extension Vector2D {
static func + (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
}
let vector = Vector2D(x: 3.0, y: 1.0)
let anotherVector = Vector2D(x: 2.0, y: 4.0)
let combinedVector = vector + anotherVector
// combinedVector๋ (5.0, 5.0) ๊ฐ์ ๊ฐ์ง๋๋ค
์ ๋์ฌ ๋ฐ ์ ๋ฏธ์ฌ ์ฐ์ฐ์ ๊ตฌํ
๋จํญ ์ฐ์ฐ์(ํ๋์ ํผ์ฐ์ฐ์์๋ง ์ ์ฉ๋๋ ์ฐ์ฐ์)๋ฅผ ๊ตฌํํ ๋๋ prefix ๋๋ postfix ์์์ด๋ฅผ ์ฌ์ฉํฉ๋๋ค:
extension Vector2D {
static prefix func - (vector: Vector2D) -> Vector2D {
return Vector2D(x: -vector.x, y: -vector.y)
}
}
let positive = Vector2D(x: 3.0, y: 4.0)
let negative = -positive // (-3.0, -4.0)
๋ณตํฉ ํ ๋น ์ฐ์ฐ์ ๊ตฌํ
๋ณตํฉ ํ ๋น ์ฐ์ฐ์(์: +=)๋ ์ฐ์ฐ๊ณผ ํ ๋น์ ๊ฒฐํฉํฉ๋๋ค. ์ฒซ ๋ฒ์งธ ํ๋ผ๋ฏธํฐ๋ฅผ inout์ผ๋ก ํ์ํฉ๋๋ค:
extension Vector2D {
static func += (left: inout Vector2D, right: Vector2D) {
left = left + right
}
}
var original = Vector2D(x: 1.0, y: 2.0)
original += Vector2D(x: 3.0, y: 4.0)
// original์ ์ด์ (4.0, 6.0) ๊ฐ์ ๊ฐ์ง๋๋ค
๋ฑ๊ฐ ์ฐ์ฐ์ ๊ตฌํ
๋ฑ๊ฐ ์ฐ์ฐ์(==, !=)๋ฅผ ๊ตฌํํ๋ ค๋ฉด Equatable ํ๋กํ ์ฝ์ ์ค์ํด์ผ ํฉ๋๋ค:
extension Vector2D: Equatable {
static func == (left: Vector2D, right: Vector2D) -> Bool {
return (left.x == right.x) && (left.y == right.y)
}
}
// ์ด์ ๋ฒกํฐ ๋น๊ต๊ฐ ๊ฐ๋ฅํฉ๋๋ค
if twoThree == anotherTwoThree {
print("๋ ๋ฒกํฐ๋ ๊ฐ์ต๋๋ค.")
}
๐ ์ฌ์ฉ์ ์ ์ ์ฐ์ฐ์ (Custom Operators)
Swift์์๋ ์์ ํ ์๋ก์ด ์ฐ์ฐ์๋ฅผ ์ ์ํ ์๋ ์์ต๋๋ค:
// ์๋ก์ด ์ ๋์ฌ ์ฐ์ฐ์ ์ ์
prefix operator +++
extension Vector2D {
static prefix func +++ (vector: inout Vector2D) -> Vector2D {
vector += vector
return vector
}
}
var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
let afterDoubling = +++toBeDoubled
// toBeDoubled์ afterDoubling ๋ชจ๋ (2.0, 8.0) ๊ฐ์ ๊ฐ์ง๋๋ค
์ฌ์ฉ์ ์ ์ ์ค์ ์ฐ์ฐ์์ ์ฐ์ ์์
์ค์ ์ฐ์ฐ์(๋ ํผ์ฐ์ฐ์ ์ฌ์ด์ ์์นํ๋ ์ฐ์ฐ์)๋ฅผ ์ ์ํ ๋๋ ์ฐ์ ์์ ๊ทธ๋ฃน์ ์ง์ ํ ์ ์์ต๋๋ค:
infix operator +-: AdditionPrecedence
extension Vector2D {
static func +- (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y - right.y)
}
}
let firstVector = Vector2D(x: 1.0, y: 2.0)
let secondVector = Vector2D(x: 3.0, y: 4.0)
let plusMinusVector = firstVector +- secondVector
// plusMinusVector๋ (4.0, -2.0) ๊ฐ์ ๊ฐ์ง๋๋ค
๐ ๊ฒฐ๊ณผ ๋น๋ (Result Builders)
๊ฒฐ๊ณผ ๋น๋๋ ์ค์ฒฉ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ(๋ฆฌ์คํธ, ํธ๋ฆฌ ๋ฑ)๋ฅผ ์ ์ธ์ ์ธ ๋ฐฉ์์ผ๋ก ์์ฑํ ์ ์๊ฒ ํด์ฃผ๋ Swift์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๋๋ค.
๊ฒฐ๊ณผ ๋น๋ ์์
๋ค์์ ๋ณ๊ณผ ํ ์คํธ๋ฅผ ์ฌ์ฉํ์ฌ ๊ทธ๋ํฝ์ ๊ตฌ์ฑํ๋ ๊ฒฐ๊ณผ ๋น๋ ์์ ์ ๋๋ค:
protocol Drawable {
func draw() -> String
}
struct Line: Drawable {
var elements: [Drawable]
func draw() -> String {
return elements.map { $0.draw() }.joined(separator: "")
}
}
struct Text: Drawable {
var content: String
init(_ content: String) { self.content = content }
func draw() -> String { return content }
}
struct Space: Drawable {
func draw() -> String { return " " }
}
struct Stars: Drawable {
var length: Int
func draw() -> String { return String(repeating: "*", count: length) }
}
struct AllCaps: Drawable {
var content: Drawable
func draw() -> String { return content.draw().uppercased() }
}
์ผ๋ฐ์ ์ธ ๋ฐฉ์์ผ๋ก ์ด๋ฌํ ๊ตฌ์กฐ์ฒด๋ฅผ ์กฐํฉํ๋ฉด ์ฝ๋๊ฐ ๋ณต์กํด์ง๋๋ค:
let name: String? = "Ravi Patel"
let manualDrawing = Line(elements: [
Stars(length: 3),
Text("Hello"),
Space(),
AllCaps(content: Text((name ?? "World") + "!")),
Stars(length: 2),
])
print(manualDrawing.draw())
// ์ถ๋ ฅ: "***Hello RAVI PATEL!**"
๊ฒฐ๊ณผ ๋น๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ์ฝ๋๋ฅผ ๋ ์ ์ธ์ ์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค:
@resultBuilder
struct DrawingBuilder {
static func buildBlock(_ components: Drawable...) -> Drawable {
return Line(elements: components)
}
static func buildEither(first: Drawable) -> Drawable {
return first
}
static func buildEither(second: Drawable) -> Drawable {
return second
}
}
// ๊ฒฐ๊ณผ ๋น๋๋ฅผ ์ฌ์ฉํ๋ ํจ์
func draw(@DrawingBuilder content: () -> Drawable) -> Drawable {
return content()
}
func caps(@DrawingBuilder content: () -> Drawable) -> Drawable {
return AllCaps(content: content())
}
// ๊ฒฐ๊ณผ ๋น๋ ๊ตฌ๋ฌธ ์ฌ์ฉ ์
func makeGreeting(for name: String? = nil) -> Drawable {
let greeting = draw {
Stars(length: 3)
Text("Hello")
Space()
caps {
if let name = name {
Text(name + "!")
} else {
Text("World!")
}
}
Stars(length: 2)
}
return greeting
}
let personalGreeting = makeGreeting(for: "Ravi Patel")
print(personalGreeting.draw())
// ์ถ๋ ฅ: "***Hello RAVI PATEL!**"
๊ฒฐ๊ณผ ๋น๋๋ ๋ฐ๋ณต๋ฌธ๋ ์ง์ํ ์ ์์ต๋๋ค:
extension DrawingBuilder {
static func buildArray(_ components: [Drawable]) -> Drawable {
return Line(elements: components)
}
}
let manyStars = draw {
Text("Stars:")
for length in 1...3 {
Space()
Stars(length: length)
}
}
// ์ถ๋ ฅ: "Stars: * ** ***"
๐ ์ ๋ฆฌ
Swift์ ๊ณ ๊ธ ์ฐ์ฐ์์ ๊ฒฐ๊ณผ ๋น๋๋ ์ฝ๋์ ํํ๋ ฅ์ ํฌ๊ฒ ํฅ์์ํค๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๋๋ค:
- ๋นํธ ์ฐ์ฐ์๋ ๊ฐ๋ณ ๋นํธ๋ฅผ ์กฐ์ํ์ฌ ์ ์์ค ํ๋ก๊ทธ๋๋ฐ์ ์ ์ฉํฉ๋๋ค.
- ์ค๋ฒํ๋ก์ฐ ์ฐ์ฐ์๋ ๊ฐ์ด ํ์ ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ ๋์ ๋์์ ์ ์ดํฉ๋๋ค.
- ์ฐ์ฐ์ ์ค๋ฒ๋ก๋ฉ์ ํตํด ๊ธฐ์กด ์ฐ์ฐ์๋ฅผ ์์ ์ ํ์ ์ ๋ง๊ฒ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
- ์ฌ์ฉ์ ์ ์ ์ฐ์ฐ์๋ก ์์ ํ ์๋ก์ด ์ฐ์ฐ์๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
- ๊ฒฐ๊ณผ ๋น๋๋ ์ค์ฒฉ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ ์ธ์ ์ผ๋ก ๊ตฌ์ฑํ ์ ์๊ฒ ํด์ค๋๋ค.
'๐ฅ Bread Basics > Swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Swift ๊ณต์ ๋ฌธ์ ์ ๋ฆฌ - ์ ๊ทผ ์ ์ด (Access Control) (0) | 2025.04.13 |
---|---|
Swift ๊ณต์ ๋ฌธ์ ์ ๋ฆฌ - ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ (Memory Safety) (0) | 2025.04.13 |
Swift ๊ณต์ ๋ฌธ์ ์ ๋ฆฌ - ์๋ ์ฐธ์กฐ ์นด์ดํ (Automatic Reference Counting) (0) | 2025.04.13 |
Swift ๊ณต์ ๋ฌธ์ ์ ๋ฆฌ - ๋ถํฌ๋ช ํ ํ์ (Opaque Types) (0) | 2025.04.13 |
Swift ๊ณต์ ๋ฌธ์ ์ ๋ฆฌ - ์ ๋๋ฆญ (Generics) (0) | 2025.04.13 |
Swift ๊ณต์ ๋ฌธ์ ์ ๋ฆฌ - ํ๋กํ ์ฝ (Protocols) (0) | 2025.04.13 |
Swift ๊ณต์ ๋ฌธ์ ์ ๋ฆฌ - ํ์ฅ (Extensions) (0) | 2025.04.13 |
Swift ๊ณต์ ๋ฌธ์ ์ ๋ฆฌ - ์ค์ฒฉ๋ ํ์ (Nested Types) (1) | 2025.04.12 |