영상 스타일 적용 10 | Living Screencast로 함수의 반환값을 실행 화면으로 바꾸기
AI AUTOMATA · 영상 스타일 적용 10 · LIVING SCREENCAST
add(5, 3)의 8은 어디서 돌아올까 — 실행 화면으로 보는 함수의 반환값
이 글을 읽고 나면 result = add(5, 3);에서 인수 5와 3이 매개변수 a와 b로 복사되고, 함수 안에서 만든 8이 return으로 하나 돌아와 result에 저장되는 순서를 설명할 수 있습니다. 그리고 함수가 끝난 뒤 a, b, sum을 왜 더 쓸 수 없는지, return과 printf가 어떻게 다른지도 구분할 수 있습니다. 이 과정을 ‘살아 있는 화면 녹화’ 스타일의 90초 영상과, 한 단계씩 넘겨 보는 HTML 추적기로 만들었습니다.
1. 무엇이 달라졌나
교재는 CODE 9.7 코드 상자와 실행 결과 한 줄, 그리고 “result = add(5, 3);은 result = 8;과 같다”는 설명으로 반환값을 보여 줍니다. 영상은 이 설명을 값이 실제로 움직이는 화면으로 바꿨습니다. 창 하나를 편집기 · 호출 프레임 · 터미널 세 구역으로 나누고, 작은 픽셀 마스코트(프로그램)가 5와 3을 들고 a와 b 상자로 옮긴 뒤, 8을 들고 return 줄에서 main의 result로 돌아옵니다. 화살표 커서(사용자)는 ‘다음 단계’ 버튼만 누릅니다.
또 하나의 변화는 예상과 실제를 나란히 둔 것입니다. 추적기가 예상한 출력 “반환된 값: 8” 바로 옆에서, gcc로 실제 컴파일·실행한 기록이 재생됩니다. 마지막에는 교재에 없는 자체 확장으로 인수를 7과 −2로 바꿔, 시청자가 먼저 5를 예측하고 실제 실행으로 확인하게 했습니다.
2. 원본 스타일 예시: Living Screencast
원본은 LemoLab의 영상 스타일 모음 Lemo-Opuscar에 있는 Living Screencast(식별자 living-screencast)입니다. 실제 제품 화면처럼 보이지만 모든 창과 버튼을 HTML로 다시 그린 ‘화면 녹화풍’ 영상에, 큰 네모 픽셀로 된 마스코트가 살면서 소프트웨어가 하는 일을 몸으로 보여 주는 스타일입니다. 시연 작품은 Clawd Moves In(59.4초)입니다.
원작: LemoLab, Clawd Moves In — Living Screencast 시연 영상(시연 영상 CC BY 4.0). 원본 설명에 따르면 Claude 앱 화면과 Claude Code 마스코트 Clawd를 쓴 비공식 팬 영상입니다. 이번 영상은 그 캐릭터·화면·음악을 쓰지 않았습니다. 재생되지 않으면 아래 ‘원본 영상 열기’를 이용하세요.
원본 영상 열기 ↗원본 STYLE.md ↗원본 DEMO.md ↗
STYLE.md의 핵심은 다섯 가지입니다. 화면은 다시 그린 실제 인터페이스이고 스크린숏이 아니다. 마스코트의 픽셀 격자는 지킨다. 마스코트는 실제 화면 요소의 윗변 위에만 서며, 그 위치는 매 프레임 화면을 측정해 정한다. 커서는 사용자, 마스코트는 소프트웨어이며 손은 나오지 않는다. 화면 위 정보층은 장 표시·자막 알약·‘▶▶ 4×’ 태그 정도로 제한한다.
3. 교재 근거: 기초 C언어 276~279쪽
| 쪽 | 내용 |
|---|---|
| 276쪽 | 9장 Section 02 사용자 정의 함수의 유형과 값 전달 · 01 반환값과 매개변수. CODE 9.7 반환값을 이용한 함수 호출 예제: int add(int a, int b) 안에서 int sum; sum = a + b; return sum;, main에서 result = add(5, 3); 후 printf("반환된 값: %d\n", result); |
| 277쪽 | RESULT “반환된 값: 8”. 코드 해설: add 함수는 a와 b의 합을 sum에 저장해 반환하고, result = add(5, 3);은 result = 8;과 같다. |
| 279쪽 | 매개변수와 인수: 함수를 정의할 때 받는 변수(매개변수)와 호출할 때 넘기는 값(인수)의 구분 |
PDF 쪽번호와 인쇄 쪽번호가 같음을 페이지 이미지로 확인했습니다. 교재 그림은 싣지 않고 아래처럼 다시 그렸습니다.
자체 도식 1 · 호출·복사·반환. 화살표 두 개가 이 글의 전부입니다. 들어갈 때는 값 두 개가 복사되고, 나올 때는 값 하나가 돌아옵니다.
4. 실제 적용 방법
설치형 스킬(lemo-opuscar 플러그인)은 설치하지도 호출하지도 않았습니다. STYLE.md 전문과 DEMO.md를 읽고 규칙을 하나씩 이번 교재 내용에 대응시켰습니다. 원본 저장소의 코드·스프라이트·음원은 가져오지 않았고, 화면·마스코트·음악·효과음을 모두 새로 만들었습니다.
| 원본 규칙 | 이번 적용 | 바꾼 점과 이유 |
|---|---|---|
| 실제 화면을 HTML로 다시 그림 | 편집기(교재 코드) · 호출 프레임 추적기 · 터미널 세 구역 창 | ‘제품’ 대신 교재 코드를 실행하는 학습 화면. 추적기에는 ‘교육용 상태 추적 · 실제 메모리 화면 아님’ 표시 |
| 데모 내용은 실제와 일치 | 터미널 글자는 script 명령으로 기록한 실제 로그 원문 | 명령 입력 속도만 영상 길이에 맞췄고, 그 사실을 터미널 아래에 적음 |
| 픽셀 마스코트 = 소프트웨어 | 새로 그린 12×10 청록 픽셀 캐릭터가 값(5, 3, 8)을 들고 이동 | 원작 캐릭터 미사용. 터미널 커서 블록에서 태어남(원본의 ‘출생 장면’ 문법만 사용) |
| 윗변 위에만 선다, 매 프레임 측정 | 코드 줄·변수 상자·호출 스택·터미널 출력 줄의 윗변을 매 프레임 측정 | 글자를 가리지 않도록 줄 끝 오른쪽과 상자 머리 아래 빈 통로에만 착지 |
| 커서 = 사용자, 원인과 결과 | 커서가 ‘다음 단계 ▶’를 누를 때마다 실행 줄과 상자 상태가 바뀜 | 키 입력 표시(HUD)는 터미널 글자로 대신해 생략 |
| 스포트라이트 정지 | result = add(5, 3); 줄과 “← result = 8;과 같다” 표지에 확대 + 주변 어둡게 | 교재 277쪽의 핵심 문장을 ‘하나의 약속’으로 사용 |
| ▶▶ 4× 시간 경과 태그 | 자체 확장(7, −2)의 단계 추적을 빠르게 넘길 때 | 예측 질문(73~76초) 뒤에만 사용 |
| 카메라: 확대 ≥ 1, 급회전에만 흐림 | 구역 사이 이동 세 번에만 흐림 | 흐림은 카메라 바깥 고정 층에 걸었고, 방향성 흐림 대신 짧은 균일 흐림 |
| 음악·효과음·음성 | 부드러운 화음 + 마스코트용 사각파 효과음, 클릭·키 소리를 새로 합성 | 음성 없음(자막형). 30fps 대신 의뢰 기준 24fps |
| 결말 선택지: 완성된 것 위에서 잠든다 | 마스코트가 실제 출력 줄 “반환된 값: 5” 위에서 잠듦 | 원작 엔드카드·서명 미사용 |
5. 입력 파일과 제작 단계
- 교재 대조. PDF 275~279쪽을 페이지 이미지로 열어 CODE 9.7, RESULT, 277쪽 해설, 279쪽 매개변수·인수 설명을 확인했습니다.
- 원본 확인. 저장소 커밋을 기록하고 STYLE.md·DEMO.md를 읽었습니다. 원본 영상은 2.5초 간격 프레임으로 확인했고 소리는 듣지 않았습니다.
- 코드 재구성과 실제 실행. CODE 9.7을 줄번호만 빼고 그대로
add.c로 옮겼습니다(원문과 다른 글자 없음). 자체 확장add_ext.c는 인수만 7, −2로 바꾸고 첫 줄에 ‘교재 원문 아님’ 주석을 달았습니다. 두 파일을 gcc로 컴파일·실행하는 터미널 전체를script명령으로 기록했습니다. - 상태 데이터 작성. 실행 순서를 11단계(0~10)의 상태 표로 만들고, 영상과 HTML 추적기가 같은 데이터를 쓰게 했습니다.
- 장면 코드와 정지 화면 점검. 브라우저로 화면을 그리고 주요 시점을 정지 화면으로 뽑아 마스코트·설명표가 글자를 가리는 곳을 고쳤습니다.
- 렌더링과 전체 확인. 90초(2,160프레임)를 MP4로 묶고, 전 구간 디코딩 검사와 1초 간격 프레임 확인을 했습니다.
함께 만든 HTML 추적기(제작 자료 폴더의 추적기.html, 이 글에는 싣지 않은 별도 파일)는 같은 세 구역을 버튼으로 한 단계씩 넘겨 보는 페이지입니다. add(5, 3), add(7, −2), add(0, 0)을 골라 볼 수 있습니다.
6. 프롬프트 전문
네 프롬프트 모두 AI 오토마타 자체 응용문입니다. 원작자의 공개 프롬프트는 원본 STYLE.md입니다. ‘최초·점검·실제 수정’은 이번 작업에서 실제로 수행한 내용이고, ‘확장’은 코드만 미리 실행해 보았고 영상은 아직 만들지 않았습니다.
최초 프롬프트 (실제 사용 · 정리본)
lemo-opuscar 저장소의 styles/living-screencast/STYLE.md(Living Screencast)를 끝까지 읽고, 그 규칙으로 90초 교육 영상을 만들어라.
설치형 스킬은 쓰지 않는다. 원작 데모(Clawd Moves In)의 마스코트(Clawd)·앱 화면·이야기·음악·엔드카드는 쓰지 않는다. 마스코트는 새로 그린 픽셀 캐릭터로 한다.
시작할 때 읽은 파일과 커밋을 밝혀라. 파일에 접근하지 못하면 추정으로 대체하지 말라.
[교재 입력 — 기초 C언어 9장 Section 02, 276~279쪽. 페이지 이미지로 대조]
- 276쪽 CODE 9.7 반환값을 이용한 함수 호출 예제: int add(int a, int b) { int sum; sum = a + b; return sum; } / main에서 int result; result = add(5, 3); printf("반환된 값: %d\n", result);
- 277쪽 RESULT: 반환된 값: 8. 해설: result = add(5, 3);은 result = 8;과 같다.
- 279쪽: 매개변수와 인수의 구분.
코드는 PDF에서 줄번호와 특수 공백을 빼고 그대로 재구성하고, 원문과 달라진 점을 기록하라.
[실행]
gcc -Wall -Wextra -std=c11로 실제 컴파일·실행하고 script 명령으로 터미널 전체를 기록하라(컴파일러 버전, 옵션, 출력, 종료 코드).
자체 확장 코드는 인수만 7, -2로 바꾸고, 파일 첫 줄에 '교재 원문 아님'을 적어라. 정수 범위 밖 입력은 쓰지 않는다.
[화면]
창 하나에 세 구역: ① 편집기(코드, 실행 줄 강조) ② 호출 프레임 추적기(main과 add를 분리한 상자, 실제 변수명 result·a·b·sum) ③ 터미널.
- 추적기에는 '교육용 상태 추적 · 실제 메모리 화면 아님' 표시. 값을 넣지 않은 변수는 '?(값 미정)'으로만 표시한다.
- add가 끝나면 a, b, sum을 '사용할 수 없음'으로만 표시하고, 메모리가 0으로 지워진다고 말하거나 그리지 않는다.
- 터미널은 기록한 session.log 글자를 그대로 재생한다. 명령 입력 속도만 조절하고 그 사실을 화면에 적는다. 녹화하지 않은 성공 화면을 꾸며 넣지 않는다.
- 마스코트(프로그램)는 값을 들고 코드 줄과 상자의 윗변 위로만 이동한다(매 프레임 DOM 측정). 커서(사용자)는 '다음 단계'를 누른다.
- 정보층은 장 표시, 자막 알약, ▶▶ 4× 태그만. 확대 ≥ 1. 움직임 흐림은 급회전에만.
[장면]
0~12초 인수·매개변수·반환값 질문 / 12~35초 호출과 값 복사 / 35~55초 합 8과 return(핵심 약속: result = add(5, 3); ≡ result = 8; 스포트라이트) / 55~70초 결과 저장과 실제 실행 / 70~90초 자체 확장 7, −2 → 5 예측 후 실제 실행.
[형식]
1920×1080, 24fps, 음성 없음(자막형). 자막은 1.8초 이상 유지하고 설명 대상·마스코트를 가리지 않는다. 음악·효과음은 새로 합성한다.
같은 상태 데이터로 단계 버튼이 있는 HTML 추적기도 만들어라.점검 프롬프트 (실제 사용)
교재 근거·코드·화면·자막·본문을 대조하라. 각 수치의 근거와 스타일 규칙 적용 장면을 확인하고 기대값/관찰값/합격 여부를 기록하라. 미실행을 합격으로 쓰지 마라. [이번 사례 점검 항목] 1. 재구성 코드와 PDF 276쪽 CODE 9.7을 글자 단위로 대조(줄번호·특수 공백 제거 여부 포함). 2. 실제 실행 기록: 컴파일러·버전·옵션·출력·종료 코드. 5+3=8, 7+(−2)=5, 0+0=0 검산. 3. 추적기 상태와 실제 출력이 같은가. 초기화 전 값을 확정 숫자로 표시한 프레임이 있는가. 4. 함수 종료 후 a, b, sum을 0으로 지운다고 표현한 곳이 있는가(화면·자막·본문). 5. 실제 실행 기록 구역과 교육용 상태 추적 구역이 화면에서 구분되는가. 6. 마스코트가 읽을 글자를 가리는가, 자막이 설명 대상을 가리는가, 자막 유지 시간 ≥ 1.8초인가. 7. 전체 영상 디코딩 오류, 1초 간격 전 프레임 확인.
수정 프롬프트 (실제 사용 · 고친 내용 포함)
실패항목의 원인을 특정하고 해당 계산·상태·도식·자막만 수정하라. 원본 교재는 건드리지 말고 수정전후와 재검증 결과를 남겨라. [이번에 실제로 고친 것] 1. 줄 끝 설명표(“← 인수 5, 3” 등)를 처음엔 해당 글자 위에 띄웠더니 바로 윗줄 코드를 가렸다 → 설명표를 그 줄의 끝으로 옮김. 재확인: 편집기 모든 줄이 가려지지 않음. 2. 마스코트(픽셀 6)가 2·5번 줄 코드와 상자 이름표를 가렸다 → 픽셀 5로 줄이고, 상자 머리 아래 48px 빈 통로를 만들고, 코드 줄 착지점을 글자 오른쪽(2번 줄 +470px, 5번 줄 +380px)으로, 호출 스택 착지점을 단계 표시가 없는 가운데로 옮김. 3. 마스코트가 터미널 출력 줄로 점프하는 시각이 출력이 화면에 나오기 전이었다 → 점프 시각을 실제 출력 시각(재생 일정의 tOut)에서 계산. 이때 명령 순번을 하나 잘못 밀어 echo $?의 '0' 줄에 착지하던 것을 1초 간격 전체 프레임 확인에서 발견 → ./add·./add_ext의 출력 줄로 되돌리고, 첫 착지점은 윗줄 컴파일 명령 글자를 가리지 않게 줄 오른쪽 끝(97%)으로 옮김. 4. add 상자 위를 걷는 구간의 도착점이 오른쪽 이름표(‘호출된 함수’)를 가렸다 → 도착점을 상자 너비의 60%로 옮김. 5. 자체 확장 장면의 호출 줄 착지점이 칩(“← 무엇이 돌아올까?”)과 겹쳤다 → 오른쪽으로 40px 이동. 6. 49~55초 자막이 두 줄로 넘쳐 화면 아래에서 잘리고 뒤의 추적기 설명과 겹쳤다 → 자막 알약을 화면 아래 기준으로 정렬하고 배경을 더 불투명하게, 문장을 '돌아온 8이 result에 저장됩니다. result = 8;과 같은 뜻입니다.'로 줄임. 재확인: 20개 자막 모두 한 줄.
확장 프롬프트 (미실행 · 다음 편 후보)
함수 안 매개변수를 바꾸어도 호출자 변수가 바뀌지 않는 자체 예시를 추가하라. 포인터 전달은 별도 후속편으로 둔다.
[구체화한 확장 프롬프트 — 다음 편 후보, 영상은 아직 만들지 않음]
같은 Living Screencast 화면(편집기·호출 프레임·터미널)을 그대로 쓰고, 아래 자체 코드를 실제로 컴파일·실행해 기록하라(교재 원문 아님 표시).
#include <stdio.h>
void change(int a) { a = 100; printf("change 안: a = %d\n", a); }
int main(void) { int x = 5; change(x); printf("main: x = %d\n", x); return 0; }
- 마스코트가 x의 값 5를 복사해 a 상자에 넣고, a를 100으로 바꾸는 동안 main의 x 상자는 5 그대로임을 같은 화면에 둔다.
- 함수가 끝나면 a는 '사용할 수 없음'으로만 표시한다(0으로 지운다고 하지 않는다).
- 실제 출력 두 줄과 추적기 예상이 같은지 확인한다. 주소(&x)와 포인터 매개변수는 다루지 않는다.
[사전 확인] 위 코드를 gcc 13.3.0(-Wall -Wextra -std=c11)으로 실행해 “change 안: a = 100”, “main: x = 5”를 확인했다. 영상은 만들지 않았다.7. 실제 영상과 대표 프레임
90초 · 1920×1080 · 24fps · 음성 없음(자막형) · 새로 합성한 음악과 효과음.
한국어 해설판 (약 99초)
위 영상은 음성 없는 자막판입니다. 아래 영상은 같은 함수 호출·반환 과정을 한국어 음성으로 설명한 별도 해설판입니다. Google Cloud TTS로 만든 합성 음성을 사용했으며, 배경음과 효과음은 해설을 들을 수 있도록 낮췄습니다.


