본문 바로가기

Back-End/Python

[Python][파이썬] 고객 정보 관리 시스템 만들기 실습 6 - class,mvc

~ 목차 ~

고객 정보 관리 시스템 만들기 실습5 에서 class화를 진행하였다.

[Python][파이썬] 고객 정보 관리 시스템 만들기 실습 5 (tistory.com)

 

[Python][파이썬] 고객 정보 관리 시스템 만들기 실습 5

파이썬에도 class가 있다는 것을 알게 되었고 class를 사용하면 어떤 점들이 좋은지 알아보고 실습 예제를 class를 사용하여 바꾸어 보자. 클래스를 사용하는 이유 코드의 구조화 및 조직화: 클래스

codingwithyou.tistory.com

 

 

이젠 do_S와 do_L 말고 다른 함수들도 가져오고,

class의 default함수(초기값) 만들고 main에 있던 변수 self변수로 가져와 보자.

추가로 자바에서 배운 model과 view를 적용해 class를 분할 해 보자.

 

 

1. do_I, do_P, do_C, do_N, do_U, do_D 모듈 class 내부로 가져오기

 

2. class의 클래스의 생성자 (default함수) 만들기

 

3. CustomerController클래스, CustomerView클래스, CustomerModel클래스 나눠주기 (파일 분리)

 


1. do_I, do_P, do_C, do_N, do_U, do_D 모듈 class 내부로 가져오기
    - self변수 붙여주기

    - import 지워주기

import pickle
import sys
import os
import re

class Customer:

    def print_menu(self):
        return input('''
        다음 중에서 하실 작업의 메뉴를 입력하세요.
        I - 고객 정보 입력
        P - 이전 고객 정보 조회
        C - 현재 고객 정보 조회
        N - 다음 고객 정보 조회
        U - 현재 고객 정보 수정
        D - 현재 고객 정보 삭제
        S - 고객 정보 저장 
        Q - 프로그램 종료
    ''').upper()

    def chk_input_data(self, msg, func, upper=True):
        while True:
            x = input(msg)
            if upper:
                x = x.upper()
            if func(x):
                break
            else:
                print('잘못 입력하셨습니다. 다시 입력 해 주세요.')
        return x

    def check_email_addr(self, email_addr):
        pattern = re.compile('^[a-zA-Z][a-zA-Z0-9]{3,10}@[a-zA-Z0-9]{2,8}[.][a-zA-Z]{2,5}$')
        return pattern.search(email_addr)


    def do_I(self, customers, index):

        print('고객정보 입력')
        customer = { 'name':'', 'gender': '', 'email': '', 'year': 0 }

        customer['name'] = self.chk_input_data('이름을 입력하세요 : ', lambda x: True if len(x) > 2 else False, upper=True)
        customer['gender'] = self.chk_input_data('성별 (M/F)를 입력하세요 : ', lambda x: True if x in ('M', 'F') else False)
        customer['email'] = self.chk_input_data('이메일 주소를 입력하세요 : ', lambda x: True if self.check_email_addr(x) else False, upper=False)
        customer['year'] = self.chk_input_data('출생년도 4자리 입력하세요 : ', lambda x: True if len(x) == 4 and x.isdigit() else False)

        customers.append(customer)
        index = len(customers) - 1
        return index

    def do_P(self, customers, index):
        print('이전 고객 정보 조회')
        if index <= 0:
            print('이전 데이터로 이동 불가.')
            print(index)
        else:
            index -= 1
            print(f'{index}번째 고객 정보 입니다.')
            print(customers[index])
        return index

    def do_C(self, customers, index):
        print('현재 고객 정보 조회')
        print('>>>>>', index)
        if index >= -1:
            print(f'{index}번째 고객 정보 입니다.')
            print(customers[index])
        else:
            print('입력된 정보가 없습니다. 정보 입력은 I를 선택하세요.')

    def do_N(self, customers, index):
        print('다음 고객 정보 조회')
        if index >= (len(customers) - 1):
            print('이후 데이터 이동 불가')
            print(index)
        else:
            index += 1
            print(f'{index}번째 고객 정보 입니다.')
            print(customers[index])
        return index

    def do_U(self, customers, index):
        print('현재 고객 정보 수정')
        customer = { 'name':'', 'gender': '', 'email': '', 'year': 0 }

        customer['name'] = self.chk_input_data('수정할 이름을 입력하세요 : ', lambda x: True if len(x) > 2 else False)
        customer['gender'] = self.chk_input_data('수정할 성별 (M/F)를 입력하세요 : ', lambda x: True if x in ('M', 'F') else False)
        customer['email'] = self.chk_input_data('이메일 주소를 입력하세요 : ', lambda x: True if self.check_email_addr(x) else False, upper=False)
        customer['year'] = self.chk_input_data('수정할 출생년도 4자리 입력하세요 : ', lambda x: True if len(x) == 4 and x.isdigit() else False)

        print(customer)
        customers[index] = customer

    def do_D(self, customers, index):
        if not customers:
            print("고객 정보가 없습니다.")
        else:
            print(f'현재 고객 정보 {customers[index]["name"]} 삭제')
            print('index : ',index)
            del customers[index]
            if index >= len(customers):
                index = len(customers) - 1
        return index

    def do_S(self, customers):
        try:
            with open('cust/customers.pickle', 'wb') as fp:
                pickle.dump(customers, fp)
        except Exception as e:
            print('저장하는데에 실패하였습니다.', e)

    def do_L(self):
        file_path = 'cust/customers.pickle'
        if os.path.exists(file_path):
            with open(file_path, 'rb') as fp:
                return pickle.load(fp)
        else:
            return list()

    #main
    def main(self):

        customers = self.do_L()
        index = -1

        while True:
            menu = self.print_menu()
            if menu == 'I':
                self.index = self.do_I(self.customers, self.index)
                print('index :', self.index)
                print('customers : ', self.customers)

            elif menu == 'P':
                self.index = self.do_P(self.customers, self.index)

            elif menu == 'C':
                self.do_C(self.customers, self.index)

            elif menu == 'N':
                self.index = self.do_N(self.customers, self.index)

            elif menu == 'U':
                self.do_U(self.customers, self.index)

            elif menu == 'D':
                self.index = self.do_D(self.customers, self.index)

            elif menu == 'S':
                self.do_S(self.customers)

            elif menu == 'Q':
                self.do_S(self.customers)
                print('저장이 완료되었습니다.')
                print('안녕히가세요~')
                sys.exit()

            else:
                print('잘못 입력하셨습니다. 다시 입력 해주세요')


