추상화와 일반화. 개발 공부를 하다 보면 꽤나 많이 듣게 되는 단어입니다.
저 또한 여러 논의를 하며 자연스럽게 두 단어를 이야기하곤 했는데 어느 날 두 개념의 차이점에 대한 질문을 받은 적이 있습니다. 한참을 고민하다 내린 결론은 그동안 혼용해서 사용하고 있었구나라는 깨달음과 이를 깊이 고민해보지 못한 반성이었습니다.
비슷하지만 분명히 다른 추상화와 일반화에 대해 정리해보려 합니다.
추상화 Abstraction
컴퓨터 과학에서 추상화는 복잡한 자료, 모듈, 시스템 등으로부터 핵심적인 개념 또는 기능을 간추려 내는 것을 말한다.
이전에 객체지향의 사실과 오해를 읽었을 때의 구절이 다시 떠올랐습니다.
"복잡성의 총체인 현실이라는 괴물을 그대로 수용하기에 인간이 지닌 인지 능력과 저장 공간은 너무나도 보잘것없다."
우리는 컴퓨터, 자동차 부품 하나하나를 알지 못해도 메모리, 브레이크 등의 개념으로 '추상화'해 이해합니다. 본능적으로 이해하기 쉽게 단순화하는 전략 없이는 이해하기 어렵기 때문이죠.
결국 추상화의 목적은 불필요한 부분을 감춤으로써 현실에 존재하는 복잡성을 극복하는 것이고, 소프트웨어 개발에서의 추상화는 복잡성을 줄이고 유연성을 증가시키는 과정입니다.
Swift에서의 대표적인 추상화 예시를 살펴보겠습니다.
/// 강아지를 '추상화' 하기.
/// 어떤 구체적인 강아지인지는 모르지만, 이런 개념(속성)과 기능(함수)가 있음을 정의.
protocol Dog {
var name: String { get set }
var age: Int { get set }
func bowWow()
}
struct Mintol: Dog {
var name: String = "민톨"
var age: Int = 4
func bowWow() {
print("\(name)이 멍멍 짖습니다!")
}
}
func myDog(dog: Dog) {
print("강아지의 이름은 \(dog.name), 나이는 \(dog.age)살입니다.")
}
myDog(dog: Mintol())
// 강아지의 이름은 민톨, 나이는 4살입니다.
Dog 프로토콜은 강아지를 추상화하고 있습니다. 어떤 구체적인 강아지인지는 모르지만, 이름과 나이라는 개념(속성)과 짖기라는 기능(함수)이 있음을 표현하고 있습니다.
이를 통해 myDog 함수는 세부적인 구현을 알지 못하지만 Dog 프로토콜을 통해 기능을 수행할 수 있습니다.
일반화 Generalization
일반화는 특정 사례들의 공통되는 속성들을 일반적인 개념이나 주장으로 공식화하는 추상화의 한 형태이다.
만약 A가 B의 일반화 개념이라면, 개념 B의 모든 사례가 개념 A의 사례라고 합니다. 아래 이미지의 4가지 나무에서 공통된 개념을 추출해 최종 나무를 만들어내는 과정을 '일반화'라고 할 수 있습니다.
소프트웨어 개발에서 일반화는 여러 개념에서 공통점을 추출해 상위 개념을 만드는 과정입니다. 일반화의 목적은 코드 중복을 줄이고 재사용성을 높이기 위함으로 볼 수 있습니다.
Swift에서의 대표적인 일반화 예시를 살펴보겠습니다.
/// 핸드폰 기기를 '일반화'하기
/// iOS와 Android는 모두 울리는 기능이 있기 때문에 공통된 기능을 추출해 상위 개념에 탑재.
class Device {
func ringRing() {
print("디바이스가 울립니다~")
}
}
class IOS: Device {
...
}
class Android: Device {
...
}
IOS().ringRing()
Android().ringRing()
iOS와 Android 핸드폰은 모두 전화벨이 울리는 기능이 있습니다. 이는 공통된 개념으로, 상위 개념인 Device로 표현이 가능합니다. 이를 통해 코드 중복(ringRing 함수를 두 번 구현하는 것)과 재사용성을 높일 수 있습니다.
또 다른 일반화 예시는 Generic을 사용하는 것입니다.
func get<T: Decodable>(url: URL) async throws -> T {
let (data, response) = try await request(url: url, method: "GET")
return try decodeResponse(data: data, response: response)
}
위 코드는 GET 메서드를 통해 네트워킹을 요청하는 코드로 제네릭을 이용해 Decodable 프로토콜을 준수하는 타입을 반환하는 함수입니다. 이 또한 공통된 개념을 추출해 코드 중복과 재사용성을 높인 일반화의 대표적인 사례입니다.(Generic 단어 뜻 자체가 일반적인~ 요런 뜻이기도 합니다!)
정리하기
위 정의에서 살펴보았듯 추상화의 하위 개념 중 하나가 일반화라고 해석할 수 있습니다. 핵심적인 내용들로 간추려내는 작업의 의미 자체도 일반화가 가지고 있기 때문입니다.
하지만 여기서 일반화는 공통된 개념을 추출하여 상위 개념을 만드는 특정한 방식의 추상화라는 점을 유념하여 차이를 인지하면 좋을 것 같습니다.
개념을 공부하며 또 하나 느낀 점은, 다른 사람들과 논의하거나 설명할 때 꼭 단어의 뜻을 명확히 인지한 상태로 사용해야 한다는 것입니다. 그동안 두 개념을 혼용해 사용했었기 때문에 얼마나 많은 오해를 불러일으켰을지,,, 걱정과 반성이 됩니다.
새삼 단어 그 자체의 진중함을 실감하게 됩니다.
'CS' 카테고리의 다른 글
책임과 역할, 비슷한 듯 다른 두 개념 (0) | 2025.02.03 |
---|---|
테스트 더블? 두 번 테스트 하는 건가요? (0) | 2025.01.21 |
스레드와 메모리,, 비슷한 거 아니었나요? (0) | 2025.01.15 |