대학원 일기

java로 만드는 BoxOffice 영화 예매 프로그램: 회원관리 구현 본문

Computer programming/java

java로 만드는 BoxOffice 영화 예매 프로그램: 회원관리 구현

대학원생(노예) 2021. 12. 17. 23:56

이전글

2021.12.17 - [개발 공부/java] - java로 만드는 BoxOffice 영화 예매 프로그램: 준비 단계

 

 

개발도구: Intellij

기본 구조

- 첫 번째 선택지 = [1] 회원 가입, [2] 로그인 선택 기능

[1] 선택 → 사용자가 입력한 아이디, 비밀번호, 이름, 생년월일을 통해 회원 가입하고 유효성 검사를 실행

[2] 선택 → 로그인, 성공(박스오피스 메뉴) / 실패(로그인 재시작)

 

 

 

회원 관리 설계(DAO 패턴 구조)

DAO(Data Access Object)란?

DAO(Data Access Object): DB를 사용하여 데이터를 조회하거나 조작하는 기능을 모아둔 Object

즉, 데이터베이스 접근을 담당함.

 

DB 클래스

- Jackson 라이브러리를 통해 member 폴더에 회원 정보를 텍스트 파일로 저장함(DB 역할).

MemberDao 클래스

- 데이터를 DB에서 읽어오거나 DB에 데이터를 저장함.

MemberService 클래스

- MemberDao를 호출하여 DB에 처리 후, Controller로 반환함.

MemberController 클래스

- 사용자의 요청을 전달받아 요청의 처리를 담당하는 서비스를 호출함.

기능: 회원가입, 로그인

 

회원관리 클래스 다이어그램

 

소스 코드

public class DB {
    Global global;

    public Member getMemberByLoginId(String loginId) {
        List<Member> members = getMembers();

        for (Member member : members) {
            if (member.loginId.equals(loginId)) {
                return member;
            }
        }
        return null;
    }
    public Member getMemberByLoginPw(String loginId, String loginPw) {
        List<Member> members = getMembers();

        for (Member member : members) {
            if (member.loginId.equals(loginId)) {
                if (member.loginPw.equals(loginPw)){
                    return member;
                }
            }
        }
        return null;
    }

    List<Member> getMembers() {
        List<Member> members = new ArrayList<>();
        int lastId = getLastMemberId();

        for (int i = 1; i <= lastId; i++) {
            String filePath = "member/" + i + ".txt";
            Member member = readMemberFromJsonFile(filePath);
            if (member != null) {
                members.add(member);
            }
        }
        return members;
    }

    void updateLastArticleId(int lastMemberId) {
        global.lastMemberId = lastMemberId;

        writeGlobalJsonFile(global);

    }

    Member[] getMembersFromFiles() {
        Member[] members = new Member[100];

        int lastMemberId = getLastMemberId();

        int membersIndex = 0;
        for (int i = 1; i <= lastMemberId; i++) {
            String fileName = "member/" + i + ".txt";
            Member member = readMemberFromJsonFile(fileName);

            if (member != null) {
                members[membersIndex] = member;
                membersIndex++;
            }
        }
        return members;
    }