if __name__ == '__main__':
    a = Customer()
    a.main()

 


 

 

2. class의 클래스의 생성자 (default함수) 만들기

    - def __init__(self): 생성

    - main()에 있던 customers = self.do_L()와   index = -1를 지우고  init 함수에 customers와 index 설정해주기

    - main() 안에 있는 각 함수에 self.붙여주기

    - main() 안에 있는 각 customers와 index에 self.붙여주기

 

import pickle
import sys
import os
import re



class Customer:

    def __init__(self):
        self.customers = self.do_L()
        self.index = -1

    def print_menu(self):
        return input('''
        다음 중에서 하실 작업의 메뉴를 입력하세요.
        I - 고객 정보 입력
        P - 이전 고객 정보 조회
        C - 현재 고객 정보 조회
        N - 다음 고객 정보 조회
        U - 현재 고객 정보 수정
        D - 현재 고객 정보 삭제
        S - 고객 정보 저장 
        Q - 프로그램 종료
    ''').upper()

    def chk_input_data(self, msg, func, upper=True):
        while True:
            x = input(msg)
            if upper:
                x = x.upper()
            if func(x):
                break
            else:
                print('잘못 입력하셨습니다. 다시 입력 해 주세요.')
        return x

    def check_email_addr(self, email_addr):
        pattern = re.compile('^[a-zA-Z][a-zA-Z0-9]{3,10}@[a-zA-Z0-9]{2,8}[.][a-zA-Z]{2,5}$')
        return pattern.search(email_addr)


    def do_I(self, customers, index):

        #view 클래스 부분
        print('고객정보 입력')
        customer = { 'name':'', 'gender': '', 'email': '', 'year': 0 }

        customer['name'] = self.chk_input_data('이름을 입력하세요 : ', lambda x: True if len(x) > 2 else False, upper=True)
        customer['gender'] = self.chk_input_data('성별 (M/F)를 입력하세요 : ', lambda x: True if x in ('M', 'F') else False)
        customer['email'] = self.chk_input_data('이메일 주소를 입력하세요 : ', lambda x: True if self.check_email_addr(x) else False, upper=False)
        customer['year'] = self.chk_input_data('출생년도 4자리 입력하세요 : ', lambda x: True if len(x) == 4 and x.isdigit() else False)

        #model 클래스 부분
        customers.append(customer)
        index = len(customers) - 1
        return index

    def do_P(self, customers, index):
        print('이전 고객 정보 조회')
        if index <= 0:
            print('이전 데이터로 이동 불가.')
            print(index)
        else:
            index -= 1
            print(f'{index}번째 고객 정보 입니다.')
            print(customers[index])
        return index

    def do_C(self, customers, index):
        print('현재 고객 정보 조회')
        print('>>>>>', index)
        if index >= -1:
            print(f'{index}번째 고객 정보 입니다.')
            print(customers[index])
        else:
            print('입력된 정보가 없습니다. 정보 입력은 I를 선택하세요.')

    def do_N(self, customers, index):
        print('다음 고객 정보 조회')
        if index >= (len(customers) - 1):
            print('이후 데이터 이동 불가')
            print(index)
        else:
            index += 1
            print(f'{index}번째 고객 정보 입니다.')
            print(customers[index])
        return index

    def do_U(self, customers, index):
        print('현재 고객 정보 수정')
        customer = { 'name':'', 'gender': '', 'email': '', 'year': 0 }

        customer['name'] = self.chk_input_data('수정할 이름을 입력하세요 : ', lambda x: True if len(x) > 2 else False)
        customer['gender'] = self.chk_input_data('수정할 성별 (M/F)를 입력하세요 : ', lambda x: True if x in ('M', 'F') else False)
        customer['email'] = self.chk_input_data('이메일 주소를 입력하세요 : ', lambda x: True if self.check_email_addr(x) else False, upper=False)
        customer['year'] = self.chk_input_data('수정할 출생년도 4자리 입력하세요 : ', lambda x: True if len(x) == 4 and x.isdigit() else False)

        print(customer)
        customers[index] = customer

    def do_D(self, customers, index):
        if not customers:
            print("고객 정보가 없습니다.")
        else:
            print(f'현재 고객 정보 {customers[index]["name"]} 삭제')
            print('index : ',index)
            del customers[index]
            if index >= len(customers):
                index = len(customers) - 1
        return index

    def do_S(self, customers):
        try:
            with open('cust/customers.pickle', 'wb') as fp:
                pickle.dump(customers, fp)
        except Exception as e:
            print('저장하는데에 실패하였습니다.', e)

    def do_L(self):
        file_path = 'cust/customers.pickle'
        if os.path.exists(file_path):
            with open(file_path, 'rb') as fp:
                return pickle.load(fp)
        else:
            return list()

    #main
    def main(self):

        # customers = self.do_L()
        # index = -1

        while True:
            menu = self.print_menu()
            if menu == 'I':
                self.index = self.do_I(self.customers, self.index)
                print('index :', self.index)
                print('customers : ', self.customers)

            elif menu == 'P':
                self.index = self.do_P(self.customers, self.index)

            elif menu == 'C':
                self.do_C(self.customers, self.index)

            elif menu == 'N':
                self.index = self.do_N(self.customers, self.index)

            elif menu == 'U':
                self.do_U(self.customers, self.index)

            elif menu == 'D':
                self.index = self.do_D(self.customers, self.index)

            elif menu == 'S':
                self.do_S(self.customers)

            elif menu == 'Q':
                self.do_S(self.customers)
                print('저장이 완료되었습니다.')
                print('안녕히가세요~')
                sys.exit()

            else:
                print('잘못 입력하셨습니다. 다시 입력 해주세요')


