Python 에서 __init__, __str__, __repr__ 메서드 사용 방법

PythonBeginner
지금 연습하기

소개

Python 의 객체 지향 프로그래밍 (OOP) 기능은 표현력 있고 사용자 정의된 객체를 생성하기 위한 강력한 도구를 제공합니다. 이 중, 특수 메서드 __init__, __str__, 그리고 __repr__은 Python 객체의 동작과 표현을 정의하는 데 중요한 역할을 합니다.

이 튜토리얼에서는 이러한 특수 메서드를 살펴보고, 그 목적을 이해하며, Python 클래스에서 효과적으로 구현하는 방법을 배웁니다. 이 랩을 마치면, 더욱 직관적이고 사용자 친화적인 Python 객체를 만들 수 있게 될 것입니다.

__init__ 메서드를 사용하여 클래스 생성하기

우리가 살펴볼 첫 번째 특수 메서드는 객체가 생성될 때 호출되는 __init__입니다. 이 메서드를 사용하면 객체의 속성을 초기화할 수 있습니다.

__init__ 메서드 이해하기

생성자 (constructor) 라고도 알려진 __init__ 메서드는 클래스의 새 인스턴스를 생성할 때 자동으로 호출됩니다. 이 메서드의 주요 목적은 속성에 값을 할당하여 객체의 초기 상태를 설정하는 것입니다.

__init__ 메서드를 사용하여 간단한 Python 클래스를 생성하는 것으로 시작해 보겠습니다.

  1. LabEx 환경에서 터미널을 엽니다.

  2. 프로젝트 디렉토리로 이동합니다.

    cd ~/project
  3. 코드 편집기를 사용하여 person.py라는 새 Python 파일을 생성합니다.

  4. 편집기에서 다음 코드를 person.py에 추가합니다.

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    ## Create a Person object
    person1 = Person("Alice", 30)
    
    ## Access the attributes
    print(f"Name: {person1.name}")
    print(f"Age: {person1.age}")
  5. 파일을 저장합니다.

  6. Python 스크립트를 실행합니다.

    python3 person.py

다음과 같은 출력을 볼 수 있습니다.

Name: Alice
Age: 30

__init__ 메서드 설명

위의 코드에서:

  • nameage의 세 가지 매개변수를 사용하는 __init__ 메서드가 있는 Person 클래스를 정의했습니다.
  • self 매개변수는 생성 중인 인스턴스를 참조하며, 객체가 생성될 때 자동으로 전달됩니다.
  • __init__ 메서드 내에서 self.nameself.age를 사용하여 nameage의 값을 객체의 속성에 할당합니다.
  • person1 = Person("Alice", 30)으로 새 Person 객체를 생성하면 __init__ 메서드가 자동으로 호출됩니다.
  • 그런 다음 점 표기법을 사용하여 속성에 액세스할 수 있습니다: person1.nameperson1.age.

더 많은 기능 추가하기

현재 연도와 사람의 나이를 기준으로 출생 연도를 계산하는 메서드를 추가하여 Person 클래스를 향상시켜 보겠습니다.

  1. 편집기에서 person.py를 엽니다.

  2. 출생 연도를 계산하는 메서드를 포함하도록 코드를 업데이트합니다.

    import datetime
    
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def birth_year(self):
            current_year = datetime.datetime.now().year
            return current_year - self.age
    
    ## Create a Person object
    person1 = Person("Alice", 30)
    
    ## Access the attributes and call the method
    print(f"Name: {person1.name}")
    print(f"Age: {person1.age}")
    print(f"Birth Year: {person1.birth_year()}")
  3. 파일을 저장합니다.

  4. Python 스크립트를 실행합니다.

    python3 person.py

이제 출력에 계산된 출생 연도가 포함되어야 합니다.

Name: Alice
Age: 30
Birth Year: 1993

(실제 출생 연도는 스크립트를 실행하는 현재 연도에 따라 달라집니다.)

이제 객체 속성을 초기화하기 위해 __init__ 메서드를 사용하고 해당 속성을 기반으로 계산을 수행하는 메서드를 추가하여 Python 클래스를 만들었습니다.

__str__ 메서드 구현하기

