0. 학습 목표

→ 회원가입 정보를 JSON 파일에 저장하고, 비밀번호는 해시값으로 관리하는 과제를 이해합니다.

더보기

이번 과제에서 할 일

이번 과제에서는 기존 로그인 프로그램에 회원가입 View를 추가합니다.

사용자가 회원가입 화면에서 아이디, 비밀번호, 이름, 이메일, 전화번호를 입력하면 새 회원 정보가 member.json 파일에 저장되어야 합니다.

중요한 점은 비밀번호를 그대로 저장하지 않는 것입니다.

비밀번호는 password_hash 형태로 변환해서 저장해야 합니다.

구분 내용
핵심 개념 회원가입 정보를 파일에 저장하고, 비밀번호는 해시값으로 관리합니다.
실습 준비 PySide6, QTabWidget, QLineEdit, QPushButton, QLabel, JSON 파일, hashlib를 사용합니다.
최종 목표 회원가입한 사용자 정보가 member.json에 저장되고, 가입한 ID/PW로 로그인할 수 있도록 구현합니다.
제출 기한 X월 X일 X요일까지 제출하세요.
회원가입 View, MemberModel, MemberStorage, member.json이 연결되는 전체 구조

이번 과제의 핵심: 회원가입으로 새 회원을 추가하고, 비밀번호는 평문이 아니라 password_hash로 저장해야 합니다.

 

1. 왜 회원가입 기능이 필요할까?

→ 기존 로그인 프로그램은 미리 저장된 회원만 사용할 수 있었기 때문에 새 회원을 추가하는 기능이 필요합니다.

더보기

1.1 기존 프로그램의 한계

기존 프로그램에서는 회원 정보가 미리 준비되어 있었습니다.

예를 들어 member.json 파일에 test 회원이 이미 들어 있고, 사용자는 그 계정으로만 로그인할 수 있었습니다.

# 기존 member.json 예시

{
    "id": "test",
    "password_hash": "03ac674216f3e15c...",
    "name": "홍길동",
    "email": "test@test.com",
    "phone": "010-1234-5678"
}

이 구조는 로그인과 파일 저장을 이해하기에는 좋습니다.

하지만 새로운 사용자가 직접 회원가입을 할 수 없습니다.

상황 문제점
회원 정보가 1명만 있음 test 계정 외에는 로그인할 수 없습니다.
회원가입 화면이 없음 새 사용자가 직접 계정을 만들 수 없습니다.
여러 회원 목록이 없음 회원 여러 명을 관리하기 어렵습니다.

 

1.2 이번 과제에서 확장할 구조

이번 과제에서는 회원 1명만 저장하는 구조를 여러 회원을 저장하는 구조로 확장합니다.

또한 QTabWidget에 회원가입 View를 추가합니다.

# 기존 구조

QTabWidget
    ├── 로그인 View
    ├── 메인화면 View
    └── 프로필 View
# 새 구조

QTabWidget
    ├── 로그인 View
    ├── 회원가입 View
    ├── 메인화면 View
    └── 프로필 View

회원가입 View에서 새 회원 정보를 입력하면 MemberModel모델이 회원가입 처리를 담당합니다.

MemberStorage저장소는 변경된 회원 목록을 member.json 파일에 저장합니다.

문제의 핵심: 미리 만들어진 회원만 로그인하는 구조에서, 사용자가 직접 회원가입하고 로그인할 수 있는 구조로 확장해야 합니다.

 

2. 회원가입 화면 구조 설계하기

→ 회원가입 View에 필요한 입력칸과 버튼을 정리합니다.

더보기

2.1 회원가입 View에 필요한 입력 요소

회원가입 View에는 새 회원 정보를 입력할 수 있는 입력칸이 필요합니다.

비밀번호는 실수 방지를 위해 한 번 더 입력받습니다.

입력 항목 설명
아이디 로그인할 때 사용할 회원 ID입니다.
비밀번호 로그인할 때 사용할 비밀번호입니다.
비밀번호 확인 비밀번호를 한 번 더 입력해 같은지 확인합니다.
이름 회원 이름입니다.
이메일 회원 이메일입니다.
전화번호 회원 전화번호입니다.

 

2.2 회원가입 View 구현 조건

회원가입 View에는 입력칸과 회원가입 버튼, 결과 메시지 라벨이 있어야 합니다.

요소 조건
ID 입력칸 QLineEdit으로 구현합니다.
PW 입력칸 QLineEdit으로 구현하고 비밀번호처럼 보이도록 EchoMode를 설정합니다.
PW 확인 입력칸 PW와 같은지 검사합니다.
회원가입 버튼 clicked.connect(...)로 회원가입 처리 함수와 연결합니다.
메시지 라벨 회원가입 성공 또는 실패 이유를 출력합니다.

핵심 확인: 회원가입 View는 입력을 받는 역할만 하고, 실제 회원가입 처리는 MemberModel에게 요청해야 합니다.

 

3. 회원가입 Model 기능 설계하기

→ MemberModel에 회원가입, 중복 검사, 로그인 검증 기능을 추가합니다.