if __name__ == '__main__':
    a = Customer()
    a.main()

 

 


 

 

3. CustomerController클래스, CustomerView클래스, CustomerModel클래스 나눠주기 (파일 분리)

    - CustomerController클래스 : CustomerView클래스와 CustomerModel클래스를 사용하는 클래스(main)

    - CustomerView 클래스 : 사용자 정보 관리하는 부분, 데이터가 보이는 로직이 주로 view

    - CustomerModel 클래스 : 데이터나 비즈니스 로직을 처리하는 역할, 데이터를 저장하는 로직이 주로 model

    - view와 model에서 각 리턴 값들 정하고 controller에서 사용하기

 

 

  • customer_mvc_control.py
    • CustomerView와 CustomerModel import하기
    • self.customer_view, self.customer_model로 뷰, 모델 클래스 호출
    • main에서 do_I 정보 가져오기
    • 마지막 실행단계에서 클래스 이름 변경해주기 
from customer_mvc_view import CustomerView
from customer_mvc_model import CustomerModel

import pickle
import sys
import os



class CustomerController:

    def __init__(self):
        self.customers = self.do_L()
        self.index = -1
        
        #CustomerView클래스 호출
        self.customer_view = CustomerView()
        #CustomerModel클래스 호출
        self.customer_model = CustomerModel()

    def print_menu(self):
        return input('''
        다음 중에서 하실 작업의 메뉴를 입력하세요.
        I - 고객 정보 입력
        P - 이전 고객 정보 조회
        C - 현재 고객 정보 조회
        N - 다음 고객 정보 조회
        U - 현재 고객 정보 수정
        D - 현재 고객 정보 삭제
        S - 고객 정보 저장 
        Q - 프로그램 종료
    ''').upper()


    def do_P(self, customers, index):
        print('이전 고객 정보 조회')
        if index <= 0:
            print('이전 데이터로 이동 불가.')
            print(index)
        else:
            index -= 1
            print(f'{index}번째 고객 정보 입니다.')
            print(customers[index])
        return index

    def do_C(self, customers, index):
        print('현재 고객 정보 조회')
        print('>>>>>', index)
        if index >= -1:
            print(f'{index}번째 고객 정보 입니다.')
            print(customers[index])
        else:
            print('입력된 정보가 없습니다. 정보 입력은 I를 선택하세요.')

    def do_N(self, customers, index):
        print('다음 고객 정보 조회')
        if index >= (len(customers) - 1):
            print('이후 데이터 이동 불가')
            print(index)
        else:
            index += 1
            print(f'{index}번째 고객 정보 입니다.')
            print(customers[index])
        return index


    def do_D(self, customers, index):
        if not customers:
            print("고객 정보가 없습니다.")
        else:
            print(f'현재 고객 정보 {customers[index]["name"]} 삭제')
            print('index : ',index)
            del customers[index]
            if index >= len(customers):
                index = len(customers) - 1
        return index

    def do_S(self, customers):
        try:
            with open('cust/customers.pickle', 'wb') as fp:
                pickle.dump(customers, fp)
        except Exception as e:
            print('저장하는데에 실패하였습니다.', e)

    def do_L(self):
        file_path = 'cust/customers.pickle'
        if os.path.exists(file_path):
            with open(file_path, 'rb') as fp:
                return pickle.load(fp)
        else:
            return list()

    #main
    def main(self):

        while True:
            menu = self.print_menu()
            if menu == 'I':
                
                #customer_view 호출(customer정보 가져오기)
                customer = self.customer_view.do_I()
                
                #customer_model 호출(뷰의 정보 변수로 넣어서 넘겨주고 customers정보 가져오기)
                self.index = self.customer_model.do_I(self.customers, customer)
                
                print('index :', self.index)
                print('customers : ', self.customers)

            elif menu == 'P':
                self.index = self.do_P(self.customers, self.index)

            elif menu == 'C':
                self.do_C(self.customers, self.index)

            elif menu == 'N':
                self.index = self.do_N(self.customers, self.index)

            elif menu == 'U':
                customer = self.customer_view.do_U()
                self.index = self.customer_model.do_U(self.customers, customer, self.index)

            elif menu == 'D':
                self.index = self.do_D(self.customers, self.index)

            elif menu == 'S':
                self.do_S(self.customers)

            elif menu == 'Q':
                self.do_S(self.customers)
                print('저장이 완료되었습니다.')
                print('안녕히가세요~')
                sys.exit()

            else:
                print('잘못 입력하셨습니다. 다시 입력 해주세요')


