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
{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
'넓고 얕은 데이터베이스 지식 > NoSQL' 카테고리의 다른 글
Redis & Valkey에 대해 알아보자 - 원자성과 자료구조(Siphash, Skiplist) (2) | 2025.05.11 |
---|---|
Redis & Valkey에 대해 알아보자 - 개념, 역사, 캐싱, 사용 분야 (0) | 2025.05.09 |
속성으로 익히는 mongoDB (관련 용어 & 명령어 요약 정리) (0) | 2023.08.11 |
macOS에서 mongoDB를 설치해보자 (0) | 2023.08.10 |