더보기

3.1 MemberModel에 필요한 기능

이번 과제에서는 MemberModel이 회원가입, 로그인, 프로필 수정을 모두 관리해야 합니다.

단, 화면 코드를 Model 안에 넣으면 안 됩니다.

MemberModel은 데이터와 기능만 담당해야 합니다.

기능 설명
register_member() 새 회원 정보를 members 목록에 추가합니다.
is_duplicate_id() 이미 존재하는 아이디인지 확인합니다.
check_login() 여러 회원 중 ID와 password_hash가 일치하는 회원을 찾습니다.
get_member_info() 현재 로그인한 회원 정보를 반환합니다.
update_profile() 현재 로그인한 회원의 이름, 이메일, 전화번호를 수정합니다.

 

3.2 회원가입 입력 검증 조건

회원가입 버튼을 눌렀을 때 바로 저장하면 안 됩니다.

먼저 입력값이 올바른지 확인해야 합니다.

검증 항목 조건
빈 값 검사 ID, PW, PW 확인, 이름, 이메일, 전화번호가 비어 있으면 가입할 수 없습니다.
비밀번호 확인 PW와 PW 확인 값이 다르면 가입할 수 없습니다.
아이디 중복 검사 이미 같은 ID가 있으면 가입할 수 없습니다.
비밀번호 해시 저장 PW는 그대로 저장하지 않고 password_hash로 저장해야 합니다.

주의할 점: 비밀번호는 절대 "pw": "1234" 형태로 저장하지 않고, 반드시 "password_hash": "..." 형태로 저장해야 합니다.

 

4. member.json 파일 구조 설계하기

→ 회원 1명 저장 구조를 여러 회원 목록 저장 구조로 확장합니다.

더보기

 

4.1 기존 파일 구조

기존 구조는 회원 1명의 정보만 저장했습니다.

# 기존 member.json 구조

{
    "id": "test",
    "password_hash": "03ac674216f3e15c...",
    "name": "홍길동",
    "email": "test@test.com",
    "phone": "010-1234-5678"
}

이 구조는 간단하지만 여러 회원을 저장하기 어렵습니다.

 

4.2 새 파일 구조

이번 과제에서는 여러 회원을 저장하기 위해 members 목록을 사용합니다.

# 새 member.json 구조

{
    "members": [
        {
            "id": "test",
            "password_hash": "03ac674216f3e15c...",
            "name": "홍길동",
            "email": "test@test.com",
            "phone": "010-1234-5678"
        },
        {
            "id": "kim",
            "password_hash": "a8b3f2...",
            "name": "김철수",
            "email": "kim@test.com",
            "phone": "010-9999-8888"
        }
    ]
}

회원가입을 하면 새 회원 딕셔너리가 members 목록에 추가되어야 합니다.

로그인할 때는 members 목록 안에서 입력한 ID와 password_hash가 일치하는 회원을 찾아야 합니다.

항목 설명
members 여러 회원 정보를 담는 리스트입니다.
id 로그인할 때 사용할 회원 아이디입니다.
password_hash 비밀번호를 해시로 변환한 값입니다.
name, email, phone 메인화면과 프로필 화면에 표시할 회원 정보입니다.

핵심 확인: 회원가입 과제에서는 회원 정보를 하나의 딕셔너리가 아니라 members 리스트 안에 여러 개의 딕셔너리로 저장해야 합니다.

 

5. 회원가입부터 로그인까지 동작 흐름 살펴보기

→ 회원가입 성공, 파일 저장, 로그인 성공, 프로필 수정 흐름을 단계별로 정리합니다.

더보기

 

5.1 회원가입 성공 흐름

회원가입 버튼을 눌렀을 때 성공하면 다음 순서로 동작해야 합니다.

# 회원가입 성공 흐름

회원가입 View에서 정보 입력
    ↓
회원가입 버튼 클릭
    ↓
빈 값 검사
    ↓
비밀번호와 비밀번호 확인 비교
    ↓
아이디 중복 검사
    ↓
비밀번호를 password_hash로 변환
    ↓
members 목록에 새 회원 추가
    ↓
member.json 파일에 저장
    ↓
회원가입 성공 메시지 출력
    ↓
로그인 View 탭으로 이동

회원가입이 성공하면 로그인 View로 이동하도록 구현하면 사용자가 바로 로그인할 수 있습니다.

 

5.2 회원가입 실패 흐름

입력값이 올바르지 않으면 회원가입을 진행하지 않습니다.

실패 이유를 메시지로 출력하고 회원가입 View에 그대로 머무릅니다.

실패 상황 출력 메시지 예시
빈 값이 있음 모든 값을 입력하세요.
비밀번호 확인 불일치 비밀번호가 서로 다릅니다.
아이디 중복 이미 사용 중인 아이디입니다.

 

5.3 가입한 회원으로 로그인하는 흐름

회원가입이 끝나면 가입한 ID와 PW로 로그인할 수 있어야 합니다.

# 가입한 회원 로그인 흐름

로그인 View에서 ID, PW 입력
    ↓
로그인 버튼 클릭
    ↓
