Chapter 12. 객체지향 프로젝트

프로그램을 작성하기 전에 어떤 기능이 필요한지 분석하고 클래스를 나누어야 합니다. 이를 프로그램 설계라고 합니다.
회원관리 프로그램에서 필요한 기능을 먼저 정리해 보겠습니다.
| 기능 | 설명 |
|---|---|
| 회원 등록 | 새로운 회원을 추가합니다. |
| 회원 조회 | 등록된 회원 전체를 출력합니다. |
| 회원 검색 | 아이디를 이용하여 회원을 찾습니다. |
| 회원 수정 | 회원의 이름, 나이, 전화번호를 수정합니다. |
| 회원 삭제 | 등록된 회원을 삭제합니다. |
| 파일 저장 | 회원 정보를 CSV 파일에 저장합니다. |
| 파일 불러오기 | CSV 파일에서 회원 정보를 읽습니다. |
기능을 모두 하나의 클래스에 작성할 수도 있지만 프로그램이 커지면 관리하기 어렵습니다. 따라서 기능을 역할별로 분리합니다.
이번 프로젝트에서는 다음 클래스를 사용합니다.
- Member: 회원 한 명의 정보를 저장합니다.
- MemberManager: 여러 회원을 등록, 수정, 삭제, 검색합니다.
- Menu: 메뉴를 출력하고 사용자 선택을 입력받습니다.
- FileManager: 회원 정보를 CSV 파일에 저장하고 불러옵니다.
프로그램을 실행하는 코드는 main.py에 작성합니다.
Member 클래스는 회원 한 명의 정보를 저장합니다. 한 명의 회원은 다음 정보를 가집니다.
- 회원 아이디
- 이름
- 나이
- 전화번호
회원 객체는 다음과 같이 생성됩니다.
member1 = Member("user01", "홍길동", 20, "010-1111-2222")
member1과 member2는 서로 다른 회원 객체입니다.
Member 클래스는 회원 한 명의 정보를 저장하고 출력하는 기능을 제공합니다.
class Member:
def __init__(self, member_id, name, age, phone):
self.member_id = member_id
self.name = name
self.age = age
self.ph>
생성자에서 전달받은 값을 인스턴스 변수에 저장합니다.
member = Member("user01", "홍길동", 20, "010-1111-2222")
회원 정보를 출력하는 메서드는 다음과 같습니다.
def print_info(self):
print("아이디 :", self.member_id)
print("이름 :", self.name)
print("나이 :", self.age)
print("전화번호 :", self.phone)
사용 예제는 다음과 같습니다.
member.print_info()
이름 : 홍길동
나이 : 20
전화번호 : 010-1111-2222
__str__() 메서드를 작성하면 회원 객체를 print()로 출력할 수 있습니다.
def __str__(self):
return (f"아이디 : {self.member_id}, "
f"이름 : {self.name}, "
f"나이 : {self.age}, "
f"전화번호 : {self.phone}")
사용 예제는 다음과 같습니다.
print(member)
CSV 파일에 저장하려면 회원 정보를 리스트로 변환하는 기능이 필요합니다.
def to_list(self):
return [self.member_id, self.name, self.age, self.phone]
사용 예제는 다음과 같습니다.
print(member.to_list())
Member 클래스가 완성되었습니다.
class Member:
def __init__(self, member_id, name, age, phone):
self.member_id = member_id
self.name = name
self.age = age
self.ph
def print_info(self):
print("아이디 :", self.member_id)
print("이름 :", self.name)
print("나이 :", self.age)
print("전화번호 :", self.phone)
def to_list(self):
return [self.member_id, self.name, self.age, self.phone]
def __str__(self):
return (f"아이디 : {self.member_id}, "
f"이름 : {self.name}, "
f"나이 : {self.age}, "
f"전화번호 : {self.phone}")
MemberManager 클래스는 여러 회원 객체를 관리합니다. 회원 객체는 리스트에 저장합니다.
class MemberManager:
def __init__(self):
self.members = []
MemberManager 객체가 생성되면 빈 회원 목록이 만들어집니다.
manager = MemberManager() print(manager.members)
회원 등록은 Member 객체를 리스트에 추가하는 기능입니다.
def add_member(self, member):
self.members.append(member)
print("회원이 등록되었습니다.")
전체 예제는 다음과 같습니다.
manager = MemberManager()
member = Member("user01", "홍길동", 20, "010-1111-2222")
manager.add_member(member)
같은 아이디가 두 번 등록되지 않도록 검사합니다.
def find_member(self, member_id):
for member in self.members:
if member.member_id == member_id:
return member
return None
회원 등록 메서드에서 중복 여부를 검사합니다.
def add_member(self, member):
if self.find_member(member.member_id) is not None:
print("이미 등록된 아이디입니다.")
return False
self.members.append(member)
print("회원이 등록되었습니다.")
return True
등록된 회원 목록을 출력하는 메서드는 다음과 같습니다.
def print_members(self):
if len(self.members) == 0:
print("등록된 회원이 없습니다.")
return
for member in self.members:
print(member)
사용 예제는 다음과 같습니다.
manager.print_members()
회원 검색 메서드는 다음과 같습니다.
def find_member(self, member_id):
for member in self.members:
if member.member_id == member_id:
return member
return None
사용 예제는 다음과 같습니다.
member = manager.find_member("user01")
if member is not None:
print(member)
else:
print("회원을 찾을 수 없습니다.")
회원 아이디를 이용해 회원을 찾은 후 이름, 나이, 전화번호를 변경합니다.
def update_member(self, member_id, name, age, phone):
member = self.find_member(member_id)
if member is None:
print("회원을 찾을 수 없습니다.")
return False
member.name = name
member.age = age
member.ph
print("회원 정보가 수정되었습니다.")
return True
사용 예제는 다음과 같습니다.
manager.update_member("user01", "홍길동", 21, "010-9999-8888")
회원 삭제 메서드는 다음과 같습니다.
def delete_member(self, member_id):
member = self.find_member(member_id)
if member is None:
print("회원을 찾을 수 없습니다.")
return False
self.members.remove(member)
print("회원이 삭제되었습니다.")
return True
사용 예제는 다음과 같습니다.
manager.delete_member("user01")
파일에서 회원 정보를 읽은 후 전체 목록을 저장하기 위한 메서드입니다.
def set_members(self, members):
self.members = members
회원 목록 반환 메서드는 다음과 같습니다.
def get_members(self):
return self.members
MemberManager 클래스가 완성되었습니다.
class MemberManager:
def __init__(self):
self.members = []
def add_member(self, member):
if self.find_member(member.member_id) is not None:
print("이미 등록된 아이디입니다.")
return False
self.members.append(member)
print("회원이 등록되었습니다.")
return True
def print_members(self):
if len(self.members) == 0:
print("등록된 회원이 없습니다.")
return
for member in self.members:
print(member)
def find_member(self, member_id):
for member in self.members:
if member.member_id == member_id:
return member
return None
def update_member(self, member_id, name, age, phone):
member = self.find_member(member_id)
if member is None:
print("회원을 찾을 수 없습니다.")
return False
member.name = name
member.age = age
member.ph
print("회원 정보가 수정되었습니다.")
return True
def delete_member(self, member_id):
member = self.find_member(member_id)
if member is None:
print("회원을 찾을 수 없습니다.")
return False
self.members.remove(member)
print("회원이 삭제되었습니다.")
return True
def get_members(self):
return self.members
def set_members(self, members):
self.members = members
Menu 클래스는 프로그램 메뉴를 출력하고 사용자의 선택을 입력받습니다.
class Menu:
def print_menu(self):
print()
print("=" * 30)
print("회원관리 프로그램")
print("=" * 30)
print("1. 회원 등록")
print("2. 회원 전체 조회")
print("3. 회원 검색")
print("4. 회원 수정")
print("5. 회원 삭제")
print("6. 파일 저장")
print("7. 파일 불러오기")
print("0. 종료")
print("=" * 30)
사용 예제는 다음과 같습니다.
menu = Menu() menu.print_menu()
회원관리 프로그램
==============================
1. 회원 등록
2. 회원 전체 조회
3. 회원 검색
4. 회원 수정
5. 회원 삭제
6. 파일 저장
7. 파일 불러오기
0. 종료
==============================
메뉴 선택 메서드는 다음과 같습니다.
def input_menu(self):
return input("메뉴 선택 : ")
메뉴는 프로그램이 종료될 때까지 반복해서 출력합니다.
while True:
menu.print_menu()
choice = menu.input_menu()
if choice == "0":
print("프로그램을 종료합니다.")
break
Menu 클래스에 회원 정보를 입력받는 메서드를 추가할 수 있습니다.
def input_member(self):
member_id = input("아이디 : ")
name = input("이름 : ")
age = int(input("나이 : "))
ph : ")
return member_id, name, age, phone
반환된 여러 값을 각각의 변수에 저장합니다.
member_id, name, age, ph>
Menu 클래스가 완성되었습니다.
class Menu:
def print_menu(self):
print()
print("=" * 30)
print("회원관리 프로그램")
print("=" * 30)
print("1. 회원 등록")
print("2. 회원 전체 조회")
print("3. 회원 검색")
print("4. 회원 수정")
print("5. 회원 삭제")
print("6. 파일 저장")
print("7. 파일 불러오기")
print("0. 종료")
print("=" * 30)
def input_menu(self):
return input("메뉴 선택 : ")
def input_member(self):
member_id = input("아이디 : ")
name = input("이름 : ")
age = int(input("나이 : "))
ph : ")
return member_id, name, age, phone
def input_member_id(self):
return input("회원 아이디 : ")
FileManager 클래스는 회원 정보를 파일에 저장하고 파일에서 불러오는 기능을 담당합니다.
이번 프로젝트에서는 CSV 파일을 사용합니다.
import csv
class FileManager:
def __init__(self, filename):
self.filename = filename
파일 저장 메서드는 다음과 같습니다.
def save(self, members):
with open(self.filename, "w", newline="", encoding="utf-8-sig") as file:
writer = csv.writer(file)
writer.writerow(["아이디", "이름", "나이", "전화번호"])
for member in members:
writer.writerow(member.to_list())
print("파일에 저장되었습니다.")
파일 저장 예제는 다음과 같습니다.
file_manager = FileManager("members.csv")
file_manager.save(manager.get_members())
CSV 파일에 저장할 형식은 다음과 같습니다.
아이디,이름,나이,전화번호 user01,홍길동,20,010-1111-2222 user02,김철수,25,010-3333-4444
파일 읽기 메서드는 다음과 같습니다.
def load(self):
members = []
try:
with open(self.filename, "r", encoding="utf-8-sig") as file:
reader = csv.reader(file)
next(reader, None)
for row in reader:
if len(row) < 4:
continue
member = Member(row[0], row[1], int(row[2]), row[3])
members.append(member)
print("파일을 불러왔습니다.")
except FileNotFoundError:
print("저장된 회원 파일이 없습니다.")
return members
CSV 파일에서 읽은 데이터는 문자열입니다. 나이는 숫자로 사용해야 하므로 int()로 변환합니다.
FileManager 클래스가 완성되었습니다.
import csv
from member import Member
class FileManager:
def __init__(self, filename):
self.filename = filename
def save(self, members):
with open(self.filename, "w", newline="", encoding="utf-8-sig") as file:
writer = csv.writer(file)
writer.writerow(["아이디", "이름", "나이", "전화번호"])
for member in members:
writer.writerow(member.to_list())
print("파일에 저장되었습니다.")
def load(self):
members = []
try:
with open(self.filename, "r", encoding="utf-8-sig") as file:
reader = csv.reader(file)
next(reader, None)
for row in reader:
if len(row) < 4:
continue
member = Member(row[0], row[1], int(row[2]), row[3])
members.append(member)
print("파일을 불러왔습니다.")
except FileNotFoundError:
print("저장된 회원 파일이 없습니다.")
return members
지금까지 작성한 클래스를 각각의 파일로 분리합니다. 프로젝트 폴더 구조는 다음과 같습니다.
member_project/ │ ├─ main.py ├─ member.py ├─ manager.py ├─ menu.py ├─ filemanager.py └─ members.csv
각각의 파일에 대한 내용은 다음과 같습니다.
class Member:
def __init__(self, member_id, name, age, phone):
self.member_id = member_id
self.name = name
self.age = age
self.ph
def print_info(self):
print("아이디 :", self.member_id)
print("이름 :", self.name)
print("나이 :", self.age)
print("전화번호 :", self.phone)
def to_list(self):
return [self.member_id, self.name, self.age, self.phone]
def __str__(self):
return (f"아이디 : {self.member_id}, "
f"이름 : {self.name}, "
f"나이 : {self.age}, "
f"전화번호 : {self.phone}")
class MemberManager:
def __init__(self):
self.members = []
def add_member(self, member):
if self.find_member(member.member_id) is not None:
print("이미 등록된 아이디입니다.")
return False
self.members.append(member)
print("회원이 등록되었습니다.")
return True
def print_members(self):
if len(self.members) == 0:
print("등록된 회원이 없습니다.")
return
for member in self.members:
print(member)
def find_member(self, member_id):
for member in self.members:
if member.member_id == member_id:
return member
return None
def update_member(self, member_id, name, age, phone):
member = self.find_member(member_id)
if member is None:
print("회원을 찾을 수 없습니다.")
return False
member.name = name
member.age = age
member.ph
print("회원 정보가 수정되었습니다.")
return True
def delete_member(self, member_id):
member = self.find_member(member_id)
if member is None:
print("회원을 찾을 수 없습니다.")
return False
self.members.remove(member)
print("회원이 삭제되었습니다.")
return True
def get_members(self):
return self.members
def set_members(self, members):
self.members = members
class Menu:
def print_menu(self):
print()
print("=" * 30)
print("회원관리 프로그램")
print("=" * 30)
print("1. 회원 등록")
print("2. 회원 전체 조회")
print("3. 회원 검색")
print("4. 회원 수정")
print("5. 회원 삭제")
print("6. 파일 저장")
print("7. 파일 불러오기")
print("0. 종료")
print("=" * 30)
def input_menu(self):
return input("메뉴 선택 : ")
def input_member(self):
member_id = input("아이디 : ")
name = input("이름 : ")
age = int(input("나이 : "))
ph : ")
return member_id, name, age, phone
def input_member_id(self):
return input("회원 아이디 : ")
import csv
from member import Member
class FileManager:
def __init__(self, filename):
self.filename = filename
def save(self, members):
with open(self.filename, "w", newline="", encoding="utf-8-sig") as file:
writer = csv.writer(file)
writer.writerow(["아이디", "이름", "나이", "전화번호"])
for member in members:
writer.writerow(member.to_list())
print("파일에 저장되었습니다.")
def load(self):
members = []
try:
with open(self.filename, "r", encoding="utf-8-sig") as file:
reader = csv.reader(file)
next(reader, None)
for row in reader:
if len(row) < 4:
continue
member = Member(row[0], row[1], int(row[2]), row[3])
members.append(member)
print("파일을 불러왔습니다.")
except FileNotFoundError:
print("저장된 회원 파일이 없습니다.")
return members
- 객체지향 설계는 프로그램의 기능을 분석하고 클래스를 나누는 과정이다.
- 클래스를 역할별로 분리하여 코드의 가독성과 유지보수성을 높인다.
- UML을 사용하여 프로그램의 구조를 시각적으로 표현할 수 있다.
- 회원 관리 프로그램은 Member, MemberManager, Menu, FileManager 클래스로 구성된다.
- 각 클래스는 자신의 역할에 맞는 기능만 수행하도록 설계한다.