SELECT 1
Entry 0242026.11.03 화
One launch a day. Picked, run, explained.

2026.11.03 화

Jik: 가비지 컬렉터 없이 메모리 오류 막기

오늘의 픽: Jik

Jik 은 가비지 컬렉터 없이 프로그램의 메모리를 관리하는 프로덕트다. C 로 컴파일되는 프로그래밍 언어다. 문자열, 구조체 같은 값은 영역에 할당되고, 영역을 해제하면 그 안의 값도 함께 해제된다.

오늘의 픽으로 선정한 이유는 가비지 컬렉터 없이도 컴파일러가 메모리 오류를 잡기 때문이다.

exit 0실행함작동한다. 다른 영역의 값을 잘못 참조하는 코드를 컴파일러가 거부했다.
출처
Show HN
만든 방식
C, Jik

무엇이 문제인가

C 처럼 메모리를 직접 할당하고 해제하는 언어에서는 해제한 메모리를 다시 사용하거나 해제를 빠뜨리는 실수가 생긴다. 가비지 컬렉터가 있는 언어는 이 실수를 막는 대신, 사용하지 않는 메모리를 실행 중에 찾아 해제하는 비용이 든다.

제작자는 README 에서 Jik 이 가비지 컬렉션도, 수동 힙 할당도 사용하지 않는다고 밝혔다. Go 공식 문서의 가비지 컬렉터 안내서에 따르면, Go 는 모든 프로그램에 런타임 라이브러리를 함께 넣는다. 그 안의 가비지 컬렉터가 더는 필요 없는 메모리를 찾아 회수한다. 같은 문서에 따르면 가비지 컬렉터는 물리 메모리와 CPU 시간을 쓴다. 메모리를 더 쓰게 하면 CPU 시간이 줄고, 메모리를 아끼면 CPU 시간이 는다.

어떻게 해결했나

Jik 은 2026년 11월 2일 Hacker News 에 Show HN 글로 올라왔다. Jik 코드는 C 로 번역된 뒤 clang 이나 gcc 로 컴파일된다. 문자열, 벡터, 구조체 같은 복합 값은 영역여러 값을 함께 할당해 두는 메모리 공간이다. 값을 하나씩 해제하지 않고 영역 전체를 한꺼번에 해제한다.에 할당된다. 모든 함수에는 지역 영역이 있다. 함수가 끝나면 그 영역과 영역 안의 값이 함께 해제된다.

함수가 문자열이나 구조체 같은 값을 반환하려면 호출자가 영역을 인자로 넘겨야 한다. 함수는 그 영역에 값을 할당한다. 컴파일러는 함수를 호출할 때 인자로 넘기는 값들이 같은 영역에 있는지 검사한다. 더 오래 남는 값이 그보다 먼저 해제되는 영역의 값을 가리키지 못하게 하기 위해서다. 제작자는 Jik 컴파일러도 Jik 으로 작성했다. 저장소에는 C 로 작성한 초기 컴파일러가 있고, 이 초기 컴파일러로 Jik 컴파일러를 빌드한다.

무엇이 다른가

첫째, 메모리를 회수하는 시점이 다르다. Jik 은 함수가 끝날 때 그 함수의 영역을 한꺼번에 해제하므로, Go 와 달리 실행 중에 회수할 메모리를 찾는 작업이 없다. 트레이드오프는 함수가 끝나기 전에는 영역의 메모리가 해제되지 않는다는 점이다. 긴 반복문 안에서 할당한 값은 다음 반복으로 넘어가도 함수가 끝날 때까지 남는다.

둘째, 메모리 안전성을 검사하는 방법이 다르다. C 컴파일러는 해제한 메모리를 가리키는 코드도 컴파일한다. Jik 컴파일러는 함수가 지역 영역에 할당한 값을 반환하거나, 구조체에 다른 영역의 값을 저장하면 컴파일하지 않는다. 트레이드오프는 프로그래머가 결과를 담을 영역을 함수의 인자로 넘기고, 함수를 호출할 때 인자로 넘기는 값들을 같은 영역에 두어야 한다는 점이다. 값을 읽기만 하는 함수는 컴파일러가 안전하다고 판단해 이 규칙에서 제외한다.

