PySide6 Model/View 기반 회원관리 프로그램 구현
이번 실습에서는 PySide6와 Model/View 구조를 활용하여 회원가입, 로그인, 메인화면, 프로필 수정 기능을 구현하였다.
핵심은 회원 정보를 각 화면에 따로 저장하지 않고, MemberModel 하나에서 관리하도록 구성한 점이다.
MemberModel
└── 회원 정보 관리
Login View
└── 로그인 처리
SignUp View
└── 회원가입 처리
Main View
└── 로그인한 회원 정보 출력
Profile View
└── 회원 정보 수정
1. 프로젝트 구조
프로젝트는 다음과 같이 파일을 나누어 구성하였다.
PythonProject4/
├── main.py
├── main_window.py
├── member_model.py
├── login_view.py
├── sign_up.py
├── main_view.py
├── profile_view.py
└── member.json
| 파일명 | 역할 |
|---|---|
| main.py | 프로그램 실행 파일 |
| main_window.py | 전체 탭 화면 관리 |
| member_model.py | 회원 정보 저장, 로그인 검사, 프로필 수정 처리 |
| login_view.py | 로그인 화면 구성 |
| sign_up.py | 회원가입 화면 구성 |
| main_view.py | 로그인한 회원 정보 출력 |
| profile_view.py | 회원 정보 수정 |
2. main.py
main.py는 프로그램 실행만 담당하도록 구성하였다.
import sys
from PySide6.QtWidgets import QApplication
from main_window import MainWindow
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
3. MemberModel 구현
MemberModel은 회원 정보를 저장하고 관리하는 Model 클래스이다. 회원가입 시 입력한 정보를 member.json에 저장하고, 로그인 시 입력한 아이디와 비밀번호를 검사하도록 구현하였다.
비밀번호는 그대로 저장하지 않고 hashlib를 사용해 SHA256 Hash 값으로 변환하여 저장하였다.
member_model.py
import json
import hashlib
class MemberModel:
def __init__(self):
# 회원 정보를 저장할 JSON 파일명
self.file_name = "member.json"
# 현재 로그인한 회원 정보를 저장할 변수
self.current_member = None
# 프로그램 시작 시 JSON 파일에서 회원 목록 불러오기
self.load_members()
def load_members(self):
# member.json 파일에 저장된 회원 목록을 불러오는 함수
try:
with open(self.file_name, "r", encoding="utf-8") as file:
self.members = json.load(file)
except:
# 파일이 없거나 읽기 실패 시 빈 리스트로 시작
self.members = []
def save_members(self):
# 현재 회원 목록을 member.json 파일에 저장하는 함수
with open(self.file_name, "w", encoding="utf-8") as file:
json.dump(
self.members,
file,
ensure_ascii=False,
indent=4
)
def register_member(self, user_id, user_pw, name, email, phone):
# 이미 존재하는 아이디인지 중복 검사
for member in self.members:
if member["id"] == user_id:
return False
# 비밀번호를 SHA256 Hash 값으로 변환
password_hash = hashlib.sha256(
user_pw.encode()
).hexdigest()
# 새 회원 정보 생성
new_member = {
"id": user_id,
"pw": password_hash,
"name": name,
"email": email,
"phone": phone
}
# 회원 목록에 새 회원 추가
self.members.append(new_member)
# JSON 파일에 저장
self.save_members()
return True
def check_login(self, input_id, input_pw):
# 입력한 비밀번호를 Hash 값으로 변환
password_hash = hashlib.sha256(
input_pw.encode()
).hexdigest()
# 회원 목록에서 아이디와 비밀번호가 일치하는 회원 찾기
for member in self.members:
if member["id"] == input_id and member["pw"] == password_hash:
# 로그인 성공 시 현재 로그인 회원으로 저장
self.current_member = member
return True
return False
def get_member_info(self):
# 현재 로그인한 회원 정보를 반환
return self.current_member
def update_profile(self, name, email, phone):
# 현재 로그인한 회원이 있을 때만 수정
if self.current_member:
self.current_member["name"] = name
self.current_member["email"] = email
self.current_member["phone"] = phone
# 수정된 정보를 JSON 파일에 저장
self.save_members()
4. 회원가입 View 구현
회원가입 View에서는 아이디, 비밀번호, 비밀번호 확인, 이름, 이메일, 전화번호를 입력받는다.
한 칸이라도 빈칸이 있으면 경고창을 출력하고, 비밀번호와 비밀번호 확인 값이 다르면 회원가입이 진행되지 않도록 구현하였다.
sign_up.py
from PySide6.QtWidgets import (
QWidget, QVBoxLayout, QLabel, QLineEdit,
QPushButton, QMessageBox, QFormLayout
)
from PySide6.QtCore import Qt
class SignUpView(QWidget):
def __init__(self, member_model, tab_widget, parent=None):
super().__init__(parent)
# MemberModel과 QTabWidget 저장
self.member_model = member_model
self.tab_widget = tab_widget
title_label = QLabel("회원가입")
title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.line_edit_id = QLineEdit()
self.line_edit_id.setPlaceholderText("아이디를 입력하세요")
self.line_edit_pw = QLineEdit()
self.line_edit_pw.setPlaceholderText("비밀번호를 입력하세요")
self.line_edit_pw.setEchoMode(QLineEdit.EchoMode.Password)
self.line_edit_pw_check = QLineEdit()
self.line_edit_pw_check.setPlaceholderText("비밀번호를 다시 입력하세요")
self.line_edit_pw_check.setEchoMode(QLineEdit.EchoMode.Password)
self.line_edit_name = QLineEdit()
self.line_edit_name.setPlaceholderText("이름을 입력하세요")
self.line_edit_email = QLineEdit()
self.line_edit_email.setPlaceholderText("이메일을 입력하세요")
self.line_edit_phone = QLineEdit()
self.line_edit_phone.setPlaceholderText("전화번호를 입력하세요")
register_button = QPushButton("가입 완료")
register_button.clicked.connect(self.register_button_clicked)
form_layout = QFormLayout()
form_layout.addRow("아이디 :", self.line_edit_id)
form_layout.addRow("비밀번호 :", self.line_edit_pw)
form_layout.addRow("비밀번호 확인 :", self.line_edit_pw_check)
form_layout.addRow("이름 :", self.line_edit_name)
form_layout.addRow("이메일 :", self.line_edit_email)
form_layout.addRow("전화번호 :", self.line_edit_phone)
layout = QVBoxLayout()
layout.addStretch()
layout.addWidget(title_label)
layout.addLayout(form_layout)
layout.addWidget(register_button)
layout.addStretch()
self.setLayout(layout)
def register_button_clicked(self):
# 입력창 값 가져오기
user_id = self.line_edit_id.text()
user_pw = self.line_edit_pw.text()
user_pw_check = self.line_edit_pw_check.text()
name = self.line_edit_name.text()
email = self.line_edit_email.text()
phone = self.line_edit_phone.text()
# 빈칸 검사
if (
user_id.strip() == "" or
user_pw.strip() == "" or
user_pw_check.strip() == "" or
name.strip() == "" or
email.strip() == "" or
phone.strip() == ""
):
QMessageBox.warning(
self,
"회원가입 실패",
"빈칸을 채워주세요."
)
return
# 비밀번호 확인 검사
if user_pw != user_pw_check:
QMessageBox.warning(
self,
"회원가입 실패",
"비밀번호가 일치하지 않습니다."
)
return
# MemberModel에 회원가입 요청
result = self.member_model.register_member(
user_id,
user_pw,
name,
email,
phone
)
# 회원가입 성공
if result:
QMessageBox.information(
self,
"회원가입 완료",
"회원가입이 완료되었습니다."
)
self.clear_inputs()
# 회원가입 완료 후 회원가입 탭 비활성화
self.tab_widget.setTabEnabled(1, False)
# 로그인 탭으로 이동
self.tab_widget.setCurrentIndex(0)
# 중복 아이디인 경우
else:
QMessageBox.warning(
self,
"회원가입 실패",
"이미 사용 중인 아이디입니다."
)
def clear_inputs(self):
# 회원가입 입력창 초기화
self.line_edit_id.clear()
self.line_edit_pw.clear()
self.line_edit_pw_check.clear()
self.line_edit_name.clear()
self.line_edit_email.clear()
self.line_edit_phone.clear()
5. Login View 구현
Login View에서는 회원가입한 아이디와 비밀번호로 로그인할 수 있도록 구현하였다. 로그인에 성공하면 메인화면 탭으로 이동하고, 실패하면 경고창을 출력하도록 구성하였다.
login_view.py
from PySide6.QtWidgets import (
QWidget, QVBoxLayout, QPushButton, QLabel,
QLineEdit, QMessageBox, QFormLayout
)
class Login(QWidget):
def __init__(self, member_model, tab_widget, main_window):
super().__init__()
self.member_model = member_model
self.tab_widget = tab_widget
self.main_window = main_window
title_label = QLabel("회원 로그인")
self.line_edit_id = QLineEdit()
self.line_edit_id.setPlaceholderText("아이디를 입력하세요")
self.line_edit_pw = QLineEdit()
self.line_edit_pw.setPlaceholderText("비밀번호를 입력하세요")
self.line_edit_pw.setEchoMode(QLineEdit.EchoMode.Password)
login_button = QPushButton("로그인")
login_button.clicked.connect(self.login_button_clicked)
signup_button = QPushButton("회원가입")
signup_button.clicked.connect(self.signup_button_clicked)
form_layout = QFormLayout()
form_layout.addRow("아이디 :", self.line_edit_id)
form_layout.addRow("비밀번호 :", self.line_edit_pw)
layout = QVBoxLayout()
layout.addWidget(title_label)
layout.addLayout(form_layout)
layout.addWidget(login_button)
layout.addWidget(signup_button)
self.setLayout(layout)
def login_button_clicked(self):
# 로그인 입력값 가져오기
input_id = self.line_edit_id.text()
input_pw = self.line_edit_pw.text()
# MemberModel을 통해 로그인 검사
if self.member_model.check_login(input_id, input_pw):
QMessageBox.information(
self,
"로그인 성공",
"로그인에 성공하였습니다."
)
# MainWindow의 로그인 성공 처리 함수 실행
self.main_window.login_success()
else:
QMessageBox.warning(
self,
"로그인 실패",
"아이디 또는 비밀번호가 올바르지 않습니다."
)
self.line_edit_id.clear()
self.line_edit_pw.clear()
self.line_edit_id.setFocus()
def signup_button_clicked(self):
# 회원가입 버튼 클릭 시 회원가입 탭 활성화 후 이동
self.tab_widget.setTabEnabled(1, True)
self.tab_widget.setCurrentIndex(1)
6. MainWindow 구성
MainWindow에서는 QTabWidget을 사용하여 로그인, 회원가입, 메인화면, 프로필 화면을 구성하였다.
로그인 전에는 메인화면과 프로필 화면에 접근할 수 없도록 제한하고, 회원가입 탭도 회원가입 버튼을 눌렀을 때만 활성화되도록 구현하였다.
main_window.py
from PySide6.QtWidgets import QMainWindow, QTabWidget, QMessageBox
from member_model import MemberModel
from login_view import Login
from sign_up import SignUpView
from main_view import MainView
from profile_view import ProfileView
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Model/View 회원관리")
self.resize(600, 400)
# 로그인 상태 저장
self.is_login = False
# MemberModel 생성
self.member_model = MemberModel()
# 탭 위젯 생성
self.tab_widget = QTabWidget()
self.setCentralWidget(self.tab_widget)
self.main_tab = MainView(self.member_model)
self.profile_tab = ProfileView(
self.member_model,
self.main_tab,
self.tab_widget
)
self.sign_up_tab = SignUpView(
self.member_model,
self.tab_widget
)
self.login_tab = Login(
self.member_model,
self.tab_widget,
self
)
self.tab_widget.addTab(self.login_tab, "로그인")
self.tab_widget.addTab(self.sign_up_tab, "회원가입")
self.tab_widget.addTab(self.main_tab, "메인화면")
self.tab_widget.addTab(self.profile_tab, "프로필")
# 처음에는 회원가입 탭 비활성화
self.tab_widget.setTabEnabled(1, False)
# 탭 이동 시 접근 권한 검사
self.tab_widget.currentChanged.connect(
self.check_tab_access
)
self.tab_widget.setCurrentIndex(0)
def check_tab_access(self, index):
# 로그인하지 않은 상태에서 메인화면/프로필 접근 제한
if self.is_login == False and index not in [0, 1]:
QMessageBox.warning(
self,
"접근 제한",
"로그인을 먼저 해주세요."
)
self.tab_widget.setCurrentIndex(0)
def login_success(self):
# 로그인 상태 변경
self.is_login = True
# 메인화면과 프로필 화면 갱신
self.main_tab.update_view()
self.profile_tab.update_view()
# 메인화면 탭으로 이동
self.tab_widget.setCurrentIndex(2)
7. JSON 파일 저장


