동료의 코드를 리뷰하다 보면, 온갖 소스 파일에 extern으로 얽혀있는 전역 변수 더미를 볼 때가 있습니다. 솔직히 말해서, 그런 코드는 나중에 기능 하나 추가하려면 전체를 다 뒤엎어야 하죠. 😭 저도 짬이 안 찼을 때는 구현에만 급급해서 "돌아가면 장땡이지!"라고 생각했습니다. 하지만 진짜 실력은 '남이 보기 편하고 고치기 쉬운 코드'에서 나옵니다. 오늘은 그 비결인 구조체와 함수 포인터 활용 팁을 소개할게요.
TIP 1. 전역 변수 대신 '핸들(Handle)' 구조체를 쓰세요 📍
센서 데이터를 읽을 때 temp_value라는 전역 변수를 쓰지 마세요. 대신 센서의 상태와 데이터를 모두 포함하는 구조체를 만들고, 함수의 인자로 그 구조체의 포인터(핸들)를 넘겨주세요. 이렇게 하면 하나의 소스 코드로 여러 개의 센서를 제어하는 것도 식은 죽 먹기입니다.
- 전역 변수는 최소화한다.
- 모든 함수는 제어할 대상의 포인터를 인자로 받는다 (예:
Sensor_Read(&h_sensor1)).
TIP 2. 함수 포인터로 '콜백(Callback)' 구현하기 🔔
펌웨어에서 인터럽트 처리는 매우 중요하죠. 하지만 인터럽트 핸들러 안에 비즈니스 로직을 직접 넣으면 코드가 엉망이 됩니다. 이때 구조체 안에 등록(Registration)용 함수 포인터를 만드세요. 특정 이벤트가 발생했을 때 미리 등록된 함수를 호출하게 하면, 모듈 간의 결합도가 획기적으로 낮아집니다.
Before vs After 설계 비교
- ❌ Before: UART 인터럽트 함수 안에서 직접 패킷을 분석하고 메인 로직 변수를 수정함.
- ✅ After: UART 드라이버 구조체에
on_rx_complete포인터를 두고, 메인에서 원하는 함수를 연결함.
TIP 3. 주의해야 할 '흔한 실수' ⚠️
함수 포인터가 강력하긴 하지만, 남용하면 디버깅이 지옥이 될 수 있습니다. 호출 스택을 따라가기 힘들어지기 때문이죠. 따라서 다음과 같은 원칙을 지키는 것이 좋습니다.
1. 함수 포인터 호출 전에는 반드시 NULL 체크를 하세요. (안 하면 하드폴트 납니다!)
2. 너무 깊은 단계의 함수 포인터 중첩은 피하세요. 가독성이 안드로메다로 갑니다.
✅ 실무 설계 3계명
if(ptr != NULL)를 확인하라.자주 묻는 질문 ❓
기술적인 정답은 없지만, 유지보수하기 좋은 코드가 결국 이기는 코드입니다. 오늘 배운 팁들을 여러분의 프로젝트에 하나씩 적용해 보세요. 분명 코드 리뷰 때 선배들의 눈빛이 달라질 겁니다! 😉

