Menu
Coddy logo textTech

데이터 은닉 구현

Coddy C# 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 70개 중 33번째.

데이터 은닉은 단순히 private 필드를 사용하는 것 그 이상을 의미합니다. 이는 내부 구현 세부 사항이 외부 코드에 완전히 보이지 않도록 클래스를 설계하고, 깔끔한 공개 인터페이스를 통해 필요한 것만 노출하는 것을 의미합니다.

사용자의 비밀번호를 추적하는 클래스를 생각해 봅시다. 원본 비밀번호에 그 누구도 접근하는 것을 원하지 않을 것입니다 - 심지어 읽는 것조차 말이죠:

public class UserAccount
{
    private string passwordHash;
    
    public void SetPassword(string password)
    {
        passwordHash = HashPassword(password);
    }
    
    public bool VerifyPassword(string password)
    {
        return HashPassword(password) == passwordHash;
    }
    
    private string HashPassword(string password)
    {
        return password.GetHashCode().ToString();
    }
}

비밀번호나 해시 자체를 조회할 수 있는 방법이 없다는 점에 유의하세요. 외부 코드는 비밀번호를 설정하거나 확인만 할 수 있으며, 내부 저장 메커니즘은 완전히 숨겨져 있습니다. HashPassword 메서드 또한 클래스 사용 방식에 영향을 주지 않고 변경될 수 있는 구현 세부 사항이므로 private으로 설정되어 있습니다.

이 접근 방식은 클래스가 오용되는 것을 방지하고 나중에 내부 구현을 변경할 수 있는 자유를 제공합니다. 다른 해싱 알고리즘을 사용하기로 결정하더라도, 비밀번호가 저장되는 방식에 의존하는 코드가 없으므로 외부 코드가 중단되지 않습니다.

challenge icon

챌린지

쉬움

진정한 데이터 은닉을 보여주는 보안 지갑 시스템을 구축해 봅시다. 잔액이 직접적인 액세스로부터 완전히 보호되는 디지털 지갑을 만들 것입니다. 외부 코드는 입금, 출금 및 거래 가능 여부 확인만 할 수 있으며, 실제 잔액을 직접 보거나 조작할 수 없습니다.

코드는 두 개의 파일로 구성됩니다:

  • Wallet.cs: Finance 네임스페이스 안에 잔액을 완전히 숨기는 Wallet 클래스를 생성합니다. 지갑은 다음을 포함해야 합니다:
    • 잔액을 저장하는 private 필드 (decimal)
    • 잔액을 "$123.45"와 같은 통화 문자열로 포맷하여 반환하는 private 메서드 FormatBalance() - 이것은 외부에 노출되지 않아야 하는 내부 헬퍼 메서드입니다.
    • 금액이 양수인 경우에만 잔액에 추가하고, 성공하면 true, 그렇지 않으면 false를 반환하는 public 메서드 Deposit(decimal amount)
    • 금액이 양수이고 현재 잔액을 초과하지 않는 경우에만 잔액에서 차감하고, 성공하면 true, 그렇지 않으면 false를 반환하는 public 메서드 Withdraw(decimal amount)
    • 잔액이 금액보다 크거나 같으면 true를, 그렇지 않으면 false를 반환하는 public 메서드 CanAfford(decimal amount)
    • 내부적으로 private FormatBalance() 메서드를 사용하고 "Current balance: {formatted balance}"를 반환하는 public 메서드 GetStatement()
    잔액을 직접 읽거나 설정할 수 있는 방법이 없다는 점에 유의하세요. 제어된 메서드를 통해서만 상호 작용할 수 있습니다!
  • Program.cs: 메인 파일에서 Wallet을 생성하고 입력 값을 사용하여 일련의 거래를 수행합니다. 지갑이 public 인터페이스를 통해 유용한 기능을 제공하면서도 내부 상태를 어떻게 보호하는지 보여주세요.

세 가지 입력을 받게 됩니다:

  • 초기 입금액 (decimal)
  • 시도할 출금액 (decimal)
  • 구매 가능 여부를 확인할 금액 (decimal)

출력은 다음 형식으로 인쇄하십시오:

Deposit {amount}: {True/False}
{GetStatement() result}
Withdraw {amount}: {True/False}
{GetStatement() result}
Can afford {amount}: {True/False}

예를 들어, 입력이 100.50, 30.25, 80.00인 경우 출력은 다음과 같아야 합니다:

Deposit 100.50: True
Current balance: $100.50
Withdraw 30.25: True
Current balance: $70.25
Can afford 80.00: False

여기서 핵심 통찰은 외부 코드가 balance 필드를 직접 건드리지 않는다는 것입니다. 포맷된 잔액 문자열조차 내부적으로 private 헬퍼를 사용하는 public 메서드를 통해 제공됩니다. 이것이 데이터 은닉입니다. 구현 세부 사항은 완전히 보이지 않으며, 지갑을 사용하는 코드를 손상시키지 않고도 잔액이 저장되거나 포맷되는 방식을 자유롭게 변경할 수 있습니다!

치트 시트

데이터 은닉은 내부 구현 세부 사항이 외부 코드에 완전히 보이지 않도록 클래스를 설계하고, 깔끔한 공개 인터페이스를 통해 필요한 것만 노출하는 것을 의미합니다.

민감한 데이터를 저장하기 위해 private 필드를 사용하고, public 메서드를 통해 제어된 액세스를 제공하세요:

public class UserAccount
{
    private string passwordHash;
    
    public void SetPassword(string password)
    {
        passwordHash = HashPassword(password);
    }
    
    public bool VerifyPassword(string password)
    {
        return HashPassword(password) == passwordHash;
    }
    
    private string HashPassword(string password)
    {
        return password.GetHashCode().ToString();
    }
}

주요 원칙:

  • 내부 데이터에 대한 직접적인 접근 금지 (민감한 필드에 대한 getter 없음)
  • 구현 세부 사항을 위한 private 헬퍼 메서드
  • public 메서드는 제어된 작업만 제공
  • 내부 저장 메커니즘은 완전히 숨겨짐

이는 클래스를 오용으로부터 보호하고 외부 코드를 손상시키지 않으면서 내부 구현을 변경할 수 있게 해줍니다.

직접 해보기

using System;
using Finance;

class Program
{
    public static void Main(string[] args)
    {
        // 입력 값 읽기
        decimal depositAmount = Convert.ToDecimal(Console.ReadLine());
        decimal withdrawAmount = Convert.ToDecimal(Console.ReadLine());
        decimal checkAmount = Convert.ToDecimal(Console.ReadLine());

        // TODO: Wallet 인스턴스 생성
        
        // TODO: 입금을 수행하고 다음 형식으로 결과 출력: "Deposit {amount}: {True/False}"
        
        // TODO: GetStatement()를 사용하여 내역 출력
        
        // TODO: 출금을 수행하고 다음 형식으로 결과 출력: "Withdraw {amount}: {True/False}"
        
        // TODO: GetStatement()를 사용하여 내역 출력
        
        // TODO: 구매 가능 여부를 확인하고 다음 형식으로 결과 출력: "Can afford {amount}: {True/False}"
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