2025.03.24 (월)

윤혜진·2025년 3월 24일

📍오늘의 학습 키워드

  • ATM 만들기 (3)

    • 회원가입 기능 구현
    • 로그인 기능 구현
    • 송금 기능 구현

📍학습 내용

  • 기능 구현 전 기존 코드 수정:

    • 로그인/회원가입 기능 구현을 위해 UserDataID, PW정보를 추가

    • 저장 또한 이름이 아닌 ID로 저장되도록 만듦.

      public UserData(string _name, int _cash, int _bankBalance, string _id, string _pw)
      {
          userName = _name;
          usercash = _cash;
          bankBalance = _bankBalance;
      
          userID = _id;
          userPW = _pw;
      }
    • 반복적으로 안내/경고 창을 띄워줘야 하는 상황이 발생해서 ErrorPopup 메서드를 다음과 같이 수정함:

      public void ErrorPopup(string message)
      {
         errorText.text = message;
         popupError.SetActive(true);   
      }
  • 회원가입 기능

    • 있어야 하는 기능:
      • ID, Name , PW , PW Confirm 으로 구성
      • 하나라도 비어있으면 “정보를 확인해주세요” 라는 안내 메세지가 뜸
      • PW 와 PW Confirm 가 다를 경우에도 안내 메세지가 떠야함
      • ID , Name , PS 에 공백이 있다면 다시 입력
      • 기존에 사용하는 ID 라면 “다른 ID를 입력해주세요”
      • PW 와 PW Confirm 는 값을 입력하면 ***로 보이도록 해야함
  • 코드(Login.cs):

    using UnityEngine;
    using UnityEngine.UI;
    
    #nullable enable
    
    public class Login : MonoBehaviour
    {
       public InputField loginField_ID;
       public InputField loginField_PW;
    
       public void Start()
       {
           this.gameObject.SetActive(true);
       }
    
       public void OnClickLoginBtn()
       {
           UserData? user = DataManager.Load(loginField_ID.text);
    
           if (user == null)
           {
               GameManager.Instance.popupBank.ErrorPopup("존재하지 않는 회원입니다.");
               return;
           }
           else if(user.userPW != loginField_PW.text)
           {
               GameManager.Instance.popupBank.ErrorPopup("올바르지 않은 비밀번호입니다.");
               return;
           }
    
           GameManager.Instance.StartBank(user);
           this.gameObject.SetActive(false);
       }
    }
  • 로그인 기능

    • 있어야 하는 기능:

      • PS 입력시 ***로 표기
      • 입력한 ID 가 데이터에 없을 시 “존재하지 않는 회원입니다.”
      • ID 는 맞았지만 PW 가 틀렸을 시 “올바르지 않은 PW입니다.”
      • 로그인 성공시 로그인한 회원정보를 통해 ATM 기능을 이용할 수 있도록 함
    • 코드(SignUp.cs):

      using UnityEngine;
      using UnityEngine.UI;
      
      public class SignUp : MonoBehaviour
      {
         public InputField idField;
         public InputField nameField;
         public InputField pwField;
         public InputField confirmField;
      
         public Text guideText;
      
         private InputField[] signUpFields;
      
         public void OnClickSignUpBtn()
         {
             if(InputCheck())
             {
                 //기본 현금 10만원 / 예금 5만원
                 UserData newUser = new UserData(nameField.text,
                                                  100000,
                                                  50000,
                                                  idField.text,
                                                  pwField.text);
                 DataManager.Save(newUser);
      
                 GameManager.Instance.popupBank.ErrorPopup("가입이 완료되었습니다.");
                 this.gameObject.SetActive(false);
             }
             else
             {
                 //에러창을 띄운다.
                 GameManager.Instance.popupBank.ErrorPopup("정보를 확인해주세요.");
             }
         }
      
         public bool InputCheck()
         {
             signUpFields = new InputField[4] { idField, nameField, pwField, confirmField };
             for (int i = 0; i < signUpFields.Length; i++)
             {
                 //만약 아무것도 입력하지 않았거나, 입력값에 공백이 포함되어 있다면
                 if (signUpFields[i].text.Length <= 0 || signUpFields[i].text.Contains(" "))
                 {
                     Debug.Log($"{signUpFields[i].name}을 확인해주세요.");
                     guideText.text = $"{signUpFields[i].name}을 확인해주세요.";
                     return false;
                 }
             }
      
             if (pwField.text != confirmField.text)
             {
                 guideText.text = "PS가 일치하지 않습니다.";
                 return false;
             }
      
             if(DataManager.CheckData(idField.text))
             {
                 guideText.text = "이미 존재하는 ID입니다.";
                 return false;
             }
             return true;      
         }
      }
  • 송금 기능

    • 있어야 하는 기능:

      • 송금 대상이 존재하지 않는 ID라면 “대상이 없습니다.”
      • 송금하려는 금액이 내 계좌 잔액보다 크면 “잔액이 부족합니다”
      • 송금 대상/금액을 입력하지 않았거나 공백이 포함되어 있을 경우 “입력 정보를 확인해주세요.”
    • 코드(PopupBank.cs):

      public void OnClickSendBtn()
      {
         //입금할 상대의 정보를 불러옴
         UserData? user = DataManager.Load(opponentID.text);
         int money = int.Parse(sendMoney.text); 
      
         if (user == null)
         {
             ErrorPopup("대상이 없습니다.");
             return;
         }
         if(GameManager.Instance.Balance < money)
         {
             ErrorPopup("잔액이 부족합니다.");
             return;
         }
      
         //Load한 상대 계좌에 입금
         user.bankBalance += money;
         //내 계좌에서 입금하는 만큼의 돈을 차감
         GameManager.Instance.Balance -= money;
      
         //Load하고 수정한 유저 정보를 저장
         DataManager.Save(user);
      
         Debug.Log($"{user.userID}에게 {money}원 송금완료");
         ErrorPopup("송금완료");
      }