이제 __init__ 메서드를 사용하여 클래스를 만드는 방법을 이해했으므로, __str__이라는 또 다른 특수 메서드를 살펴보겠습니다. 이 메서드를 사용하면 객체를 문자열로 표현하는 방법을 정의할 수 있습니다.

__str__ 메서드 이해하기

__str__ 메서드는 객체에 대해 str() 함수를 사용하거나 print() 함수를 사용하여 객체를 인쇄할 때 호출됩니다. 이 메서드는 객체의 사람이 읽을 수 있는 문자열 표현을 반환해야 합니다.

__str__ 메서드를 포함하도록 Person 클래스를 업데이트해 보겠습니다.

  1. 편집기에서 person.py를 엽니다.

  2. __str__ 메서드를 포함하도록 코드를 업데이트합니다.

    import datetime
    
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        def birth_year(self):
            current_year = datetime.datetime.now().year
            return current_year - self.age
    
        def __str__(self):
            return f"{self.name}, {self.age} years old"
    
    ## Create a Person object
    person1 = Person("Alice", 30)
    
    ## Access the attributes and call the method
    print(f"Name: {person1.name}")
    print(f"Age: {person1.age}")
    print(f"Birth Year: {person1.birth_year()}")
    
    ## Use the __str__ method implicitly
    print("\nString representation of the object:")
    print(person1)
    
    ## Use the __str__ method explicitly
    print("\nExplicit string conversion:")
    print(str(person1))
  3. 파일을 저장합니다.

  4. Python 스크립트를 실행합니다.

    python3 person.py

다음과 유사한 출력을 볼 수 있습니다.

Name: Alice
Age: 30
Birth Year: 1993

String representation of the object:
Alice, 30 years old

Explicit string conversion:
Alice, 30 years old

__str__의 작동 방식

위의 코드에서:

  • 사람의 이름과 나이가 포함된 형식화된 문자열을 반환하는 __str__ 메서드를 정의했습니다.
  • print(person1)을 호출하면 Python 은 표시할 내용을 결정하기 위해 자동으로 __str__ 메서드를 호출합니다.
  • str(person1)을 사용하여 객체를 문자열로 명시적으로 변환할 수도 있으며, 이 또한 __str__ 메서드를 호출합니다.

__str__이 없으면 어떻게 될까요?

__str__ 메서드의 중요성을 이해하기 위해, 이 메서드를 정의하지 않으면 어떻게 되는지 살펴보겠습니다.

  1. without_str.py라는 새 파일을 생성합니다.

  2. 다음 코드를 추가합니다.

    class SimpleClass:
        def __init__(self, value):
            self.value = value
    
    ## Create an object
    obj = SimpleClass(42)
    
    ## Print the object
    print(obj)
  3. 파일을 저장합니다.

  4. 스크립트를 실행합니다.

    python3 without_str.py

다음과 같은 출력을 볼 수 있습니다.

<__main__.SimpleClass object at 0x7f2d8c3e9d90>

출력이 그다지 유익하지 않습니다. 클래스 이름과 객체의 메모리 주소를 표시하지만, 내용은 표시하지 않습니다. 이것이 객체를 더 사용자 친화적으로 만들기 위해 적절한 __str__ 메서드를 구현하는 것이 중요한 이유입니다.

실습

__str__ 메서드가 있는 Book이라는 새 클래스를 만들어 보겠습니다.

  1. book.py라는 새 파일을 생성합니다.

  2. 다음 코드를 추가합니다.

    class Book:
        def __init__(self, title, author, pages):
            self.title = title
            self.author = author
            self.pages = pages
    
        def __str__(self):
            return f'"{self.title}" by {self.author} ({self.pages} pages)'
    
    ## Create book objects
    book1 = Book("The Great Gatsby", "F. Scott Fitzgerald", 180)
    book2 = Book("To Kill a Mockingbird", "Harper Lee", 281)
    
    ## Print the books
    print(book1)
    print(book2)
  3. 파일을 저장합니다.

  4. 스크립트를 실행합니다.

    python3 book.py

출력은 다음과 같아야 합니다.

"The Great Gatsby" by F. Scott Fitzgerald (180 pages)
"To Kill a Mockingbird" by Harper Lee (281 pages)

이제 __str__ 메서드를 사용하여 객체의 사람이 읽을 수 있는 문자열 표현을 만드는 방법을 이해했습니다.