if __name__ == '__main__':
	#클래스 이름 변경
    a = CustomerController()
    a.main()

 

 

  • customer_mvc_view.py
    • chk_input_data()
    • check_email_addr()
    • do_I()의 view부분
    • do_U()의 view부분
    • return값 설정(controller에 넘겨줄 부분)
      - return customer
import re


class CustomerView:
    #데이터가 보이는 로직이 주로 view
    def chk_input_data(self, msg, func, upper=True):
        while True:
            x = input(msg)
            if upper:
                x = x.upper()
            if func(x):
                break
            else:
                print('잘못 입력하셨습니다. 다시 입력 해 주세요.')
        return x

    def check_email_addr(self, email_addr):
        pattern = re.compile('^[a-zA-Z][a-zA-Z0-9]{3,10}@[a-zA-Z0-9]{2,8}[.][a-zA-Z]{2,5}$')
        return pattern.search(email_addr)

    def do_I(self):
        #view 클래스에 i메소드
        print('고객정보 입력')
        customer = { 'name':'', 'gender': '', 'email': '', 'year': 0 }

        customer['name'] = self.chk_input_data('이름을 입력하세요 : ', lambda x: True if len(x) > 2 else False, upper=True)
        customer['gender'] = self.chk_input_data('성별 (M/F)를 입력하세요 : ', lambda x: True if x in ('M', 'F') else False)
        customer['email'] = self.chk_input_data('이메일 주소를 입력하세요 : ', lambda x: True if self.check_email_addr(x) else False, upper=False)
        customer['year'] = self.chk_input_data('출생년도 4자리 입력하세요 : ', lambda x: True if len(x) == 4 and x.isdigit() else False)

        return customer

    def do_U(self):
        #view
        print('현재 고객 정보 수정')
        customer = { 'name':'', 'gender': '', 'email': '', 'year': 0 }

        customer['name'] = self.chk_input_data('수정할 이름을 입력하세요 : ', lambda x: True if len(x) > 2 else False)
        customer['gender'] = self.chk_input_data('수정할 성별 (M/F)를 입력하세요 : ', lambda x: True if x in ('M', 'F') else False)
        customer['email'] = self.chk_input_data('이메일 주소를 입력하세요 : ', lambda x: True if self.check_email_addr(x) else False, upper=False)
        customer['year'] = self.chk_input_data('수정할 출생년도 4자리 입력하세요 : ', lambda x: True if len(x) == 4 and x.isdigit() else False)

        return customer

 

  • customer_mvc_model.py
    • do_I에서 model부분
    • do_U에서 model부분
    • return값 index보내주기