회원 정보를 저장하는 JSON 파일 구성
회원가입 시 입력한 회원 정보를 저장하며 프로그램 재실행 후에도 회원 정보를 유지하도록 구현
( 파일 버튼 클릭 후 -> 원하는 파일명.JSON -> [ ] 입력해줘야 안에 내용이 입력이 됨.
8. 구현 결과 정리
- 회원가입 탭을 추가하였다.
- 아이디, 비밀번호, 비밀번호 확인, 이름, 이메일, 전화번호를 입력받도록 구현하였다.
- 빈칸이 있을 경우 경고창을 출력하도록 구현하였다.
- 비밀번호와 비밀번호 확인 값이 다르면 회원가입이 되지 않도록 구현하였다.
- 중복 아이디는 가입할 수 없도록 구현하였다.
- 비밀번호는 Hash 값으로 변환하여 저장하였다.
- 회원 정보는 member.json에 저장되도록 구현하였다.
- 회원가입한 아이디와 비밀번호로 로그인할 수 있도록 구현하였다.
- 로그인 성공 시 현재 로그인한 회원 정보가 메인화면과 프로필 화면에 출력되도록 구현하였다.
- 프로필 수정 시 현재 로그인한 회원 정보만 변경되도록 구현하였다.
회원 정보는 View마다 따로 저장하지 않고, MemberModel에서 관리하도록 구현하였다.
회원가입, 로그인, 프로필 수정 기능이 모두 하나의 Model을 기준으로 동작하도록 구성하였다.
'개발일지' 카테고리의 다른 글
| 호텔 관리 시스템(PMS) 개발 프로젝트 - 06/10~06/16 (0) | 2026.06.16 |
|---|---|
| 호텔 관리 시스템(PMS) 개발 프로젝트 - 기능 구현 및 화면 소개 (0) | 2026.06.16 |
| 스마트 객실 관리 시스템 프로젝트 완성 (0) | 2026.06.08 |
| 호텔 객실 에너지 효율 향상을 위한 스마트 객실 환경 관리 시스템 개발일지 (0) | 2026.06.02 |
| [개발일지] 객체지향 프로그래밍과 PySide6 구조 ,Qt Creator 이해 (0) | 2026.05.15 |