__repr__ 메서드 구현하기

__str__ 외에도 Python 은 문자열 표현을 위한 또 다른 특수 메서드인 __repr__을 제공합니다. __str__이 사람이 읽을 수 있는 표현을 제공하기 위한 것이라면, __repr__은 가능한 경우 객체를 다시 생성하는 데 사용할 수 있는 객체의 모호하지 않은 표현을 제공하기 위한 것입니다.

__repr__ 메서드 이해하기

__repr__ 메서드는 객체에 대해 repr() 함수를 사용하거나 대화형 세션에서 객체를 표시할 때 호출됩니다. 이 메서드는 eval()에 전달될 때 (가능한 경우) 동등한 객체를 생성하는 문자열을 반환해야 합니다.

__repr__ 메서드를 포함하도록 Book 클래스를 업데이트해 보겠습니다.

  1. 편집기에서 book.py를 엽니다.

  2. __repr__ 메서드를 포함하도록 코드를 업데이트합니다.

    class Book:
        def __init__(self, title, author, pages):
            self.title = title
            self.author = author
            self.pages = pages
    
        def __str__(self):
            return f'"{self.title}" by {self.author} ({self.pages} pages)'
    
        def __repr__(self):
            return f'Book("{self.title}", "{self.author}", {self.pages})'
    
    ## Create book objects
    book1 = Book("The Great Gatsby", "F. Scott Fitzgerald", 180)
    book2 = Book("To Kill a Mockingbird", "Harper Lee", 281)
    
    ## Print the books (uses __str__)
    print("String representation (using __str__):")
    print(book1)
    print(book2)
    
    ## Get the representation (uses __repr__)
    print("\nRepresentation (using __repr__):")
    print(repr(book1))
    print(repr(book2))
  3. 파일을 저장합니다.

  4. 스크립트를 실행합니다.

    python3 book.py

다음과 같은 출력을 볼 수 있습니다.

String representation (using __str__):
"The Great Gatsby" by F. Scott Fitzgerald (180 pages)
"To Kill a Mockingbird" by Harper Lee (281 pages)

Representation (using __repr__):
Book("The Great Gatsby", "F. Scott Fitzgerald", 180)
Book("To Kill a Mockingbird", "Harper Lee", 281)

__str____repr__의 차이점

__str____repr__의 주요 차이점은 다음과 같습니다.

  • __str__은 사람이 읽을 수 있는 출력을 위한 것이고, __repr__은 개발자 및 디버깅을 위한 것입니다.
  • __str__이 정의되지 않았지만 __repr__이 정의된 경우, Python 은 str() 또는 print()에 대한 대체로 __repr__을 사용합니다.
  • __repr__은 이상적으로 eval()에 전달될 때 객체를 다시 생성할 수 있는 문자열을 반환해야 하지만, 이것이 항상 가능하거나 필요한 것은 아닙니다.

__repr__과 함께 eval() 함수 사용하기

올바르게 구현되면 __repr__에서 반환된 문자열을 eval()과 함께 사용하여 객체를 다시 생성할 수 있습니다. 이를 실제로 살펴보겠습니다.

  1. repr_eval.py라는 새 파일을 생성합니다.

  2. 다음 코드를 추가합니다.

    class Point:
        def __init__(self, x, y):
            self.x = x
            self.y = y
    
        def __str__(self):
            return f"Point at ({self.x}, {self.y})"
    
        def __repr__(self):
            return f"Point({self.x}, {self.y})"
    
    ## Create a point
    p1 = Point(3, 4)
    
    ## Get the repr string
    repr_str = repr(p1)
    print(f"Representation: {repr_str}")
    
    ## Use eval to recreate the object
    p2 = eval(repr_str)
    print(f"Recreated object: {p2}")
    
    ## Verify they have the same values
    print(f"p1.x = {p1.x}, p1.y = {p1.y}")
    print(f"p2.x = {p2.x}, p2.y = {p2.y}")
  3. 파일을 저장합니다.

  4. 스크립트를 실행합니다.

    python3 repr_eval.py

다음과 같은 출력을 볼 수 있습니다.

Representation: Point(3, 4)
Recreated object: Point at (3, 4)
p1.x = 3, p1.y = 4
p2.x = 3, p2.y = 4

