
OSSCA(오픈소스 컨트리뷰션 아카데미) 2026 Valkey 트랙 5주차 과제 기록입니다.
4주차 과제에서는 echofallkim이라는 새 명령어를 Valkey에 직접 추가했습니다.
echofallkim abc를 입력하면 "abc"를 그대로 돌려주는 명령이었습니다.
127.0.0.1:6379> echofallkim abc
"abc"
내부적으로는 기존 echoCommand와 동일하게 addReplyBulk(c, c->argv[1])를 호출해서 입력값을 그대로 반환하는 방식이었습니다.
이번 5주차 과제는 응답을 가공하는 것입니다.
127.0.0.1:6379> echofallkim abc
"echo2_abc"
입력값 앞에 echo2_ prefix를 붙여서 응답하도록 기존 함수를 수정합니다.
Valkey에서 문자열은 대부분 sds 타입으로 다룹니다.
sds는 사실 char *인데, 문자열 앞쪽 메모리에 길이·할당 크기·타입 정보를 가진 header가 붙어 있습니다.
[ len | alloc | flags | buf[] ]
↑
sds 포인터가 여기를 가리킴
덕분에 strlen()처럼 끝까지 순회하지 않고 sdslen()으로 O(1)에 길이를 알 수 있고, 중간에 \0이 있어도 길이를 header가 알고 있어 binary safe합니다.
c->argv[1]은 robj * 타입입니다. 실제 문자열 값은 val_ptr이라는 멤버에 들어있는데, 임베디드 값일 수 있어 직접 접근하면 안 됩니다.
objectGetVal(c->argv[1])을 통해 안전하게 sds 포인터를 꺼냅니다.
새로 만든 sds를 RESP bulk string으로 클라이언트에 응답하는 함수입니다.
이 함수는 넘겨받은 sds의 소유권을 가져가기 때문에, 호출 후 별도로 sdsfree()를 호출하면 double-free 위험이 있습니다.
기존 echofallkimCommand는 addReplyBulk()로 argv[1]을 그대로 반환합니다.


변경 순서:
1. objectGetVal(c->argv[1])로 입력값의 sds를 꺼낸다
2. sdsempty()로 빈 sds를 하나 만든다
3. sdscatfmt(reply, "echo2_%S", input)으로 prefix와 입력값을 이어 붙인다
4. addReplyBulkSds(c, reply)로 응답 후 소유권을 넘긴다
sdscatfmt()에서 %S(대문자)는 sds 타입 문자열을 받는 포맷 지정자입니다.
일반 C 문자열이라면 소문자 %s를 씁니다.
이전 과제에서 echofallkimCommand를 server.h에 선언하는 것을 빠뜨렸습니다.
빌드 시 commands.def에서 해당 함수를 찾지 못해 에러가 발생했고, 이번에 함께 추가했습니다.
void echoCommand(client *c);
void echofallkimCommand(client *c); // 추가
void commandCommand(client *c);
make -j4
./src/valkey-server --port 6399 --daemonize yes
./src/valkey-cli -p 6399 echofallkim abc

모든 케이스에서 echo2_ prefix가 정상적으로 붙어 응답됩니다.
addReplyBulk()는 이미 있는 robj를 그대로 보낼 때 편하지만, 응답을 가공해야 한다면 sds를 직접 조합해야 한다addReplyBulkSds()는 sds 소유권을 가져가므로 호출 후 sdsfree() 불필요 (double-free 주의)objectGetVal()로 robj에서 실제 sds 포인터를 꺼내야 한다 — val_ptr 직접 접근 금지sdscatfmt()의 %S는 sds용, %s는 C string용 포맷 지정자sds는 char *이지만 header에 길이 정보를 담아 binary safe하고 O(1) 길이 조회가 가능