세터에서의 유효성 검사
Coddy C 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 61개 중 20번째.
이전 레슨에서 단순히 값을 할당하는 기본적인 세터(setters)를 만들었습니다. 하지만 이는 캡슐화(encapsulation)의 핵심적인 이점을 놓치고 있습니다: 검증 로직을 추가하여 데이터를 보호하는 능력입니다.
절대로 음수가 되어서는 안 되는 Counter를 가정해 봅시다. 캡슐화가 없다면, 누구나 c->value = -50과 같이 작성하여 상태를 손상시킬 수 있습니다. 세터(setter)를 사용하면, 어떤 값이 허용될지 제어할 수 있습니다:
// counter.c
void counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return; // 잘못된 입력을 조용히 거부합니다
}
c->value = new_value;
}이제 음수 값은 단순히 무시됩니다.
성공 또는 실패를 나타내는 상태 코드를 반환할 수도 있습니다:
int counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return 0; // 실패
}
c->value = new_value;
return 1; // 성공
}이 패턴은 호출자에게 작업의 성공 여부를 알려줍니다. 핵심 통찰은 세터(setter)가 단순히 할당만을 위한 것이 아니라, 객체의 상태가 가질 수 있는 값에 대한 규칙을 강제하는 문지기(gatekeepers)라는 점입니다. 이것이 캡슐화의 진정한 힘입니다. 외부 코드가 무엇을 시도하든 상관없이 객체는 스스로의 무결성을 유지합니다.
챌린지
쉬움세터(setter)에서 유효성 검사를 사용하여 데이터를 보호하는 Temperature 모듈을 만들어 보겠습니다. 유효한 범위 내의 값만 허용하는 온도 추적기를 생성하여, 세터가 객체 상태의 게이트키퍼(gatekeeper) 역할을 하는 방법을 실습합니다.
세 개의 파일을 생성해야 합니다:
temperature.h: 불투명 포인터(opaque pointer) 패턴을 사용하는 공개 인터페이스입니다. 전방 선언(forward declaration)만 사용하여Temperature타입을 선언하세요. 다음 함수들을 선언합니다:create_temperature— 초기 온도를 정수로 받아 Temperature 포인터를 반환합니다.free_temperature— 할당된 메모리를 해제합니다.temp_get_degrees— 현재 온도 값을 반환하는 게터(getter)입니다.temp_set_degrees—int를 반환하는 세터(1은 성공, 0은 실패)입니다.
TEMPERATURE_H심볼을 사용하여 인클루드 가드(include guards)를 적용하세요.temperature.c: 숨겨진int degrees멤버를 가진 실제struct Temperature를 정의합니다. 모든 함수를 구현하세요. 핵심은 세터입니다. -50에서 150 사이(경계값 포함)의 값만 허용해야 합니다. 값이 이 범위를 벗어나면 0을 반환하고 온도를 변경하지 않은 상태로 둡니다. 유효한 경우 값을 업데이트하고 1을 반환합니다.main.c: 유효한 온도와 유효하지 않은 온도를 모두 설정해 보면서, 유효하지 않은 값은 거부되고 유효한 값은 수락되는 것을 보여줌으로써 유효성 검사를 시연합니다.
세 개의 입력을 받게 됩니다: 초기 온도, 설정할 유효한 온도(범위 내), 시도할 유효하지 않은 온도(범위 밖).
메인 파일에서 초기 값으로 Temperature를 생성하고 출력하세요. 그런 다음 유효하지 않은 온도를 설정해 봅니다. 거부되어야 하므로 결과를 출력하고 값이 변경되지 않았음을 보여줍니다. 마지막으로 유효한 온도를 설정하고 성공 결과를 출력한 뒤 업데이트된 값을 보여줍니다. 메모리를 해제하고 정리가 완료되었음을 확인합니다.
출력은 다음 형식으로 하세요:
Initial: {degrees}
Set {invalid}: {0 or 1}
After invalid: {degrees}
Set {valid}: {0 or 1}
After valid: {degrees}
Freed예를 들어, 입력이 25, 100, 200인 경우 출력은 다음과 같습니다:
Initial: 25
Set 200: 0
After invalid: 25
Set 100: 1
After valid: 100
Freed이것은 캡슐화의 진정한 힘을 보여줍니다. 세터는 유효한 온도를 구성하는 규칙을 강제하여, 외부 코드에서 어떤 값을 할당하려고 시도하든 객체의 무결성을 보호합니다.
치트 시트
세터(Setter)는 데이터 무결성을 보호하기 위해 유효성 검사 로직을 포함할 수 있습니다. 단순히 값을 할당하는 대신, 유효한 객체 상태에 대한 규칙을 강제하는 게이트키퍼(gatekeepers) 역할을 합니다.
기본적인 유효성 검사 예시 - 잘못된 입력을 조용히 거부하기:
void counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return; // Reject invalid input
}
c->value = new_value;
}성공 또는 실패를 나타내기 위해 상태 코드 반환하기:
int counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return 0; // Failure
}
c->value = new_value;
return 1; // Success
}이 패턴을 통해 호출자는 작업의 성공 여부를 확인할 수 있으며, 외부 코드의 시도와 상관없이 객체가 스스로의 무결성을 유지할 수 있게 합니다.
직접 해보기
#include <stdio.h>
#include "temperature.h"
int main() {
// 입력 읽기
int initial, valid_temp, invalid_temp;
scanf("%d", &initial);
scanf("%d", &valid_temp);
scanf("%d", &invalid_temp);
// TODO: initial 값으로 Temperature 생성
// TODO: 초기 온도 출력
// 형식: "Initial: {degrees}"
// TODO: 유효하지 않은 온도(invalid_temp) 설정 시도
// 결과를 출력하고 값이 변경되지 않았음을 확인
// 형식: "Set {invalid}: {0 or 1}"
// 형식: "After invalid: {degrees}"
// TODO: 유효한 온도(valid_temp) 설정
// 성공 결과를 출력하고 업데이트된 값 확인
// 형식: "Set {valid}: {0 or 1}"
// 형식: "After valid: {degrees}"
// TODO: 메모리를 해제하고 "Freed" 출력
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.