class CustomerModel:

    #데이터를 저장하는 로직이 주로 model

    def do_I(self, customers, customer):
        #model 클래스에 i메소드
        customers.append(customer)
        index = len(customers) - 1
        return index

    def do_U(self, customers, customer, index):

        print(customer)
        customers[index] = customer
        return index

 

 

여기서는 insert와 update만 mvc로 구분 하였지만 다른 부분도 나누어 보자.


 

 

'self.' 하는 이유 

  1. 객체의 속성과 메서드에 접근: self를 통해 현재 객체의 속성에 접근.
    예를 들어, self.customers는 현재 객체의 customers 속성을 나타낸다.
  2. 다른 메서드 호출: self를 통해 같은 객체 내의 다른 메서드를 호출.
    예를 들어, self.do_L()은 현재 객체의 do_L 메서드를 호출합니다.
  3. 객체의 상태 관리: self를 사용하여 객체의 상태를 관리하고 유지.
    객체의 상태는 해당 클래스의 인스턴스 변수들로 표현되며, self를 통해 이들에 접근하고 수정할 수 있다.

 

모델-뷰-컨트롤러 (MVC)

 

  1. Controller 클래스 : 사용자 입력을 받아와 해당 입력에 따라 다양한 작업을 수행하는 역할
    모델(Model)과 뷰(View) 객체를 사용하여 데이터와 사용자 인터페이스를 관리
  2. View 클래스 : 사용자 인터페이스를 관리하고 사용자에게 정보를 표시하는 역할
    예를 들어, 사용자로부터 입력을 받는 메서드, 메뉴를 출력하는 메서드, 정보를 표시하는 메서드 등
  3. Model 클래스 : 데이터나 비즈니스 로직을 처리하는 역할
    예를 들어, 고객 정보를 저장하고 관리하는 메서드, 파일에서 데이터를 읽거나 쓰는 메서드, 데이터 유효성 검사 메서드 등

 

728x90