📍겪은 어려움

  • Button에 등록할 메서드의 매개변수 문제

    • 송금 기능을 구현하려던 중 다음과 같이 코드를 짜고 등록해 주려니 메서드 목록에 안 뜨는 것을 발견.

      public void OnClickSendBtn(InputField opponentID, InputField sendMoney)
      {
         UserData? user = DataManager.Load(opponentID.text);
         int money = int.Parse(sendMoney.text);
      
         if (user == null)
         {
             ErrorPopup("대상이 없습니다.");
             return;
         }
         if (GameManager.Instance.Balance < money)
         {
             ErrorPopup("잔액이 부족합니다.");
             return;
         }
      
         user.bankBalance += int.Parse(sendMoney.text);
         GameManager.Instance.Balance -= money;
      
         DataManager.Save(user);
      
         Debug.Log($"{user.userID}에게 {money}원 송금완료");
         ErrorPopup("송금완료");
      }
    • InputField를 매개변수로 받아서 안 뜨는 것이라기엔 이미 InputField를 매개변수로 받는 메서드가 존재했음.

    • 지금까지의 메서드와 다른 점이라고는 매개변수가 두 개라는 것 뿐이라 해당 코드에서 매개변수 하나만 빼 보았더니 이번엔 정상적으로 뜨는 것이 확인됨

    • 그래서 두 개를 넣을 수 있는 방법을 찾기 위해 좀 더 실험해봄:

      • 배열 안됨
      • 리스트 안됨
      • 파람스 안됨
      • 튜플 안됨
      • 스트럭트로 묶어서 받기 안 됨
    • 구글링을 통해 좀 더 찾아보니 원래 버튼에 붙이는 메서드는 매개변수를 한 개만 쓸 수 있다고 함...

    • 안되는 이유:

      • Button.onClickUnityEvent, 내부적으로는 매개변수 없는 UnityEvent.Invoke()를 호출함.
      • 인스펙터에서는 1개의 인자까지만 바인딩할 수 있도록 설계됨.
      • 따라서 void SomeMethod(int, string)처럼 2개 이상은 지원하지 않음.
    • 매개변수 두 개 이상 사용하려면:
      - 아래와 같이 AddListener로 코드에서 붙여준다면 매개변수를 여러 개 받아올 수 있음.

      public Button myButton;
      
      void Start()
      {
         // 람다를 통해 다중 인자 전달
         myButton.onClick.AddListener(() => RealMethod(123, "Hello")); 
      }
      
      private void RealMethod(int number, string message)
      {
         Debug.Log($"{number}, {message}");
      }
    • 해결방식: InputField opponentIDsendMoney를 스크립트에서 public으로 받아와 매개변수 없이 구현해주었다.

    • 수정한 코드:

         public void OnClickSendBtn()
         {
             UserData? user = DataManager.Load(opponentID.text);
             int money = int.Parse(sendMoney.text); 
      
             if (user == null)
             {
                 ErrorPopup("대상이 없습니다.");
                 return;
             }
             if(GameManager.Instance.Balance < money)
             {
                 ErrorPopup("잔액이 부족합니다.");
                 return;
             }
      
             user.bankBalance += int.Parse(sendMoney.text);
             GameManager.Instance.Balance -= money;
      
             DataManager.Save(user);
      
             Debug.Log($"{user.userID}에게 {money}원 송금완료");
             ErrorPopup("송금완료");
         }
  • 유니티에서의 nullable 사용

    • nullable을 사용하려니 다음과 같은 오류가 뜸:
  • 해결: 코드 상단에 #nullable enable 를 붙여주니 오류가 뜨지 않았다.

📍회고 및 반성

  • 드디어 ATM을 완성했지만 GameManager.cs의 역할이 모호하고 PopupBank.cs에 많은 기능이 몰려있어 구조 리펙토링이 필요해 보인다...
  • 그래도 이번 과제를 통홰 json을 이용한 직렬화를 공부하고 적용해볼 수 있어서 좋았다!
  • 남은 시간 동안에는 밀린 특강도 듣고, 이번 ATM 코드도 리팩토링 하고, 저장한 유저 정보를 암호화 하는 기술도 개인적으로 공부해서 적용해보고 싶음.
  • 암호화는 최종 프로젝트 때도 필요할 테니 이번 프로젝트에 적용하지 못하더라도 꼭 공부해볼 것!

0개의 댓글