이것은 __repr__에서 반환된 문자열과 eval() 함수를 사용하여 원래 객체를 다시 생성할 수 있음을 보여줍니다.

각 메서드를 언제 사용해야 할까요?

  • 객체의 초기 상태를 설정하려면 __init__을 사용합니다.
  • 최종 사용자를 위해 사람이 읽을 수 있는 표현을 제공하려면 __str__을 사용합니다.
  • 개발자 및 디버깅을 위해 정확하고 모호하지 않은 표현을 제공하려면 __repr__을 사용합니다.

실습: 완전한 예시

세 가지 특수 메서드 모두를 사용하여 Rectangle 클래스를 만들어 보겠습니다.

  1. rectangle.py라는 새 파일을 생성합니다.

  2. 다음 코드를 추가합니다.

    class Rectangle:
        def __init__(self, width, height):
            self.width = width
            self.height = height
    
        def area(self):
            return self.width * self.height
    
        def perimeter(self):
            return 2 * (self.width + self.height)
    
        def __str__(self):
            return f"Rectangle with width {self.width} and height {self.height}"
    
        def __repr__(self):
            return f"Rectangle({self.width}, {self.height})"
    
    ## Create rectangles
    rect1 = Rectangle(5, 10)
    rect2 = Rectangle(3, 7)
    
    ## Display information about the rectangles
    print(f"Rectangle 1: {rect1}")
    print(f"Area: {rect1.area()}")
    print(f"Perimeter: {rect1.perimeter()}")
    print(f"Representation: {repr(rect1)}")
    
    print("\nRectangle 2: {0}".format(rect2))
    print(f"Area: {rect2.area()}")
    print(f"Perimeter: {rect2.perimeter()}")
    print(f"Representation: {repr(rect2)}")
    
    ## Recreate a rectangle using eval
    rect3 = eval(repr(rect1))
    print(f"\nRecreated rectangle: {rect3}")
    print(f"Is it the same area? {rect3.area() == rect1.area()}")
  3. 파일을 저장합니다.

  4. 스크립트를 실행합니다.

    python3 rectangle.py

다음과 같은 출력을 볼 수 있습니다.

Rectangle 1: Rectangle with width 5 and height 10
Area: 50
Perimeter: 30
Representation: Rectangle(5, 10)

Rectangle 2: Rectangle with width 3 and height 7
Area: 21
Perimeter: 20
Representation: Rectangle(3, 7)

Recreated rectangle: Rectangle with width 5 and height 10
Is it the same area? True

이 예제는 세 가지 특수 메서드 (__init__, __str__, __repr__) 가 함께 작동하여 잘 설계된 클래스를 만드는 방법을 보여줍니다.

실용적인 애플리케이션 만들기

이제 세 가지 특수 메서드 __init__, __str__, __repr__을 이해했으므로, 실제 시나리오에서 이러한 메서드의 사용을 보여주는 더 실용적인 애플리케이션을 만들어 보겠습니다. BankAccount 클래스를 사용하여 간단한 은행 시스템을 만들 것입니다.

은행 계좌 클래스 구축하기

  1. bank_account.py라는 새 파일을 생성합니다.

  2. 다음 코드를 추가합니다.

    class BankAccount:
        def __init__(self, account_number, owner_name, balance=0.0):
            self.account_number = account_number
            self.owner_name = owner_name
            self.balance = balance
            self.transactions = []
    
        def deposit(self, amount):
            if amount <= 0:
                print("Deposit amount must be positive")
                return False
    
            self.balance += amount
            self.transactions.append(f"Deposit: +${amount:.2f}")
            return True
    
        def withdraw(self, amount):
            if amount <= 0:
                print("Withdrawal amount must be positive")
                return False
    
            if amount > self.balance:
                print("Insufficient funds")
                return False
    
            self.balance -= amount
            self.transactions.append(f"Withdrawal: -${amount:.2f}")
            return True
    
        def get_transaction_history(self):
            return self.transactions
    
        def __str__(self):
            return f"Account {self.account_number} | Owner: {self.owner_name} | Balance: ${self.balance:.2f}"
    
        def __repr__(self):
            return f'BankAccount("{self.account_number}", "{self.owner_name}", {self.balance})'
  3. 파일을 저장합니다.

은행 계좌 클래스 테스트하기

