Menu
Coddy logo textTech

공개 필드와 비공개 필드

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 107개 중 47번째.

Go에서, 구조체(struct) 수준의 **캡슐화(encapsulation)**는 필드 이름의 대소문자에 의해 제어됩니다. 이 간단한 규칙은 구조체가 정의된 패키지 외부에서 필드에 접근할 수 있는지 여부를 결정합니다.

대문자로 시작하는 필드는 내보내기(exported)됩니다. 즉, 어떤 패키지에서도 접근할 수 있습니다. 소문자로 시작하는 필드는 내보내지 않으며(unexported), 동일한 패키지 내에서만 접근할 수 있습니다:

// "user" 패키지 내
type User struct {
    Name     string  // 외부로 노출됨(Exported) - 어디서나 접근 가능
    Email    string  // 외부로 노출됨(Exported) - 어디서나 접근 가능
    password string  // 외부로 노출되지 않음(Unexported) - "user" 패키지 내에서만 접근 가능
    age      int     // 외부로 노출되지 않음(Unexported) - "user" 패키지 내에서만 접근 가능
}

다른 패키지에서 이 구조체를 임포트하여 사용할 때, 내보내기 된(exported) 필드하고만 상호작용할 수 있습니다:

// "main" 패키지 내에서
import "user"

func main() {
    u := user.User{
        Name:  "Alice",      // 정상 작동
        Email: "a@mail.com", // 정상 작동
        // password: "secret", // 컴파일 에러: 알 수 없는 필드
    }
    
    fmt.Println(u.Name)     // 정상 작동
    // fmt.Println(u.password) // 컴파일 에러: 내보내지 않은(unexported) 필드를 참조할 수 없음
}

이 메커니즘은 민감한 데이터와 내부 구현 세부 사항을 보호합니다. password 필드는 패키지 외부에서 직접 읽거나 수정할 수 없으므로, 다른 코드가 사용자가 제공하는 메서드를 사용하도록 강제합니다. 이것은 객체 지향 프로그래밍에서 캡슐화의 핵심 원칙인 데이터 은닉을 달성하기 위한 Go의 접근 방식입니다.

challenge icon

챌린지

쉬움

내보낸(exported) 필드와 내보내지 않은(unexported) 필드를 통해 캡슐화를 보여주는 은행 계좌 시스템을 구축해 보겠습니다. 안전한 공개 정보는 노출하면서 민감한 금융 데이터는 보호하는 패키지를 만들게 됩니다.

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

  • account.go: 적절한 데이터 보호 기능을 갖춘 실제 은행 계좌를 모델링하는 BankAccount 구조체를 main 패키지에 생성합니다:
    • HolderName (내보냄) - 계좌 소유주의 이름으로, 공개적으로 표시해도 안전합니다.
    • AccountType (내보냄) - 계좌 유형 (예: "Savings", "Checking")
    • balance (내보내지 않음) - 보호되어야 하는 실제 잔액
    • pin (내보내지 않음) - 매우 민감한 데이터인 계좌 비밀번호
    소유주 이름, 계좌 유형, 초기 잔액, 비밀번호를 인자로 받아 새로운 BankAccount의 포인터를 반환하는 생성자 함수 NewBankAccount를 추가하세요. 또한 Account: [HolderName] ([AccountType]) 형식을 반환하는 GetPublicInfo() string 메서드를 추가하세요.
  • main.go: 입력에서 계좌 세부 정보를 읽고, 생성자를 사용하여 BankAccount를 생성한 뒤 캡슐화를 시연합니다. 메서드를 사용하여 공개 정보를 출력한 다음, 각 내보낸 필드에 직접 접근하여 별도의 줄에 출력하세요. 내보내지 않은 필드(balancepin)는 보호되므로 생성자를 통해서만 설정할 수 있습니다.

다음 입력이 제공됩니다:

  • 1행: 계좌 소유주 이름
  • 2행: 계좌 유형
  • 3행: 초기 잔액 (float 형식)
  • 4행: PIN 코드

예를 들어, Alice Johnson, Savings, 5000.50, 1234가 주어지면 출력은 다음과 같아야 합니다:

Account: Alice Johnson (Savings)
Holder: Alice Johnson
Type: Savings

잔액과 PIN은 출력에 전혀 나타나지 않는다는 점에 유의하세요. 이들은 구조체 내부에 안전하게 숨겨져 있으며 패키지 내에서만 접근할 수 있습니다. 이것이 바로 캡슐화의 실제 사례입니다. 민감한 데이터는 보호되면서 공개 정보는 접근 가능한 상태로 유지됩니다.

치트 시트

Go에서 캡슐화(encapsulation)는 구조체(struct) 내 필드 이름의 대소문자에 의해 제어됩니다:

  • 대문자로 시작하는 필드는 내보내기(exported) 됩니다 (모든 패키지에서 접근 가능).
  • 소문자로 시작하는 필드는 내보내지 않음(unexported) 처리됩니다 (동일한 패키지 내에서만 접근 가능).
type User struct {
    Name     string  // 내보내기됨 - 어디서나 접근 가능
    Email    string  // 내보내기됨 - 어디서나 접근 가능
    password string  // 내보내지 않음 - 동일 패키지 내에서만 접근 가능
    age      int     // 내보내지 않음 - 동일 패키지 내에서만 접근 가능
}

다른 패키지의 구조체를 사용할 때는 내보내기된 필드에만 접근할 수 있습니다:

import "user"

func main() {
    u := user.User{
        Name:  "Alice",      // 작동함
        Email: "a@mail.com", // 작동함
        // password: "secret", // 컴파일 에러: 알 수 없는 필드
    }
    
    fmt.Println(u.Name)     // 작동함
    // fmt.Println(u.password) // 컴파일 에러: 내보내지 않은 필드를 참조할 수 없음
}

이러한 메커니즘은 민감한 데이터와 내부 구현 세부 사항을 보호하며, 외부 코드에서 데이터에 접근할 때 제공된 메서드를 사용하도록 강제합니다.

직접 해보기

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// 계좌 소유자 이름을 읽습니다
	holderName, _ := reader.ReadString('\n')
	holderName = strings.TrimSpace(holderName)

	// 계좌 유형을 읽습니다
	accountType, _ := reader.ReadString('\n')
	accountType = strings.TrimSpace(accountType)

	// 초기 잔액을 읽습니다
	balanceStr, _ := reader.ReadString('\n')
	balanceStr = strings.TrimSpace(balanceStr)
	balance, _ := strconv.ParseFloat(balanceStr, 64)

	// PIN을 읽습니다
	pinStr, _ := reader.ReadString('\n')
	pin := strings.TrimSpace(pinStr)

	// TODO: 생성자를 사용하여 새로운 BankAccount를 생성하세요
	// account := NewBankAccount(...)

	// TODO: GetPublicInfo() 메서드를 사용하여 공개 정보를 출력하세요

	// TODO: 내보낸(exported) 필드에 직접 접근하여 소유자 이름을 출력하세요
	// fmt.Println("Holder:", ...)

	// TODO: 내보낸(exported) 필드에 직접 접근하여 계좌 유형을 출력하세요
	// fmt.Println("Type:", ...)

	// Note: balance와 pin은 내보내지 않은(unexported) 필드이므로 여기에서 직접 접근할 수 없습니다
	// 이들은 구조체 내에 안전하게 캡슐화되어 있습니다

	_ = balance // balance를 사용할 때 이 줄을 제거하세요
	_ = pin     // pin을 사용할 때 이 줄을 제거하세요
}
quiz icon실력 점검

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

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