함수는 왜 "호출한다"고 표현할까?
(quuxplusone.github.io)- 프로그래밍에서 함수를 "호출한다" 는 표현의 기원은, 도서관에서 책을 "청구"하거나 "부르는" 개념과 유사함
- 초기 컴퓨팅에서는 서브루틴을 라이브러리에서 소환, 호출하는 방식이 주를 이룬 경향이 있음
- Fortran II가 CALL 명령어를 도입하면서 "to call 함수"라는 표현을 빠르게 대중화함
- 이후 Algol 및 JOVIAL 등의 언어도 이를 받아들여 "call"이라는 명사를 사용하게 됨
- "call"의 의미는 런타임 제어 이전, 중, 이후로 점차 확대되어 정착됨
왜 프로그래머는 함수를 "호출(call)"한다고 말하는가?
- StackExchange에서 "함수를 호출(call)한다"는 표현의 기원에 대해 질문이 있었음
- 여러 비유가 있지만, 실제로는 "call"이 소환(summon)하거나 불러온다는 의미에서 유래함
- 도서관에서 책을 "청구"하는 것처럼, 서브루틴을 "청구"해 사용하는 것에서 시작
- "call number"가 도서관에서 책의 위치를 나타내는 표식임
도서관 용어에서의 "call"의 역사
- OED에 따르면 Melvil Dewey가 1876년에 도서관 과학 용어로 "call number"를 처음 사용함
- "call number"는 책의 위치나 청구 요청에 쓰이는 표기임
- 1888년의 Library Journal에서도 "call blank", "call slip", "call number" 등의 용어가 일상적으로 사용됨
-
Joudrey & Taylor의 해설에 따르면, "call number"는 닫힌 서가에서 자료를 부르는 행위에서 나온 명칭임
- Cutter number 같은 체계는 분류를 위해 도입됨
컴퓨터 과학에서의 "call" 사용 초기
-
John W. Mauchly의 1947년 논문에서는 서브루틴 라이브러리에서 서브루틴을 "called in"하여 사용하는 사례가 등장함
- 기록된 번호로 빠르게 참조해 사용한다는 맥락
-
MANIAC II 어셈블리 루틴(1956) 역시, 각 서브루틴에 "call number"를 부여하고 이를 통해 필요할 때 불러오는 개념이 적용됨
- 실제 어셈블리어에서는 "transfer control"로 지칭했음
- 이 시기에는 런타임에서의 "호출"보다는, 컴파일 또는 링크 시점에 코드 조각을 불러오는 개념이 강조됨
프로그래밍 언어에서 "CALL" 명령의 등장
-
Fortran II(1958) 가
CALL
및RETURN
명령어를 도입- "호출(call for)"이라는 동작으로 서브루틴에 실행 제어를 넘김
-
CALL
명령어가 실제로 "호출"하는 구문적 행위를 가리킴
- 점차 런타임에서 "control을 transfer"하는 것과, 링크/어셈블 시점의 "호출" 행위가 모호하게 섞이기 시작함
1960년대 "call"의 의미 확장 및 정착
-
Sarbacher(1959) 의 사전에서는 "call in"을 메인 루틴에서 서브루틴으로의 제어 이동으로 정의
- "call number"와 "call word"로 식별자, 호출 코드까지 설명함
-
JOVIAL(1960) 에서는 "procedure call", "calls" 등이 공식적으로 명사로 사용됨
- 이후 호출 시점(site), 인수(argument), 파라미터 등 다층 의미와 함께 사용됨
-
Algol(1959~1960) 도 "procedure call", "called procedure", "during the call" 등 호출 시점을 다양하게 표현함
- Peter Naur의 Algol 60 리포트에서도 "call for"와 "during the call"이라는 시간적 의미 구분 등장
- Burroughs Algebraic Compiler(1961) 에서, 동사형 "to call"이 명확히 처음 나타남
- Corbató 등(1963) 이후로 현대적 용법인 "to call a subroutine"이 일반화됨
결론
-
Fortran II의 "CALL X" 명령이 함수/서브루틴 호출에 "call" 표현을 자리잡게 함
- 이전의 도서관적 개념(번호로 부름)에서 착안했으나, 프로그래밍 언어에서 새로운 의미 확장
- 이후 Algol, JOVIAL 등 다양한 언어가 "call", "call site" 등 용어를 받아들임
- 1961년 무렵부터 "to call X"라는 표현이 공식적인 프로그램 문서와 커뮤니티에서 정착되기 시작함
Hacker News 의견
- 'call'이라는 단어의 원래 의미(물리적 도서관에서 자료를 정리하는 데 쓰였던 call number에서 유래함)가 'compiler'라는 용어의 탄생에도 영향을 주었다고 Grace Hopper가 설명함. 각각의 서브루틴에 'call word'가 부여되었고, 도서관에서 자료를 꺼내 조합하는 것처럼 프로그램을 만든다는 개념에서 비롯된 것임
- 나는 이 용어들을 직접 사용함
- 이제야 비로소 퍼즐이 맞춰짐을 느낌. 듀이십진분류체계의 식별 숫자는 'call number'라고 불렸음
- Library Science(문헌정보학)가 현대 컴퓨팅 분야에 우리가 상상하는 것보다 훨씬 더 많은 기여를 했다고 생각함. 예를 들어 데이터베이스 인덱스를 설명할 때 카드 카탈로그 이미지를 자주 꺼냄. 저자명, 듀이 십진, 주제별로 찾을 수 있는 나무 서랍장을 보면 다들 바로 이해함. 도서관 카탈로그 개념 참고
- 나는 로컬 도서관에서 나무 서랍장과 종이사전 같은 것들을 써봤던 세대임. 25년 전 해시맵이나 IDictionary를 처음 접했을 때 이 이미지 덕분에 바로 감이 잡혔음. 하지만 요즘은 이 은유가 그다지 더 도움이 안 됨. 직접 카드 카탈로그나 사전이 어땠는지 설명해야 하는 상황이 종종 있었고, 젊은 사람들은 "아, 그러니까 그게 아날로그 해시맵이군요"라고 말함
- 몇 달 전만 해도 왜 터미널의 표준 폭이 80자인지 궁금했었음. 예전 PC 화면 크기 때문이라고 생각했음. 그런데 알고 보니 펀치카드가 80자였기 때문이고, 펀치카드의 시작도 결국 인덱스 카드였던 셈임. 또 한 번 문헌정보학에 경의를 표하는 계기였음. 이건 마치 자동차 너비가 말 엉덩이 두 개 크기에서 유래한 것과 비슷한 컴퓨팅 역사 같음
- 1~2년 전에 도서관 구석에 있는 먼지 쌓인 나무 서랍을 데이터베이스에 빗대어 설명한 적이 있음. 맥락과 선이해가 정말 중요함
- 나는 항상 책 뒤쪽의 색인이 컴퓨팅 용어에서 'index'라는 단어가 나온 시초라고 생각해왔음. 'index cards'와 연결지은 적은 없었음
- 요즘 젊은 세대는 카드 카탈로그 자체를 본 적이 없을 수도 있음. 나는 하드디스크가 0과 1이 나열된 리스트임을 설명하고, 뭔가를 찾으려면 구조가 필요하다는 점을 유추하도록 함
- 핀란드인임. 핀란드어에서 '함수 호출'에 해당하는 단어는 'kutsua'인데, 영어로 다시 번역하면 'invite'나 'summon' 임. 즉, '엄마가 아이를 마당에서 부르는 것' 같은 '호출'의 의미로 쓰이지, 'Joe가 친구에게 전화를 건다'거나 '이 색을 뭐라고 부르지?' 할 때의 call과는 쓰임이 다름. 그냥 공유하고 싶었음
- 독일어에선 'aufrufen'을 쓰는데, fragment 단위로 번역하면 '불러 올린다' 정도임. 학교에서 학생 이름 부를 때 같이 직접 목적어와 함께 쓰면 누군가를 name이나 번호로 부르는 의미임. 전화 걸다에 해당하는 단어는 'anrufen'임
- 'summon'은 뭔가 코드에 오컬트적 공포를 불러올 때도 있는 것 같고, 때로는 매우 적절함. 'invite'는 악마나 뱀파이어를 초대하는 것일 수도 있다고 느끼기도 함
- 노르웨이에서는 'funksjonskall'을 쓰는데, 직역하면 function call임. 단순히 무언가를 부르는 call 의미임
- 러시아어도 비슷해서, 역번역하면 '전화로 부르다', '소환하다', '초대하다' 등임
- 직접적인 주제는 아니지만, 혹시 헬싱키에 있다면 현지 Hacker News 밋업에 참여하면 좋겠음
- Wilkes, Wheeler, Gill (1951)이라는 책에서 'call in'이라는 문구가 서브루틴 실행에 쓰임. 31페이지에 "서브루틴이 바르게 호출되지 않으면 기계가 멈춘다", "어떤 프로그램에서든 자유롭게 서브루틴을 호출할 수 있다"는 내용이 있음. 1950년 EDSAC 초기 보고서에도 "call in auxiliary sub-routine"이라는 주석이 남아있음을 이 프리젠테이션에서 볼 수 있음
- 가끔씩 'call' 보다는 'invoke'나 'execute'도 쓰이지만, 더 길고 일반적인 용어임. 그런데 'call'이라는 용어가 잘못 쓰인 상황("calling a command", "calling a button")이 비영어권 CS 학생들에게서 많이 들려오는데, 그게 좀 거슬림
- 'invoke'는 라틴어 invocō, invocāre(불러 일으키다)에서 왔으니 잘못된 게 아니라 약식 표현임
- 가장 흔히 듣는(혹은 싫어하는) 잘못된 예는 'return'과 같이 쓰는 것임. "이제 return 키워드를 호출하면 함수가 끝나요" 같은 표현을 들은 적이 있음
- C#은 대리자나 reflection 같은 곳에 'Invoke'를 자주 쓰면서, 디버거에서는 'Call Stack'을 씀
- 내 경험상 프로그래밍을 처음 배우는 원어민들도 비슷한 용법을 씀. 그들은 명령이 아닌 것들도 'command'라고 설명함
- 초보자가 아예 반대로 statement나 함수 선언 전체를 'command'라고 부르는 경우도 종종 봄
- 과학 이론은 아니고 그냥 한 가지 관찰임. 새로운 용어는 뭔가 통하는 지점이 있을 때 전파가 잘됨. 대개 짧고, 의미나 이미지를 쉽게 연상/기억할 수 있어서 빠르게 퍼짐. 때론 설명이 필요하지만 맥락만으로도 사람들이 익혀서 전파함. 예를 들어 'salty' 같은 단어가 그렇고, call도 마찬가짐. 짧으면서 자주 쓰이니 입에 잘 붙고, call up/call in/summon/invoke(마법 주문 같은 느낌) 모두 느낌이 맞아떨어짐. 당시엔 전화기도 새롭고 신기한 기술이었으므로, 다른 사람에게 전화를 거는 이미지를 서브루틴 호출에 비추어 쉽게 연결지었을 것임. 'jump' 같은 용어는 이미 다른 의미로 쓰이고 있었으니 call이 널리 퍼질 수 있었다고 생각함
- 나에게 'salty'는 tears와는 별 상관 없음. 내 언어습관에서는 누군가 'salty'하다는 건 슬프다는 게 아니라 짜증나거나 불쾌한 상태임. 즉, 소금처럼 맵고 강렬하다는 이미지에서 비유가 나옴. 즉, 서로 해석이 달라도 은유는 잘 통한다는 점에서, call이 그런 식으로 퍼질 수 있었음을 보여줌
- "... 복잡한 것들은 라이브러리, 즉 자석 테이프 세트(이전에 작성된 가치 있는 문제가 저장된 곳)에 있어야 한다"는 문장에서 라이브러리라는 단어가 실제로 라벨 붙은 자료 선반에서 유래된 것이라는 생각을 해본 적이 없었음
- EDSAC의 원조 링크인 Margaret Hartrey가 종이테이프 서랍에서 라이브러리 서브루틴 테이프를 꺼내는 메이킹 영상에서 확인할 수 있음. 전체 영상도 볼 만함
- 라이브러리가 다른 이름으로 불린 적을 들어본 적 없음. 대표적으로 .lib 파일 확장자가 있음
- 함수가 굳이 call이라는 키워드를 필요로 했던 건 아니라고 생각해왔음. 함수는 보통 값을 반환하므로 대입문 안에 사용하면 됨. call이 필요한 건 subroutine(실질적으로는 이름이 붙은 주소/레이블)이었음. 사실 GOTO로도 이 주소를 직접 이동하고 다시 올 수 있음. CALL 키워드 덕분에 실행 흐름이 더 명확하게 보임. 마치 사장이 Sam에게 계산을 맡겼다가, Bill에게 TPS 리포트 인쇄를 맡기는 것처럼 일의 흐름이 진행됨. 결국 모든 것이 함수로 바뀌었고 subroutine은 'spaghetti'라는 별명으로 불렸음. 그런데 왜 routine(프로그램)과 subroutine이라는 용어가 있는지 궁금함
- routine이라는 단어의 유래는 1947년 Goldstine과 von Neumann의 문서에 따르면 "문제의 코딩된 일련의 명령을 routine이라 부릅니다"라고 명시되어 있음 (참고)
- 음악에도 "call and response"라는 표현이 있음. return value 개념과도 연결된다고 생각함
- Algol 60도 함수뿐만 아니라 파라미터에 대해서 "call"이라는 용어를 썼음. 예를 들어 "call by value", "call by name" 등인데, 4.7.5.3에 보면 "call by value인 경우"라는 구조가 나옴. 오늘날에는 procedure/function/subroutine은 'call'하고, argument/parameter는 'pass'한다고 말하기 때문에 'pass by value/reference/name'이 더 명확함. 하지만 "call by value" 등의 옛 용어도 아직 일부 문맥에선 남아 있음. Argument나 parameter를 호출(call)하는 개념은 사라졌으나 이런 legacy 용어는 계속 존재함