TL;DR
- Odin 같은 명령형 프로그래밍 언어의 네임스페이싱 논쟁은 긴 타입 이름에서 절차 이름이 길어지는 데 대한 미학적 반감이며, 메서드(method) 없이도 의미상 문제가 생기는 것은 아님.
- Odin은 메서드를 일반적인 방식으로 지원하지 않으며, 네임스페이싱에 대한 미학적 불만을 다루는 가장 적절한 방법은 아무것도 하지 않는 것임.
- 파일 단위 비공개(
@(private="file"))는 불필요한 마찰을 만들 수 있으며, 공개 API와 내부 구현을 구분하려면_접두사나 타입 소거(type erasure) 같은 대안을 고려할 수 있음. - 비공개 선언과 필드에 직접 접근할 방법이 없으면 필요한 코드를 다시 구현하거나 구조체 필드에 안전하지 않은 포인터 연산을 써야 하므로, API 설계에는 필요할 때 쓸 수 있는 탈출구(escape hatch)가 필요함.
- 네임스페이싱 불만과 비공개 우선 습관은 다른 언어의 가정을 Odin에 가져오는 데서 비롯되며, Odin의 설계는 마찰을 통해 부적절한 사용을 피하도록 넛징(nudging)함.
타입_동사 연관
- Karl Zylinski의 *Tom’s Namespaces: An Odin Fanfic*은 Odin 같은 명령형 프로그래밍 언어의 네임스페이싱 문제를 훌륭하게 살펴보는 글임. 이 글을 읽기 전에 해당 글을 읽기를 강력히 권하며, 여러 댓글 포럼에 공유한 뒤 내린 결론은 이 문제에 실질적인 “해결책”이 없다는 것임.
- 간단한 예시는
world_add(&world, entity)처럼 타입 이름과 동사를 결합하는 방식임. - 타입 이름이 짧을 때는 괜찮아 보이지만,
Thingy_Foo_Helper처럼 길어지면thingy_foo_helper_get_handle(&tfh)처럼 함수 이름이 다루기 불편해진다는 것이 이 방식에 대한 미학적 반론임. - 불만을 제기하는 사람들이 흔히 제안하는 해결책은 메서드(method)이며, 예를 들면
tfh.get_handle()임. - 그러나 핵심은 여전히 미학적 반감이며, 순수한 명령형 절차적 프로그래밍 언어에 대한 미학적 반감이라고 볼 수 있음. 메서드가 없어도 의미상 불가능한 일은 없으며, 일부 사람에게 그저 “보기 흉할” 수 있을 뿐임.
- 메서드는 그 자체로 별도의 문제를 만들기도 함. Odin FAQ는 Odin에 메서드가 없는 이유를 간략히 설명하며, Odin은 일반적인 의미의 메서드를 지원하지 않음.
Odin에서 이 “미학적 문제”를 다루는 가장 적절한 방법은 뉴웰식 접근임: 아무것도 하지 않음.
기본 공개
- 반복해서 보이는 관련 패턴은 사람들이
@(private="file")을 남용해 불필요한 마찰을 만드는 일임. 항상 묻는 질문은 “누구에게 코드를 숨기는가? 자기 자신인가?”임. - 이 습관은 대개 Java, C#, C++ 개발자가 기본 비공개(private-by-default)를 당연히 좋은 관행으로 여기면서, 실제로 그런지 의문을 제기하지 않는 데서 비롯된다고 봄. 프로그래밍에는 의심 없이 따르는 교리가 많지만, 이를 모두 열거하는 것은 이 글의 범위를 벗어남. 기본 비공개가 좋은 관행인 것은 아니며, Odin이 패키지 수준에서 기본 공개(public-by-default)이고 구조체 수준의 비공개나 보호(protected)를 두지 않는 이유도 여기에 있음.
- 어떤 것이 파일 단위로 비공개여야 하는지, 패키지 단위 비공개로는 왜 충분하지 않은지, 그리고 애초에 비공개여야 하는지를 자문할 필요가 있음. Odin이 기본 공개인 데는 이유가 있으며, 이를 받아들이기를 권함.
- 불만의 대부분은 공개 API와 비공개 내부 구현을 분리하고 싶다는 데서 비롯됨. 실제로 그런 구분이 필요하다면
_접두사를 사용하는 “의사 비공개(pseudo-private)” 관례를 쓸 수 있음. 내부용임을 나타내면서도 필요할 때 접근을 막지는 않음. “진짜” 비공개가 필요하다면 타입 소거(type erasure)를 시도할 수 있음. - 서드파티 API가 구조체 필드나 절차를 비공개로 만들어 둬서 접근이 필요했던 경우가 여러 번 있었음. 구조체 필드에는 비공개를 우회하려고 안전하지 않은 포인터 연산을 썼고, 절차에는 처음부터 다시 구현해야 했음.
- API를 설계할 때 사용자가 필요로 할 것을 설계자가 더 잘 안다고 가정하지 말기를 바람. 미래나 사용자가 실제로 필요로 할 것을 예측할 수 없음. 필요하다면 경고를 추가하되, 사용자가 우회하는 일을 완전히 막지는 말아야 함. 필요하다면 안전장치를 끄고 위험을 감수할 수 있게 해야 함.
- 내가 아는 한 근본적인 문제는 어떤 언어도 선언이나 필드의 비공개 가시성을 직접 덮어쓸 방법을 제공하지 않는다는 점임.
- Java는 리플렉션(reflection)을 이용해 간접적으로 우회할 수 있는 사례지만, 실제 사용에서는 성능 문제가 생길 수 있으며 특히 특정 필드나 호출에 의존할 때 두드러짐.
- 모든 언어는 선언의 가시성을 엄격하고 절대적인 것으로 다루며, 우회할 수 없는 것으로 취급함. 패키지 수준 절차에는 때때로 좋은 선택일 수 있지만, 구조체 필드에는 결코 좋은 선택이 아님.
- Odin의 핵심 설계 철학 중 하나는 가능한 곳에 탈출구를 제공하는 것임. 컨텍스트(context)는 이 언어에서 이런 메커니즘을 보여주는 대표적인 사례임.
- 캡슐화(encapsulation)를 의심 없이 따르는 교리로 여기는 태도가 답답하지만, 그런 태도가 어디서 비롯되는지는 이해함. 기본 비공개를 선호하는 사람들은 대체로 두 부류임.
- 첫 번째 부류는 SOLID 같은 원칙에 뿌리를 두고, 구현 세부 정보를 숨기는 캡슐화 자체를 본질적으로 좋은 관행으로 여김.
- 두 번째 부류는 더 실용적이며, 언제든 바뀔 수 있는 내부 요소에 API 사용자가 의존하지 않기를 바람.
- 두 번째 부류의 우려는 정당함. 안정성을 보장하지 않는 요소를 기반으로 사람들이 코드를 작성하는 것은 원하지 않을 수 있음. 하지만 항목을 잠그면 공개 API로 드러나지 않은 요소에 실제로 접근해야 하는 사람까지 막게 됨. 의도치 않게 첫 번째 부류와 똑같이 구현 세부 정보를 숨기게 되는 셈임.
- 따라서 API를 설계할 때 탈출구를 제공하는 방안을 고려할 필요가 있음. 일상적인 사용을 억제할 만큼 불편한 형태로 만들고, “안정성 보장이 없으므로 이에 의존하지 말 것”이라고 명확히 표시하면 됨.
설계 철학의 한 측면인 넛징
- 네임스페이싱에 대한 불만과 기본 비공개 습관은 모두 다른 언어나 패러다임에서 비롯된 가정을 Odin에 적용하고, Odin의 설계 철학에 맞춰 적응하지 않는 데서 비롯됨.
- Odin 설계의 상당 부분은 현실 세계의 문제를 실용적인 방식으로 해결하는 데 초점을 둠. 반대로 Odin의 생각을 그런 방식으로 설계되지 않은 언어에 강요하는 것 역시 좋은 생각이 아닐 수 있음.
- 그 결과, 언어는 사용자를 특정 방향으로 유도하기 위해 일부 작업을 의도적으로 불편하게 만듦.
- 프로그래밍의 즐거움은 키우기 어려운 요소이며, Odin으로 이를 북돋우기 위해 최선을 다했음. 넛징은 Odin이 사용하기 편리하게 느껴지는 이유 중 하나임.
- 대부분의 사람은 자연스럽게 “순탄한 경로(happy path)”를 따름. 잘못된 접근에 있는 미묘한 마찰을 거슬러 나아가지 않으므로 대개 그 마찰을 알아차리지 못함. 그러나 일부는 언어나 컴파일러의 신호를 받아들이지 않고 마찰을 정면으로 밀어붙임.
- 패키지, 네임스페이스, 비공개 여부는 다른 언어에서 가져온 의심 없는 교리를 바탕으로 기능을 오용하는 영역임.
- 때로는 사람들이 스스로 눈을 찌르는 일을 막을 수 없음. 스스로 또는 다른 사람을 통해 결국 자신과 자신의 코드를 사용하는 모든 사람에게 상황을 더 나쁘게 만들고 있음을 깨닫기를 바랄 수밖에 없음.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요