추상 자료형(ADT: Abstract Data Type)

유석현(SeokHyun Yu)·2022년 7월 26일
0
post-thumbnail

1. 추상 자료형이란?

추상 자료형! 간단히 ADT라고도 불리는 이것은 컴퓨터 공학에서 흔히 등장하는 용어이다.

ADT에 대한 이해는 C++이나 JAVA와 같은 객체지향 언어를 공부하면서 더 깊어질 수 있다.


지갑을 통해 간단히 지갑에 대한 '추상 자료형'을 추출해 보겠다.

- 카드의 삽입

- 카드의 추출

- 동전의 삽입

- 동전의 추출

- 지폐의 삽입

- 지폐의 추출

위에는 지갑의 기능들이 나열되어있다.

하지만 그 기능이 어떠한 과정을 거쳐서 완성되는지는 언급하지 않고 있다.

예를 들어서 동전의 삽입은 다음의 과정을 거쳐야 한다.

"지갑을 열고 동전 주머니를 찾아서 동전 주머니의 지퍼를 내린다."

"그리고 동전 주머니에 동전을 넣는다."

"이어서 동전 주머니의 지퍼를 올린 다음 마지막으로 지갑을 닫는다."

이를 보면 여러 과정을 거쳐서 동전의 삽입이 이뤄짐을 알 수 있다.

하지만 위에 정리해 놓은 것은 그 자세한 과정들을 나열하지 않고 지갑이 제공하는 기능 그 자체만을 나열하고 있다.

이렇듯 '구체적인 기능의 완성과정을 언급하지 않고, 순수하게 기능이 무엇인지 나열한 것'을 가리켜 '추상 자료형' 또는 간단히 'ADT(Abstract Data Type)'라 한다.

하지만 추상 자료형이라는 그 이름 때문에 다음과 같은 생각을 할 수 있다.

"근데 그게 왜 추상 자료형이에요?"

"그건 int, double과 같은 자료형과 관계가 없지 않나요?"

"'기능의 명세' 같은 표현이 더 어울리지 않을까요?"

그럼 이번에는 자료형에 대해서 이야기해 보자.

물론 이는 C언어를 공부할 때 이해한 개념이지만 이번에는 조금 더 정확히 할 필요가 있다.

먼저 구조체를 이용해서 지폐와 동전의 정보 저장이 가능한 지갑을 정의해 보겠다.

typedef struct wallet
{
    int coint;
    int bill;
} Wallet;

이렇게 구조체를 정의하였다면, 다음과 같이 이야기할 수 있다.

"구조체를 기반으로 지갑을 의미하는 Wallet이라는 자료형을 정의했어요!"

알다시피 이는 Wallet이라는 자료형의 정의이다.

그런데 컴퓨터 공학적 측면에서 위의 구조체 정의만으로 Wallet이라는 자료형의 정의가 완성되는 것은 아니다.

Wallet을 기반으로 하는 연산의 종류를 결정하는 것도 자료형 정의의 일부로 보아야 하고, 이러한 연산의 종류가 결정되었을 때 비로소 자료형의 정의는 완성이 된다.

"구조체와 관련된 연산의 종류를 결정하는 것도 자료형 정의의 일부라는 거군요."

"근데 구조체 변수로 할 수 있는 연산은 대입연산 외에 몇 개 없으니, 별도로 연산의 종류를 정의할 것도 없을 것 같은데요?"

위에서 언급한 '연산'은 C언어에서 제공하는 그러한 기본 연산을 의미하는 것이 아니고, Wallet을 기반으로 제공할 수 있는 기능 관련 연산을 의미하는 것이다.

예를 들면 다음과 같은 것들이다.

int TakeOutMoney(Wallet * w, int coinNum, int billNum); // 지갑에서 돈을 꺼낸다
int PutMoney(Wallet * w, int cointNum, int billNum); // 지갑에 돈을 넣는다

이렇듯 C언어에서는 구조체에서 필요로 하는 연산을 함수를 이용해 정의한다.

그리고 위의 두 연산이 Wallet과 관련이 있는 연산의 전부라고 하면, 이 둘이 더해져서 Wallet에 대한 자료형의 정의가 완성이 된다.

결론은 '자료형'의 정의에 '기능' 혹은 '연산'과 관련된 내용을 명시할 수 있다는 것이다.

따라서 추상 자료형이라 하여 그것에 기능 혹은 연산과 관련된 내용을 명시할 수 없다는 생각은 버리기 바란다.


다시 본론으로 돌아와서 Wallet의 추상 자료형을 정의할 차례인데, 정리 차원에서 앞서 말한 다음 문장을 다시 한번 보이고자 한다.

"구체적인 기능의 완성과정을 언급하지 않고, 순수하게 기능이 무엇인지를 나열한 것을 가리켜 '추상 자료형' 또는 간단히 ADT라 한다."

그럼 이어서 자료구조 Wallet의 ADT를 정의해보자.

추상 자료형을 명시하는데 있어 특정 언어에 의존적이지 않게 별도의 표기법을 활용하는 것이 좋겠지만 꼭 그래야 하는 것은 아니다.

명시해야할 정보인 '기능'을 충분히 묘사하고 있다면 위와 같은 방법도 괜찮다.

"그런데 최소한 구조체 Wallet의 정의는 ADT에 포함시켜야 하는 것 아닌가요?"

물론 필요하다면 포함시켜도 된다.

중요한 정보라면 무엇이든 추가할 수 있으며, 그 방법에는 제한이 없다.

하지만 불필요한 것을 포함시키는 것은 바람직하지 못하다.

그럼 구조체 Wallet의 정의는 필요한 정보일까?

이를 판단하기 위해서 다음 main 함수를 관찰하자.

#include "Wallet.h"

int main(void)
{
    Wallet myWallet;
    ...
    PutMoney(&myWallet, 5, 10);
    ...
    ret = TakeOutMoney(&myWallet, 2, 5);
    ...
}

위의 예에서 보이듯이 Wallet을 기반으로 돈을 넣고 꺼내는데 있어서, 구조체 Wallet의 멤버가 어떻게 구성이 되어 있는지를 알 필요는 없다.

따라서 위의 경우 Wallet의 정의를 ADT에 포함시키는 것은 바람직하지 못하다.

"동전이나 지폐가 몇 개씩 있는지 확인해야 하는 상황에 처할 수도 있잖아요"

"그렇다면 Wallet의 멤버에 대해서도 알아야 하지 않나요?"

동전의 수를 확인해야 한다면, 그에 관련된 연산을 위의 ADT에 추가하는 것이 옳다.

우리는 구조체의 멤버에 직접 접근하는 것이 익숙하지만, 사용자들(C언어에 대해 잘 모르는 사람들 or Wallet 구조체에 대한 정보가 없는 사람들)은 그렇지 않으므로, 이것이 늘 옳은 것인지는 고민해봐야 한다.

한가지만 더 말한다면, 우리는 C언어의 파일 입출력을 공부하면서 FILE 구조체의 내부를 궁금해하지 않았다.

FILE 구조체의 내부를 몰라도 파일과 관련된 모든 연산을 처리할 수 있기 때문이다.

앞으로 우리가 만들어갈 모든 자료구조는 그 내부 구현을 알지 못해도 활용할 수 있도록 구현할 것이다.

그리고 그렇게 하기 위해서는 ADT의 정의가 필수이다.

profile
Backend Engineer

0개의 댓글