WIL 0917~1001

김우진·2026년 10월 1일

크래프톤 정글

목록 보기
22/26

1. 학습 진행 상황

이번 C언어 주차에는 CS:APP를 읽으며 프로그램의 실행 방식과 메모리 구조를 공부하고, 디버깅 랩을 통해 실제 코드에서 오류의 원인을 찾아보았다.

디버깅 랩은 전체 20문제 중 10번까지 살펴봤고, CS:APP는 부동소수점 부분을 제외한 학습 범위를 읽었다. 다만 연습문제까지 충분히 풀지는 못했고, 읽은 내용을 직접 적용하는 데에는 아직 부족함을 느꼈다.

이번 기간에는 C언어 지식뿐 아니라, 코드를 읽는 순서와 공부 시간을 사용하는 방법, 그리고 혼자 하는 공부를 지속하는 방법에 대해서도 고민하게 됐다.

2. 디버깅: 오류가 발생한 위치와 원인이 생긴 위치는 다르다

프로그램의 전체 흐름부터 파악하기

디버깅 랩에서 가장 오래 붙잡고 있었던 것은 1번 문제였다. 처음에는 오류를 찾기 전에 프로그램이 무엇을 하는지 파악하는 것부터 어려웠다. 함수 포인터 문법도 낯설었고, 여러 함수가 연결된 실행 흐름도 한눈에 들어오지 않았다. GPT의 도움을 받아 코드를 해석하는 순서부터 차근차근 익혔다.

처음부터 파일 전체를 이해하려 하기보다 main()에서 프로그램의 큰 흐름을 먼저 잡는 것이 도움이 됐다.

  1. 위젯 4개를 생성하고 화면에 등록한다.
  2. 첫 번째 화면을 그린다.
  3. 닫기 이벤트를 전달한다.
  4. 상태 메시지를 생성한다.
  5. 두 번째 화면을 그린다.
  6. 메모리를 정리한다.

이 흐름을 정리하니 정상적인 결과도 예상할 수 있었다. 처음에는 위젯 4개가 나오고, 닫기 이벤트 이후에는 다이얼로그를 제외한 3개가 나와야 했다.

정상 동작을 먼저 생각하는 것이 오류를 이해하는 출발점이라는 것을 배웠다.

GDB로 오류 위치 확인하기

GDB에서는 run으로 실행하고, bt로 멈춘 함수와 호출 경로를 확인했다. 오류는 두 번째 화면을 그리는 과정에서 발생했고, print i로 세 번째 위젯인 다이얼로그를 처리하다가 실패했다는 것을 확인했다.

이때 bt가 과거의 전체 실행 기록을 보여주는 것이 아니라, 현재 시점의 함수 호출 관계를 보여준다는 것도 알게 됐다. 해제 함수에 브레이크포인트를 걸고 다시 실행하니, 멈춘 위치에 따라 호출 경로도 달라졌다.

오류 위치에서 원인으로 거슬러 올라가기

이후에는 “첫 번째에는 잘 그렸는데, 두 번째 그리기 전까지 무엇이 달라졌을까?”라는 질문으로 두 호출 사이를 추적했다.

다이얼로그는 닫기 이벤트를 처리하면서 자신을 해제했지만, 화면의 배열에는 해제된 주소가 그대로 남아 있었다. 이후 상태 메시지가 그 메모리 공간을 재사용했고, 화면을 다시 그릴 때는 그 공간을 여전히 위젯으로 취급하면서 오류가 발생했다.

수정 방향은 다이얼로그에서 바로 해제하는 대신 닫힘 표시를 남기고, 화면 쪽에서 해제와 배열 정리를 함께 처리하는 것으로 잡았다. 비워진 칸은 NULL로 바꾸고, 그리기와 이벤트 처리에서 건너뛰도록 하는 방식이다. 다만 수정 방향을 정리한 단계까지였고, 수정 후 실행 결과까지 검증하지는 못했다.

