본문 바로가기
넓고 얕은 데이터베이스 지식/NoSQL

Valkey 오픈 소스를 직접 빌드하고 나만의 명령어를 추가해보자

by 팡펑퐁 2025. 5. 13.
728x90
💡 설명 : C언어를 전혀 모르는 자바 개발자가 최대한 이해하기 쉽게 풀어쓴 실습 기록입니다.
🌀 목표 : Valkey의 소스 코드에서 echo 명령어를 참고하여 나만의 echo 명령어 만들어보기

- 커맨드 이름 : echoX3
- 커맨드 설명 : 입력 문자열을 세 번 반복하는 echo 명령어
- 커맨드 입력 예시 : "helloworld!"
- 커멘드 출력 예시 : "helloworld! helloworld! helloworld!"

 

👨🏻‍🔬 사전 준비

🧪 Valkey GitHub 저장소 Fork & Clone

아래 링크로 접속:
👉 https://github.com/valkey-io/valkey

오른쪽 상단의 Fork 버튼 클릭
👉 본인의 GitHub 계정으로 복사본 생성됨 (예: github.com/your-username/valkey)
# 본인 계정에 생성된 fork 저장소 clone
git clone https://github.com/your-username/valkey.git
  • Github에서 Valkey Repository에 들어가 fork 합니다.
  • 로컬에서 git clone 명령어를 통해 프로젝트를 다운로드합니다.

 

🔬 make 명령어로 빌드하기 &  Valkey 서버 실행

🔸 src 폴더 살펴보기

  • clone 받은 프로젝트에서 src 폴더에 들어가 보면 아직 빌드 전이라 서버 실행 파일이 존재하지 않음을 확인할 수 있습니다.

 

🔸 make 명령어로 빌드하기

$ make

  • make 명령어를 통해 빌드해 봅시다.
  • 그럼 위와 같이 valeky-cli, valkey-server 파일이 생성됩니다.

 

🔸 Valkey 서버 실행하기

# src 폴더 내부
$ ./valkey-server

  • valkey를 빌드하고 실행하는 데까지 성공했습니다.

 

🔸 Valkey 클라이언트 접속하기

$ ./valkey-cli 
127.0.0.1:6379> ping

# 출력
PONG
  • 새로운 터미널을 띄우고 이번에는 valkey-cli 파일을 실행시킵니다.
  • 그럼 valkey 클라이언트로 접속이 가능합니다.

 

🔸 기존 echo 명령어 실행해 보기

127.0.0.1:6379> echo helloworld!

# 출력
"helloworld!"
  • echo 명령어를 실행하면 입력값 그대로 리턴함을 확인할 수 있습니다.

 

🚀 Valkey에서의 명령어 동작 흐름과 연관 파일 정리

redis-cli -> 입력 받은 문자열을 파싱 -> 명령어 이름 분석
        -> 명령어 목록에서 해당 함수 찾기
        -> 함수 실행 (예: echoCommand)
        -> 응답 생성 -> 클라이언트에게 전달

 

👾 연관된 파일

🔸 server.c

  • Valkey 서버가 실행될 때 진입하는 핵심 파일입니다.
  • 이 안에서 initServer() 함수를 통해 서버 초기화가 이루어집니다.
  • 그 과정 중 populateCommandTable()이 호출되어 command.def에 정의된 명령어들이 실제 메모리에 등록됩니다.
  • 즉, 서버가 클라이언트의 명령어를 인식하고 실행할 수 있도록 만드는 출발점이라 할 수 있습니다.
    • Java로 치면 main() 메서드와 초기 설정을 모두 포함한 시작 클래스 역할을 한다고 볼 수 있습니다.

 

🔸 command.def

  • 명령어 정의 파일로 명령어 테이블이라고도 합니다.
  • command.def는 일종의 템플릿 데이터처럼 사용됩니다.
  • 빌드 과정 중 이 파일이 자동으로 파싱 되어 → commands.c라는 파일이 생성됩니다.
    • 생성된 commands.c에는 명령어 이름과 실행 함수 포인터가 매핑된 명령어 테이블 배열이 포함되어 있습니다.
  • 즉, 추가하고 싶은 명령어를 이 목록에 등록하면 됩니다.

 

🔸 server.h

  • C 언어에서 .h 파일은 Java에서 interface나 import에 해당합니다.
  • server.h에 함수의 선언을 추가하면 다른 파일에서도 사용이 가능합니다.
  • 이걸 선언하지 않으면 server.c가 컴파일될 때 함수가 존재하지 않는다는 에러가 발생합니다.

 

🔭 실습 시작

🏃🏻‍♂️‍➡️ 명령어 등록해 보기

🔸 command.def

command.def로 생성된 command.c 파일 내부