이제 BankAccount 클래스를 테스트해 보겠습니다.

  1. bank_test.py라는 새 파일을 생성합니다.

  2. 다음 코드를 추가합니다.

    from bank_account import BankAccount
    
    ## Create bank accounts
    account1 = BankAccount("12345", "John Doe", 1000.0)
    account2 = BankAccount("67890", "Jane Smith", 500.0)
    
    ## Display initial account information
    print("Initial Account Status:")
    print(account1)
    print(account2)
    
    ## Perform transactions
    print("\nPerforming transactions...")
    
    ## Deposit to account1
    print("\nDepositing $250 to account1:")
    account1.deposit(250)
    print(account1)
    
    ## Withdraw from account2
    print("\nWithdrawing $100 from account2:")
    account2.withdraw(100)
    print(account2)
    
    ## Try to withdraw too much from account2
    print("\nTrying to withdraw $1000 from account2:")
    account2.withdraw(1000)
    print(account2)
    
    ## Try to deposit a negative amount to account1
    print("\nTrying to deposit -$50 to account1:")
    account1.deposit(-50)
    print(account1)
    
    ## Display transaction history
    print("\nTransaction history for account1:")
    for transaction in account1.get_transaction_history():
        print(f"- {transaction}")
    
    print("\nTransaction history for account2:")
    for transaction in account2.get_transaction_history():
        print(f"- {transaction}")
    
    ## Recreate an account using repr
    print("\nRecreating account1 using repr:")
    account1_repr = repr(account1)
    print(f"Representation: {account1_repr}")
    
    recreated_account = eval(account1_repr)
    print(f"Recreated account: {recreated_account}")
  3. 파일을 저장합니다.

  4. 스크립트를 실행합니다.

    python3 bank_test.py

다음과 유사한 출력을 볼 수 있습니다.

Initial Account Status:
Account 12345 | Owner: John Doe | Balance: $1000.00
Account 67890 | Owner: Jane Smith | Balance: $500.00

Performing transactions...

Depositing $250 to account1:
Account 12345 | Owner: John Doe | Balance: $1250.00

Withdrawing $100 from account2:
Account 67890 | Owner: Jane Smith | Balance: $400.00

Trying to withdraw $1000 from account2:
Insufficient funds
Account 67890 | Owner: Jane Smith | Balance: $400.00

Trying to deposit -$50 to account1:
Deposit amount must be positive
Account 12345 | Owner: John Doe | Balance: $1250.00

Transaction history for account1:
- Deposit: +$250.00

Transaction history for account2:
- Withdrawal: -$100.00

Recreating account1 using repr:
Representation: BankAccount("12345", "John Doe", 1250.0)
Recreated account: Account 12345 | Owner: John Doe | Balance: $1250.00

구현 이해하기

이 은행 애플리케이션에서:

  1. __init__ 메서드는 계좌 번호, 소유자 이름 및 선택적 초기 잔액으로 은행 계좌를 초기화합니다. 또한 거래를 추적하기 위해 빈 목록을 만듭니다.

  2. depositwithdraw 메서드는 거래를 처리하고 잔액 및 거래 내역을 업데이트합니다.

  3. __str__ 메서드는 계좌 번호, 소유자 이름 및 현재 잔액을 표시하여 계좌의 사용자 친화적인 표현을 제공합니다.

  4. __repr__ 메서드는 계좌 객체를 다시 생성할 수 있는 문자열을 제공합니다 (하지만 이 구현에서는 거래 내역이 유지되지 않습니다).

이 예제는 이러한 특수 메서드를 실용적인 애플리케이션에서 사용하여 보다 직관적이고 사용자 친화적인 객체를 만드는 방법을 보여줍니다.

애플리케이션 확장하기