    void writeGlobalJsonFile(Global global) {
        ObjectMapper om = new ObjectMapper();

        try {
            om.writeValue(new File("member/global.txt"), global);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    void loadGlobal() {
        global = readGlobalFromJsonFile();
    }

    int getLastMemberId() {
        return global.lastMemberId;
    }

    Member readMemberFromJsonFile(String filePath) {
        ObjectMapper om = new ObjectMapper();
        Member member = null;

        try {
            member = om.readValue(new File(filePath), Member.class);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return member;
    }

    Global readGlobalFromJsonFile() {
        ObjectMapper om = new ObjectMapper();
        Global global = null;

        try {
            global = om.readValue(new File("member/global.txt"), Global.class);
        } catch (JsonParseException | JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // 파일 없으면 여기서 생성
            global = new Global();
            writeGlobalJsonFile(global);
        }

        return global;
    }

    void writeMemberJsonFile(String filePath, Member member) {
        ObjectMapper om = new ObjectMapper();
        try {
            om.writeValue(new File(filePath), member);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class Member {
    public int id;
    public String regDate;
    public String loginId;
    public String loginPw;
    public String loginBirth;
    public String regName;

    public Member() {

    }
    public Member(int id, String regDate, String loginId, String loginPw, String loginBirth, String regName) {
        super();
        this.id = id;
        this.regDate = regDate;
        this.loginId = loginId;
        this.loginPw = loginPw;
        this.regName = regName;
        this.loginBirth = loginBirth;
    }

    @Override
    public String toString() {
        return "Member [id=" + id + ", regDate=" + regDate + ", loginId=" + loginId + ", loginPw=" + loginPw + ", Name= " + regName +  ", Birth=" + loginBirth + "]";
    }
}
public class MemberDao {
    // Data Access Object: DB를 사용하여 데이터를 조회하거나 조작하는 기능을 모아둔 Object(클래스)
    DB db;
    Member[] members;
    int lastMemberIndex;
    int lastMemberId;

    MemberDao(DB db) {
        this.db = db;

        members = db.getMembersFromFiles();

        for (int i = 0; i < members.length; i++) {
            if (members[i] == null) {
                lastMemberIndex = i - 1;
                break;
            }
        }
        lastMemberId = db.getLastMemberId();
    }

    boolean isUsedloginId(String loginId) {
        Member member = db.getMemberByLoginId(loginId);

        return member != null;
    }
    boolean isUsedloginPw(String loginId, String loginPw) {
        Member member = db.getMemberByLoginPw(loginId, loginPw);
        return member != null;
    }

    void add(String loginId, String loginPw, String loginBirth, String regName) {
        int id = lastMemberId + 1;
        String regDate = Util.getNowDateStr();
        Member member = new Member(id, regDate, loginId, loginPw, loginBirth, regName);
        lastMemberIndex++;
        members[lastMemberIndex] = member;

        String memberFilePath = "member/" + member.id + ".txt";
        db.writeMemberJsonFile(memberFilePath, member);

        lastMemberId++;
        db.updateLastArticleId(lastMemberId);
    }
}
public class MemberService {
    MemberDao memberDao;

    MemberService(MemberDao memberDao) {
        this.memberDao = memberDao;
    }

    boolean join(String loginId, String loginPw, String loginBirth, String regName) {
        if (isUsedLoginId(loginId)) {
            return false;
        }

        memberDao.add(loginId, loginPw, loginBirth, regName);
        return true;
    }

    boolean isUsedLoginId(String loginId) {
        return memberDao.isUsedloginId(loginId);
    }

    boolean isUsedLoginPw(String loginId, String loginPw) {
        return memberDao.isUsedloginPw(loginId, loginPw);
    }
}
public class Main {
    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        DB db = new DB();
        db.loadGlobal();

        MemberDao memberDao = new MemberDao(db);
        MemberService memberService = new MemberService(memberDao);
        MemberController controller = new MemberController(scanner, memberService);

        label:
        while (true) {
            System.out.println("1. 회원가입");
            System.out.println("2. 로그인");
            System.out.println("3. 비회원 로그인");
            System.out.println("종료: exit\n");
            System.out.print("명령어) ");
            String command = scanner.nextLine();

            switch (command) {
                case "1":
                    controller.doCommandJoin();
                    break;
                case "2":
                    controller.doCommandLogin();
                    break;
                case "3":
                    controller.doNonLogin();
                    break;
                case "exit":
                    break label;
            }
        }
        scanner.close();
    }

    private static class MemberController {
        Scanner scanner;

        MemberService memberService;

        MemberController(Scanner scanner, MemberService memberService) {
            this.memberService = memberService;
            this.scanner = scanner;
        }

        public boolean isNumeric(String str) { // 숫자 검사기
            return Pattern.matches("^[0-9]*$", str);
        }

        public boolean isAlpha(String str) { // 영어 검사기
            return Pattern.matches("^[a-zA-Z]*$", str);
        }

        public boolean checkDate(String checkDate) {
            try {
                SimpleDateFormat dateFormatParser = new SimpleDateFormat("yyyyMMdd"); //검증할 날짜 포맷 설정
                dateFormatParser.setLenient(false); //false일경우 처리시 입력한 값이 잘못된 형식일 시 오류가 발생
                dateFormatParser.parse(checkDate); //대상 값 포맷에 적용되는지 확인
                return true;
            } catch (Exception e) {
                return false;
            }
        }

        public boolean isKorean(String str) { // 한국어 검사기
            return Pattern.matches("[가-힣]*$", str);
        }

        public boolean isAlphaNumeric(String str) { // 영문 + 숫자
            return Pattern.matches("[a-zA-Z0-9]*$", str);
        }

        void doNonLogin(){
            String logId = "Non-Name";
            BoxOffice.showMenu(logId);
        }

        void doCommandJoin() {
            System.out.println("\n== 회원가입 시작 ==");

            String loginId;
            String loginPw;
            String loginBirth;
            String regName;
            String loginPwConFirm;

            while (true) {
                System.out.print("회원가입 아이디 : ");
                loginId = scanner.nextLine().trim();

                if (loginId.length() == 0) {
                    System.out.println("회원가입 할 아이디를 입력해 주세요.");
                    continue;
                }
                if (loginId.length() < 2) {
                    System.out.println("회원가입 할 아이디를 2자 이상 입력해 주세요.");
                    continue;
                }
                boolean rsId = isAlphaNumeric(loginId);
                if (rsId) {
                    break;
                } else {
                    System.out.println("영문이나 숫자로만 입력해주세요.");
                }
            }

            while (true) {
                boolean loginPwValid = true;

                while (true) {
                    System.out.print("회원가입 비밀번호 : ");
                    loginPw = scanner.nextLine().trim();

                    if (loginPw.length() == 0) {
                        System.out.println("회원가입 할 비밀번호를 입력해 주세요.");
                        continue;
                    }

                    if (loginPw.length() < 2) {
                        System.out.println("비밀번호를 2자 이상 입력해 주세요.");
                        continue;
                    }
                    break;
                }

                while (true) {
                    System.out.print("회원가입 비밀번호 확인 : ");
                    loginPwConFirm = scanner.nextLine().trim();

                    if (loginPwConFirm.length() == 0) {
                        System.out.println("비밀번호 확인을 위해 설정한 비밀번호를 입력해 주세요.");
                        continue;
                    }
                    if (!loginPw.equals(loginPwConFirm)) {
                        System.out.println("입력한 비밀번호와 일치하지 않습니다.");
                        loginPwValid = false;
                        break;
                    }
                    break;
                }
                if (loginPwValid) {
                    break;
                }
            }
            while (true) {
                System.out.print("이름 : ");
                regName = scanner.nextLine().trim();
                boolean rsEngName = isAlpha(regName);
                boolean rsKorName = isKorean(regName);
                if (regName.length() == 0) {
                    System.out.println("이름을 입력해주세요.");
                } else if (rsEngName || rsKorName) {
                    break;
                } else {
                    System.out.println("올바르지 않은 형식입니다.\n");
                }
            }

            while (true) {
                System.out.print("생년월일(ex:20000411) : ");
                loginBirth = scanner.nextLine().trim();

                if (loginBirth.length() == 0) {
                    System.out.println("생년월일을 입력해 주세요.");
                    continue;
                }
                boolean rsNumBth = isNumeric(loginBirth);
                if (!rsNumBth) {
                    System.out.println("숫자만 입력해주세요.");
                    continue;
                }
                boolean rsBth = checkDate(loginBirth);
                if (rsBth) {
                    break;
                } else {
                    System.out.println("올바르지 않은 형식입니다.");
                }
            }
            boolean rs = memberService.join(loginId, loginPw, loginBirth, regName);

            if (rs) {
                System.out.println("회원가입 성공\n");
            } else {
                System.out.println("회원가입 실패\n");
            }
            System.out.println("== 회원가입 끝 ==\n");
        }

        void doCommandLogin() {
            System.out.println("\n== 로그인 시작 ==");
            while (true) {
                System.out.print("아이디 : ");
                String logId = scanner.nextLine();
                boolean rsId = memberService.isUsedLoginId(logId);
                if (rsId) {
                    System.out.print("비밀번호 : ");
                    String logPw = scanner.nextLine();
                    boolean rsPw = memberService.isUsedLoginPw(logId, logPw);
                    if (rsPw) { // 비밀번호가 맞을 경우 -> 영화 메뉴로 이동
                        System.out.println("로그인 성공");
                        BoxOffice.showMenu(logId);
                        break;
                    } else {
                        System.out.println("잘못된 비밀번호입니다. 다시 시도해주세요.\n");

                    }
                } else {
                    System.out.println("존재하지 않은 아이디입니다. 다시 입력해주세요.\n");
                }
            }
            System.out.println("== 로그아웃 ==\n");
        }
    }
}
public class Global {
    public int lastMemberId;
    Global() {
        lastMemberId = 0;
    }
}

public class Util {
    static String getNowDateStr() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat Date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return Date.format(cal.getTime());
    }
}

 

마치며

DAO 패턴을 이용하여 사용자가 회원가입과  로그인하는 기능을 만들었다. 다음에는 영화 OPEN API를 가져와보겠다.

Comments