어떻게 만들었나

  • 커밋 207개는 2026년 4월 25일부터 11월 2일까지 개발자 한 명이 작성했다. Co-authored-by 트레일러는 없다.
  • 상태는 베타(v0.1.0-beta.1)다. 제작자는 알려진 한계를 docs/known-issues.md 에 정리했다.
  • 테스트는 C 로 된 초기 컴파일러용과 Jik 컴파일러용이 따로 있다.

실행해 보니

clang 으로 저장소를 빌드하고, 4코어 가상 머신에서 README 의 명령을 따라 실행했다.

  1. 빌드. make 는 16초 만에 끝났다. 컴파일러 실행 파일은 927 KB 였다. 생성된 C 코드를 컴파일하는 동안 C 컴파일러가 경고 238개를 출력했다.
  2. 테스트. make test 를 실행하자 검사 13,036개가 14초 만에 모두 통과했다.
  3. 영역 검사. 지역 영역에 만든 구조체를 반환하는 함수를 넣자 컴파일 오류가 났다. 함수의 지역 문자열을 다른 영역의 구조체에 저장하는 호출도 거부됐다. 문자열 리터럴을 인자로 직접 넘기자 컴파일에 성공했다. 문서에 따르면 이때 컴파일러가 리터럴을 구조체의 영역에 할당한다.
  4. 반복문의 메모리. 정수 2,000,000개를 문자열로 바꾸는 반복을 main 안에 두자 main 의 영역이 96 MB 까지 커졌다. 최대 메모리 사용량은 97.8 MB 였다. 같은 작업을 함수로 옮겨 반복마다 호출하자 main 의 영역은 66 KB, 최대 메모리 사용량은 11.1 MB 였다. 실행 시간을 한 번씩 측정하니 main 안에서 반복한 쪽이 0.14초, 함수를 호출한 쪽이 0.25초였다. 저장소의 메모리 관리 문서와 알려진 한계 문서에는 반복문 안의 할당에 대한 안내가 없다.
  5. 셀프 호스팅컴파일러를 그 컴파일러가 컴파일하는 언어로 작성해, 컴파일러가 자신을 직접 빌드하게 하는 방식이다.. make test-bootstrap-full 은 초기 컴파일러에서 시작해, 앞 단계에서 만든 컴파일러로 다음 단계의 Jik 컴파일러를 세 번 이어서 빌드한다. 57초 만에 끝났다. 2단계 컴파일러와 3단계 컴파일러가 생성한 C 코드가 같았다. 컴파일러가 자신을 다시 빌드해도 결과가 달라지지 않는다는 뜻이다.
jik error: cannot return local allocation
      --> bad_return.jik:7:12
jik error: region mismatch
      --> bad_store.jik:11:15
    = all storing/returning call arguments must belong to the same region

확인하지 못한 것

  • C 라이브러리 호출. 패키지 저장소 jik-packages 에는 C 게임 라이브러리 Raylib 의 바인딩다른 언어로 작성한 함수를 호출할 수 있도록, 호출하는 언어에서 그 함수의 이름과 타입을 선언한 것이다.이 있다. 이 바인딩으로 예제 게임을 빌드해 보자.
  • Windows. 제작자는 Windows x64 에서도 테스트했다고 밝혔다. gcc 로 빌드하고 make test 를 실행해 보자.

판정

작동한다. 다른 영역의 값을 잘못 참조하는 코드를 컴파일러가 거부했다. 다만 반복문 안에서 할당한 값은 함수가 끝날 때까지 남아, 반복할수록 메모리 사용량이 커진다. 가비지 컬렉터 없이 C 보다 안전한 언어가 필요한 경우에 써 볼 만하다.

시작하기

  1. git clone https://github.com/jik-lang/jik && cd jik
  2. make
  3. ./jik run examples/hello.jik
필요한 것
Make 와 clang 또는 gcc. Jik 으로 작성한 프로그램을 빌드할 때도 C 컴파일러가 필요하다
비용
MIT, 무료.

제작자에 따르면 Jik 은 베타 단계라 아직 버그가 있을 수 있고 언어 사양도 바뀔 수 있다.

실행해서 확인한 절차다.

진행

  1. 3일예정
  2. 7일예정
  3. 15일예정
  4. 30일예정
  5. 90일예정
  6. 180일예정
  7. 365일예정