입력한 PW를 hash_password()로 변환
    ↓
members 목록에서 같은 ID 찾기
    ↓
저장된 password_hash와 입력 PW 해시값 비교
    ↓
일치하면 로그인 성공
    ↓
현재 로그인한 회원 정보를 저장
    ↓
메인화면 View 탭으로 이동

로그인에 성공하면 현재 로그인한 회원 정보를 기준으로 메인화면과 프로필 화면이 갱신되어야 합니다.

 

5.4 프로필 수정 흐름

프로필 수정은 전체 회원이 아니라 현재 로그인한 회원에게만 적용되어야 합니다.

# 프로필 수정 흐름

프로필 View에서 이름, 이메일, 전화번호 수정
    ↓
수정하기 버튼 클릭
    ↓
현재 로그인한 회원 찾기
    ↓
해당 회원의 name, email, phone 수정
    ↓
member.json 파일에 저장
    ↓
메인화면 View와 프로필 View 갱신

중요: 여러 회원을 저장할 때는 프로필 수정이 모든 회원에게 적용되지 않도록, 현재 로그인한 회원만 찾아서 수정해야 합니다.

 

6. 구현 조건과 제출 전 체크리스트 정리하기

→ 과제에서 반드시 지켜야 할 조건과 제출 전 확인 항목을 정리합니다.

더보기

6.1 핵심 구현 조건

반드시 다음 조건을 지켜서 구현하세요.

번호 조건
1 QTabWidget에 회원가입 View를 추가합니다.
2 회원가입 View에서 ID, PW, PW 확인, 이름, 이메일, 전화번호를 입력받습니다.
3 회원가입 시 빈 값 검사를 수행합니다.
4 PW와 PW 확인 값이 같은지 검사합니다.
5 이미 존재하는 ID는 가입할 수 없도록 중복 검사를 합니다.
6 비밀번호는 그대로 저장하지 않고 password_hash로 저장합니다.
7 member.json에는 members 리스트 구조로 여러 회원을 저장합니다.
8 회원가입한 ID/PW로 로그인할 수 있어야 합니다.
9 로그인 성공 시 메인화면과 프로필 화면에 현재 로그인한 회원 정보가 출력되어야 합니다.
10 프로필 수정 시 현재 로그인한 회원 정보만 변경되어야 합니다.

 

6.2 권장 프로젝트 구조

프로젝트 구조는 아래처럼 구성하는 것을 권장합니다.

# 권장 프로젝트 구조

signup_login_hash_project/
    ├── main.py
    ├── member_model.py
    ├── member_storage.py
    ├── password_utils.py
    └── tab_window.py
파일 역할
main.py QApplication을 만들고 프로그램을 실행합니다.
member_model.py 회원가입, 로그인 검사, 프로필 수정을 담당합니다.
member_storage.py member.json 파일 저장과 불러오기를 담당합니다.
password_utils.py 비밀번호를 password_hash로 변환하는 함수를 담당합니다.
tab_window.py QTabWidget과 각 View 화면 구성을 담당합니다.

 

6.3 제출 전 확인 사항

제출하기 전에 아래 항목을 직접 확인하세요.

확인 항목 완료
회원가입 View가 추가되었는가?
ID, PW, PW 확인, 이름, 이메일, 전화번호 입력칸이 있는가?
빈 값이면 회원가입이 되지 않는가?
PW와 PW 확인이 다르면 회원가입이 되지 않는가?
중복 ID이면 회원가입이 되지 않는가?
비밀번호가 password_hash로 저장되는가?
member.json에 새 회원이 members 목록으로 추가되는가?
가입한 회원으로 로그인할 수 있는가?
로그인 후 메인화면과 프로필 화면에 해당 회원 정보가 보이는가?
프로필 수정 시 현재 로그인한 회원 정보만 수정되는가?
View마다 회원 정보를 따로 저장하지 않고 하나의 MemberModel을 공유하는가?

 

6.4 선택 구현과 심화 구현

기본 구현을 완료했다면 아래 기능을 추가로 구현해 볼 수 있습니다.

구분 내용
선택 구현 회원가입 성공 후 입력칸 초기화, 로그인 탭 자동 이동, 오류 메시지 자세히 표시
심화 구현 로그아웃 기능, 회원 탈퇴 기능, 비밀번호 변경 기능, salt를 추가한 비밀번호 해시 저장

기억할 문장: 회원가입 기능은 새 회원을 추가하는 기능이고, 비밀번호는 그대로 저장하지 않고 password_hash로 저장해야 합니다.

 

참고. 공식 문서로 확인하기

→ QTabWidget, JSON 저장, hashlib 사용법은 공식 문서에서 확인할 수 있습니다.

더보기

참고 문서

이번 과제에서 사용하는 주요 개념은 아래 공식 문서에서 더 자세히 확인할 수 있습니다.

참고: 이번 과제에서는 학습용으로 SHA-256 해시를 사용할 수 있습니다. 실제 서비스에서는 salt와 bcrypt, scrypt, argon2 같은 비밀번호 저장 전용 방식을 검토해야 합니다.