result = add(5, 3);은 result = 8;처럼 읽힙니다.
8. 검산 · 오류 · 연습
실제 실행 기록
$ gcc --version | head -n 1 gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0 $ gcc -Wall -Wextra -std=c11 -o add add.c $ ./add 반환된 값: 8 $ echo $? 0 $ gcc -Wall -Wextra -std=c11 -o add_ext add_ext.c $ ./add_ext 반환된 값: 5 $ echo $? 0
컴파일 경고 없음. add_ext.c는 교재 원문이 아닌 자체 확장 코드입니다.
| 항목 | 기대값 | 관찰값 | 결과 |
|---|---|---|---|
| add(5, 3) — 교재 값 | 8 | “반환된 값: 8”, 종료 코드 0 | 일치 |
| add(7, −2) — 자체 확장 | 5 | “반환된 값: 5”, 종료 코드 0 | 일치 |
| add(0, 0) — 자체 검산 | 0 | 검산 코드 출력 0 | 일치 |
| 추적기 예상 출력 vs 실제 출력 | 같음 | 8 / 8, 5 / 5 | 일치 |
| 초기화 전 값 | 숫자로 확정해 표시하지 않음 | result·sum 모두 ‘?(값 미정)’ | 지킴 |
| 함수 종료 후 지역변수 | ‘0으로 지운다’는 표현 없음 | ‘사용할 수 없음’으로만 표시 | 지킴 |
모든 입력은 int 범위 안의 작은 정수만 사용했습니다. 위 표에서 7, −2, 0은 자체 연습 수치이고, 5와 3·8만 교재 원문 수치입니다.
지역변수는 언제까지 쓸 수 있나
자체 도식 2 · 지역변수 생존 구간. a, b, sum은 add가 호출된 동안에만 쓸 수 있습니다. add가 끝난 뒤 그 값이 메모리에서 어떻게 되는지는 C 언어가 정해 두지 않으므로, 이 글은 ‘0이 된다’고 하지 않고 ‘더 이상 사용할 수 없다’고만 씁니다. result와 sum은 값을 넣기 전까지 ‘값 미정’입니다.
연습: return과 printf는 어떻게 다를까
add를 아래처럼 바꾸면 화면에는 무엇이 찍히고, main의 result에는 무엇이 들어갈까요? (자체 연습 코드)
int add(int a, int b) {
printf("%d\n", a + b);
return 0;
}
답 보기
화면에는 add 안의 printf가 8을 먼저 찍고, 이어서 main이 “반환된 값: 0”을 찍습니다. printf는 값을 화면에 보여 줄 뿐 호출한 쪽에 건네지 않고, 호출한 쪽이 받는 값은 return이 돌려준 0 하나입니다. 계산 결과를 다른 곳에서 다시 쓰려면 return으로 돌려줘야 합니다.
연습 2: result = add(add(1, 2), 4);에서 result는 몇일까요?
답 보기
안쪽 add(1, 2)가 먼저 3을 돌려주고, 그 3이 바깥 add의 인수가 되어 add(3, 4) = 7입니다. 반환값은 그 자리에 값 하나로 놓인다고 생각하면 됩니다.
다음 편 예고: 매개변수를 바꾸면 호출자 변수도 바뀔까
확장 프롬프트용으로 아래 자체 코드를 미리 실행해 보았습니다. 함수 안에서 a를 100으로 바꿔도, main의 x는 그대로 5입니다. 값이 복사되어 들어갔기 때문입니다. 주소를 넘기는 포인터 전달은 후속편에서 다룹니다.
#include <stdio.h>
void change(int a) { a = 100; printf("change 안: a = %d\n", a); }
int main(void) { int x = 5; change(x); printf("main: x = %d\n", x); return 0; }
change 안: a = 100 main: x = 5
9. 출처
- 교재: 『기초 C언어』 276~279쪽 (CODE 9.7, RESULT, 매개변수와 인수)
- 원본 스타일: LemoLab, Lemo-Opuscar — Living Screencast STYLE.md (코드·문서 MIT)
- 원본 시연 영상: LemoLab, Clawd Moves In (CC BY 4.0) — 이 글에는 링크로만 실었습니다.
- 글꼴: Pretendard, JetBrains Mono (SIL Open Font License)
- 영상·도식·추적기·연습 코드: AI 오토마타 자체 제작
댓글
댓글 쓰기