이 과정에서 가장 크게 배운 것은 “여기까지 프로그램이 죽지 않았다”는 사실이 “데이터 상태가 정상이다”를 의미하지는 않는다는 것이다. 잘못된 상태는 앞에서 만들어지고, 오류는 나중에 드러날 수 있었다.

3. C언어: 주소와 메모리의 수명을 구분하기

함수 주소를 저장하는 것과 호출하는 것은 다르다

함수 포인터는 선언 형태만 볼 때보다 실제 연결과 호출을 따라갈 때 이해하기 쉬웠다.

w->vtbl->render(w)도 위젯에 함수 주소가 담긴 표를 연결하고, 그 표에서 render에 해당하는 함수를 호출하는 과정으로 나누어 보니 이해할 수 있었다.

특히 함수의 주소를 저장하는 것과 함수를 실행하는 것은 다르다는 점이 명확해졌다. 표에 render와 on_event가 함께 있어도 두 함수가 자동으로 차례대로 실행되는 것은 아니다. 어떤 항목을 호출하느냐에 따라 실행되는 함수가 달라진다.

주소가 남아 있어도 메모리가 유효한 것은 아니다

메모리 관리에서도 비슷한 구분이 필요했다. 포인터에 주소가 남아 있다고 해서 그 주소의 메모리를 계속 사용할 수 있는 것은 아니다. free() 이후에는 다른 포인터에 같은 주소가 남아 있어도 더 이상 유효한 접근이 아니다.

realloc() 역시 기존 내용이 유지된다는 사실과 주소가 유지된다는 사실을 구분해야 했다. 주소가 그대로일 수도 있고 다른 위치로 옮겨질 수도 있으므로, 반환된 주소를 기준으로 이후 접근을 생각해야 한다.

C언어는 메모리를 직접 다룰 수 있는 만큼, 그 메모리가 언제까지 유효한지와 누가 정리할지도 직접 신경 써야 하는 언어라는 것을 느꼈다. “큰 힘에는 큰 책임이 따른다”는 말이 잘 어울렸다.

4. 공부 방식: 처음부터 완벽하게 이해하려고 하지 않기

학습 속도와 주어진 시간을 잘못 예상했다

이번 기간에 가장 부족했던 부분은 내 학습 속도를 과대평가하고, 주어진 시간을 너무 여유롭게 생각한 것이었다.

2주라는 시간이 있으니 할 일이 많아도 충분히 해낼 수 있을 것 같았다. 하지만 1번 디버깅 문제와 CS:APP 초반 내용을 이해하는 데 예상보다 훨씬 많은 시간이 들었다.

특히 책을 처음 읽을 때부터 모든 내용을 완전히 이해하려고 했다. 꼼꼼하게 읽는 것 자체는 도움이 됐지만, 한 부분에 오래 머물면서 뒤의 내용을 공부할 시간이 부족해졌다. 전체 범위를 충분히 보지 못한 상태에서 일부 내용만 깊게 파고든 셈이었다.

전체를 훑은 뒤 부족한 부분을 다시 보기

이번에 해보니 GPT에 해당 절의 핵심 설명을 먼저 요청하고, 그 설명으로 큰 흐름을 잡은 뒤 책을 읽는 방식이 비교적 잘 맞았다. 이후 이해되지 않는 부분을 다시 찾아보면 처음부터 모든 문장을 붙잡고 읽을 때보다 수월했다.

앞으로는 다음 순서로 공부해 보려고 한다.

  1. 핵심 설명으로 전체 흐름을 잡는다.
  2. 책에서 해당 내용을 읽는다.
  3. 이해되지 않는 부분을 따로 표시한다.
  4. 짧게 설명하거나 문제에 적용해 본다.
  5. 부족한 부분을 다시 깊게 공부한다.

읽었다는 것만으로 이해했다고 판단하지 않고, 설명과 문제 풀이로 확인하는 과정이 필요하다고 느꼈다.