마지막 연습으로, 여러 계정을 관리하는 간단한 은행 시스템을 만들어 보겠습니다.

  1. banking_system.py라는 새 파일을 생성합니다.

  2. 다음 코드를 추가합니다.

    from bank_account import BankAccount
    
    class BankingSystem:
        def __init__(self, bank_name):
            self.bank_name = bank_name
            self.accounts = {}
    
        def create_account(self, account_number, owner_name, initial_balance=0.0):
            if account_number in self.accounts:
                print(f"Account {account_number} already exists")
                return None
    
            account = BankAccount(account_number, owner_name, initial_balance)
            self.accounts[account_number] = account
            return account
    
        def get_account(self, account_number):
            return self.accounts.get(account_number)
    
        def list_accounts(self):
            return list(self.accounts.values())
    
        def __str__(self):
            return f"{self.bank_name} - Managing {len(self.accounts)} accounts"
    
        def __repr__(self):
            return f'BankingSystem("{self.bank_name}")'
    
    ## Create a banking system
    bank = BankingSystem("Python First Bank")
    print(bank)
    
    ## Create some accounts
    bank.create_account("A001", "John Doe", 1000)
    bank.create_account("A002", "Jane Smith", 500)
    bank.create_account("A003", "Bob Johnson", 250)
    
    ## List all accounts
    print("\nAll accounts:")
    for account in bank.list_accounts():
        print(account)
    
    ## Make some transactions
    account = bank.get_account("A001")
    if account:
        print(f"\nBefore deposit: {account}")
        account.deposit(500)
        print(f"After deposit: {account}")
    
    account = bank.get_account("A002")
    if account:
        print(f"\nBefore withdrawal: {account}")
        account.withdraw(200)
        print(f"After withdrawal: {account}")
    
    ## Try to create an existing account
    print("\nTrying to create an existing account:")
    bank.create_account("A001", "Someone Else", 300)
    
    ## Final state of the banking system
    print(f"\n{bank}")
  3. 파일을 저장합니다.

  4. 스크립트를 실행합니다.

    python3 banking_system.py

다음과 유사한 출력을 볼 수 있습니다.

Python First Bank - Managing 0 accounts

All accounts:
Account A001 | Owner: John Doe | Balance: $1000.00
Account A002 | Owner: Jane Smith | Balance: $500.00
Account A003 | Owner: Bob Johnson | Balance: $250.00

Before deposit: Account A001 | Owner: John Doe | Balance: $1000.00
After deposit: Account A001 | Owner: John Doe | Balance: $1500.00

Before withdrawal: Account A002 | Owner: Jane Smith | Balance: $500.00
After withdrawal: Account A002 | Owner: Jane Smith | Balance: $300.00

Trying to create an existing account:
Account A001 already exists

Python First Bank - Managing 3 accounts

이 예제는 이전에 만든 BankAccount 클래스를 보다 완벽한 애플리케이션에서 사용하는 방법을 보여줍니다. __init__, __str__, __repr__과 같은 특수 메서드가 직관적이고 사용자 친화적인 클래스를 만드는 데 어떻게 탄탄한 기반을 제공하는지 보여줍니다.

요약

이 랩에서는 더 표현력이 풍부하고 사용자 친화적인 객체를 만드는 데 도움이 되는 Python 의 세 가지 필수 특수 메서드에 대해 배웠습니다.

  1. __init__: 객체가 생성될 때 객체의 속성을 초기화하는 생성자 메서드입니다.

  2. __str__: 주로 최종 사용자를 위해 객체의 사람이 읽을 수 있는 문자열 표현을 제공하는 메서드입니다.

  3. __repr__: 주로 개발자 및 디버깅을 위해 객체의 모호하지 않은 문자열 표현을 제공하는 메서드입니다.

PersonBook과 같은 간단한 클래스부터 은행 시스템과 같은 더 복잡한 애플리케이션까지, 여러 예제에서 이러한 메서드를 구현했습니다. 또한 __str____repr__의 차이점과 각 메서드를 언제 사용해야 하는지 배웠습니다.

이러한 특수 메서드를 마스터함으로써 언어의 내장 기능과 원활하게 통합되는 보다 직관적이고 사용자 정의된 Python 객체를 만들 수 있습니다. 이 지식은 Python 에서 객체 지향 프로그래밍의 필수적인 부분을 형성하며, 더 깨끗하고 유지 관리 가능한 코드를 작성하는 데 도움이 될 것입니다.

Python 여정을 계속 진행하면서, 객체의 동작을 더욱 사용자 정의할 수 있는 다른 많은 특수 메서드가 있다는 것을 기억하십시오. 이러한 메서드를 탐색하면 다양한 컨텍스트에서 객체가 어떻게 동작하는지에 대한 더 많은 제어 권한을 얻을 수 있습니다.