# command.def
{MAKE_CMD("echo","Returns the given string.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,ECHO_History,0,ECHO_Tips,0,echoCommand,2,CMD_LOADING|CMD_STALE|CMD_FAST,ACL_CATEGORY_CONNECTION,ECHO_Keyspecs,0,NULL,1),.args=ECHO_Args},

# echo 명령 정의를 복사 붙여넣기 하여 아래 내용으로 변경
# 명령어 이름을 echoX3, 함수명을 echoX3Command로 변경
# my custom command 
{MAKE_CMD("echoX3","Returns the given string.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,ECHO_History,0,ECHO_Tips,0,echoX3Command,2,CMD_LOADING|CMD_STALE|CMD_FAST,ACL_CATEGORY_CONNECTION,ECHO_Keyspecs,0,NULL,1),.args=ECHO_Args},
  • command.def 파일에서 echo 명령어의 정의 부분을 복사/붙여넣기 후 명령어 이름과 명령어의 함수명을 변경하는 작업입니다.
  • command.c 파일을 보면 첫 번째 인자가 name이며, 중간에는 인자는 function 명에 해당합니다. 이를 echoX3과 echoX3Command로 변경합니다.
    • echoX3은 명령어 이름이고, echoX3Command은 명령어 사용 시 호출되는 함수명일 것입니다.

 

🔸 server.c

# server.c

/* my custom command */
void echoX3Command(client *c) {
    if (c->argc != 2) {
        addReplyError(c, "Wrong number of arguments for 'echoX3' command");
        return;
    }

    sds input = c->argv[1]->ptr;

    // "input input input" 형식의 문자열 생성
    sds result = sdscatfmt(sdsempty(), "%S %S %S", input, input, input);

    // addReplyBulkSds()는 sds 메모리를 직접 해제함
    addReplyBulkSds(c, result);
}

  • 이제 server.c에서 echoCommand 함수를 찾아 바로 아래에 복사하여 붙여 넣은 뒤 입력값을 그대로 반환하는 것이 아니라 입력값을 세 번 반복해서 출력하도록 코드를 수정합니다.
  • 참고로, C 언어는 Java와 달리 가비지 컬렉션이 존재하지 않기 때문에, 메모리를 직접 할당한 경우 수동으로 해제해야 합니다.
    • 하지만 addReplyBulkSds() 함수는 전달받은 문자열(sds)의 소유권을 가져가서, 내부적으로 메모리를 알아서 해제해 주므로 따로 free()나 sdsfree()를 호출할 필요는 없습니다.

 

🔸 server.h

# server.h
void echoX3Command(client *c);

  • 위에서 설명한 대로 새로운 함수의 시그니처를 server.h에 선언합니다.

 

🚨 server.h에 선언하지 않을 시 발생하는 에러

./commands.def:11103:151: error: use of undeclared identifier 'echoX3Command'; did you mean 'echoCommand'?
 11103 | {MAKE_CMD("echoX3","Returns the given string.","O(1)","1.0.0",CMD_DOC_NONE,NULL,NULL,"connection",COMMAND_GROUP_CONNECTION,ECHO_History,0,ECHO_Tips,0,echoX3Command,2,CMD_LOADING|CMD_STALE|CMD_FAST,ACL_CATEGORY_CONNECTION,ECHO_Keyspecs,0,NULL,1),.args=ECHO_Args},
  • 만약 .h 파일에 별도로 선언하지 않으면 빌드 시 위와 같은 에러가 발생합니다.
  • 즉, 컴파일러는 echoX3Command라는 함수가 정의되어 있다는 사실을 알지 못하기 때문에, 정의되지 않은 식별자(unresolved identifier) 에러가 발생하게 됩니다.
  • 따라서 .h 파일에 함수 선언을 추가하는 것은 C 언어에서 필수적인 작업입니다.

 

🚨 빌드하지 않고 새로운 커맨드 실행하기

127.0.0.1:6379> echoX3 helloworld
(error) ERR unknown command 'echoX3', with args beginning with: 'helloworld'
  • 당연하게도 새로 빌드를 하지 않으면 적용이 안됩니다.

 

⚡️ 빌드 후 새로운 커맨드 실행하기

# 이전 빌드 초기화
$ make clean

# 재빌드
$ make

############# src 폴더 내부 #############

# 서버 재실행
$ ./valkey-server

# 클라이언트 접속 후 테스트
$ ./valkey-cli
127.0.0.1:6379> echoX3 helloworld!

# 출력
"helloworld! helloworld! helloworld!"
  • 위와 같이 간단한 방식으로 나만의 명령어를 추가할 수 있습니다.
  • 이렇게 오픈소스 코드를 직접 들여다보고, 작은 수정을 해보는 경험을 통해 Valkey와 오픈소스 프로젝트에 한 발 더 가까이 다가갈 수 있었습니다.
  • 개인적으로도 매우 의미 있고 흥미로운 시간이었습니다. 😊

 

 

 

참고

2025 오픈소스 컨트리뷰션 아카데미 Git & Redis 수업 자료

ChatGPT

728x90