5. 팀 학습: 효율뿐 아니라 지속할 수 있는지도 중요하다

함께 공부하는 방식을 시도했다

조가 바뀌면서 고등학생 팀원들과도 함께하게 됐는데, 모두 내향적인 편이라 처음에는 어색했다.

9월 18일에는 약 5쪽씩 분량을 나누고 2시간 동안 공부한 뒤, 만나서 이야기하는 방식을 해보기로 했다. 남는 시간은 각자 책을 더 읽거나 다른 공부에 사용하는 방식이었다. 처음에는 두 팀이 함께할까 생각했지만, 우선 우리 팀끼리 진행했다.

이해한 내용을 설명하는 것도 별도의 준비가 필요했다

한 번 해보니 내가 이해한 내용을 다른 사람에게 설명하는 일이 생각보다 어려웠다. 설명할 때 멋쩍기도 했고, 머릿속에서는 알 것 같던 내용도 말로 꺼내려니 정리가 잘되지 않았다. 설명을 위해서는 별도의 준비가 필요하다는 것을 느꼈다.

동시에 이 방식이 얼마나 도움이 되는지 회의감도 들었다. 내가 맡은 부분을 설명해야 하니 공부에 강제성이 생기는 것은 장점이었다. 하지만 다른 사람의 설명을 듣고 낯선 내용을 바로 이해하기는 쉽지 않았다. 준비 시간이 짧고, 우리도 내용을 배우는 중이기 때문이다.

함께 공부하면 덜 지치고 덜 지루했다

그럼에도 함께 공부하는 시간에는 다른 장점이 있었다. 혼자 공부할 때보다 시간이 빨리 가고, 덜 지루하고, 덜 지쳤다.

공부가 항상 가장 효율적인 방식으로만 진행될 필요는 없겠다는 생각이 들었다. 계속 공부할 수 있게 해주는 방식이라는 점에서도 팀 학습은 의미가 있었다.

앞으로는 각자 맡은 내용을 길게 설명하기보다, 핵심 개념과 막혔던 부분을 중심으로 이야기해 보고 싶다. 내용을 전달하면서 내가 무엇을 이해했고 무엇을 아직 설명하지 못하는지도 확인할 수 있을 것 같다.

6. 다음 학습에서 보완할 점

하루 단위로 구체적인 계획 세우기

다음에는 하루에 읽을 범위와 풀 문제를 더 구체적으로 정하려고 한다. “오늘은 CS:APP를 공부한다”처럼 넓게 잡기보다, 어디까지 읽고 무엇을 확인할지 정해두는 것이 필요하다.

한 부분을 오래 붙잡고 있다면 우선 넘어가고, 다시 볼 내용을 남겨두는 방식도 시도해 보고 싶다. 처음부터 완벽하게 이해하려는 욕심 때문에 전체 진도가 밀리지 않도록 해야겠다.

집중과 회복을 함께 생각하기

초반에는 어느 정도 집중이 됐지만, 시간이 지날수록 혼자 하는 공부가 지겹게 느껴지고 집중력도 떨어졌다. 추석 때 쉬고 돌아오니 훨씬 나아졌지만, 앞으로도 같은 문제가 반복될 수 있겠다는 걱정은 남았다.

이번 경험을 통해 계획에는 공부할 분량뿐 아니라, 집중을 유지하고 회복할 방법도 포함돼야 한다고 느꼈다. 혼자 공부하는 시간과 팀원들과 함께하는 시간을 적절히 섞으며, 덜 지치고 오래 이어갈 수 있는 방식을 찾아보고 싶다.

이번 주차를 통해 공부의 기준을 조금 바꾸게 됐다. 처음부터 모든 것을 완벽하게 이해하는 것보다, 전체 흐름을 잡고 직접 확인하며 부족한 부분을 채워가는 것이 지금 나에게 더 필요한 방식이었다.

0개의 댓글