스크린샷 2025-08-19 오후 12.06.15.png

스크린샷 2025-08-19 오후 3.44.53.png

package com.haenin.section04.testapp.aggregate;

import java.io.Serializable;
import java.util.Arrays;

public class Member implements Serializable {
    private int memNO;
    private String id;
    private String pwd;
    private int age;
    private String[] hobbies;
    private BloodType bloodType;
    private AccountStatus accountStatus;

    public Member() {
    }

    /* 설명. 회원가입 시 사용자가 입력한 값을 지닌 Member 객체가 되기 위한 생성자 */

    public Member(String id, String pwd, int age, String[] hobbies, BloodType bloodType) {
        this.id = id;
        this.pwd = pwd;
        this.age = age;
        this.hobbies = hobbies;
        this.bloodType = bloodType;
    }

    public Member(int memNO, String id, String pwd, int age, String[] hobbies, BloodType bloodType, AccountStatus accountStatus) {
        this.memNO = memNO;
        this.id = id;
        this.pwd = pwd;
        this.age = age;
        this.hobbies = hobbies;
        this.bloodType = bloodType;
        this.accountStatus = accountStatus;
    }

    public int getMemNO() {
        return memNO;
    }

    public void setMemNO(int memNO) {
        this.memNO = memNO;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String[] getHobbies() {
        return hobbies;
    }

    public void setHobbies(String[] hobbies) {
        this.hobbies = hobbies;
    }

    public BloodType getBloodType() {
        return bloodType;
    }

    public void setBloodType(BloodType bloodType) {
        this.bloodType = bloodType;
    }

    public AccountStatus getAccountStatus() {
        return accountStatus;
    }

    public void setAccountStatus(AccountStatus accountStatus) {
        this.accountStatus = accountStatus;
    }

    @Override
    public String toString() {
        return "Member{" +
                "memNO=" + memNO +
                ", id='" + id + '\\'' +
                ", pwd='" + pwd + '\\'' +
                ", age=" + age +
                ", hobbies=" + Arrays.toString(hobbies) +
                ", bloodType=" + bloodType +
                ", accountStatus=" + accountStatus +
                '}';
    }
}

package com.haenin.section04.testapp.aggregate;

public enum BloodType {
    A, AB, B, O
}

package com.haenin.section04.testapp.aggregate;

public enum AccountStatus {
    ACTIVE, DEACTIVE
}

package com.haenin.section04.testapp.stream;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class MyObjectOutput extends ObjectOutputStream {
    public MyObjectOutput(OutputStream out) throws IOException {
        super(out);
    }

    @Override
    protected void writeStreamHeader() throws IOException {
    }
}

package com.haenin.section04.testapp.run;

import com.haenin.section04.testapp.aggregate.BloodType;
import com.haenin.section04.testapp.aggregate.Member;
import com.haenin.section04.testapp.service.MemberService;

import java.util.Scanner;

public class Application {

    private static final MemberService ms = new MemberService();

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(true){
            System.out.println("====== 회원 관리 프로그램 =====");
            System.out.println("1. 모든 회원 정보 보기");
            System.out.println("2. 회원 찾기");
            System.out.println("3. 회원 가입");
            System.out.println("4. 회원 정보 수정");
            System.out.println("5. 회원 탈퇴");
            System.out.println("9. 프로그램 종료");
            System.out.print("메뉴를 선택해 주세요: ");
            int input = sc.nextInt();

            /* 설명.
            *   조회: find
            *   추가: regist
            *   수정: modify
            *   삭제: remove
            * */
            switch (input){
                case 1: ms.findAllMembers(); break;
                case 2: ms.findMemberBy(Application.chooseMemNo()); break;
                case 3: ms.registMember(Application.signUp()); break;
                case 4: break;
                case 5: break;
                case 9:
                    System.out.println("프로그램이 종료됩니다.");
                    return;
                default:
                    System.out.println("번호를 잘못 입력하셨습니다.");
            }
        }
    }

    private static int chooseMemNo() {
        Scanner sc = new Scanner((System.in));
        System.out.println("해당 회원 번호를 입력하세요: ");
        return sc.nextInt();
    }

    private static Member signUp() {
        Member member = null;
        Scanner sc = new Scanner(System.in);
        System.out.print("아이디를 입력하세요: ");
        String id = sc.nextLine();

        System.out.print("패스워드를 입력하세요: ");
        String password = sc.nextLine();

        System.out.print("나이를 입력하세요: ");
        int age = sc.nextInt();
        sc.nextLine(); // 필기. 버퍼 제거용
        System.out.print("입력할 취미의 갯수를 입력하세요(숫자는 1이상): ");
        int length = sc.nextInt();
        sc.nextLine(); // 필기. 버퍼 제거용
        String[] hobbies = new String[length];
        for (int i = 0; i < length; i++) {
            System.out.print("취미" + (i+1) +"번째 취미를 입력하세요: ");
            hobbies[i] = sc.nextLine();;
        }

        BloodType bt = null;
        System.out.print("혈액형을 입력하세요(A, B, O, AB): ");
        String bType = sc.nextLine();
        switch (bType){
            case "A": bt = BloodType.A; break;
            case "B": bt = BloodType.B; break;
            case "O": bt = BloodType.O; break;
            case "AB": bt = BloodType.AB; break;
        }

        member = new Member(id, password, age, hobbies, bt);
        return member;
    }
}

package com.haenin.section04.testapp.service;

import com.haenin.section04.testapp.aggregate.AccountStatus;
import com.haenin.section04.testapp.aggregate.Member;
import com.haenin.section04.testapp.repository.MemberRepository;

import java.util.ArrayList;

/* 목표, 트랜잭션 처리(DB와의 CRUD 이후 성공 및 실패 여부 처리) 및 비즈니스 로직 담당 및 유효성 검사 */
public class MemberService {

//    private final MemberRepository memberRepository = new MemberRepository();
    private final MemberRepository memberRepository;

    public MemberService(){
        memberRepository = new MemberRepository();
    }
    public void findAllMembers() {
        ArrayList<Member> result = memberRepository.findALlmembers();

        if(!result.isEmpty()) {
            System.out.println("Service에서 조회 확인: ");
            for (Member member : result) {
                System.out.println("member = " + member);
            }
        }else{
            System.out.println("우리사이트 회원 없음");
        }
    }

    public void findMemberBy(int memNo) {
        Member findMember = memberRepository.findMemberBy(memNo);
        if(findMember != null){ // 회원이 조회 되는 경우
            System.out.println("회원 조회 성공: " + findMember);
        } else {                // 안되는 경우
            System.out.println(memNo + "번호의 회원은 존재하지 않습니다.");
        }
    }

    public void registMember(Member registMember) {
        /* 설명. 회원가입에서 입력받은 값을 제외하고 두 개의 데이터(회원번호, 상태) 추가 */
        /* 설명. 1.회원 번호 생성 */
        int lastNo = memberRepository.findLastMemberNo();
        registMember.setMemNO(lastNo + 1);
        /* 설명. 2.회원 활성화 상태 추가 */
        registMember.setAccountStatus(AccountStatus.ACTIVE);

        /* 설명. DML의 성공여부는 int 값으로 돌아옴(라이브러리) */
        int result = memberRepository.registMember(registMember);

        if (result == 1){
            System.out.println(registMember.getId() + "회원님 환영합니다!");
        }else {
            System.out.println("회원 가입 실패");
        }
    }
}

package com.haenin.section04.testapp.repository;

import com.haenin.section04.testapp.aggregate.AccountStatus;
import com.haenin.section04.testapp.aggregate.BloodType;
import com.haenin.section04.testapp.aggregate.Member;
import com.haenin.section04.testapp.stream.MyObjectOutput;

import java.io.*;
import java.util.ArrayList;

/* 설명. 데이터베이스(현재는 파일) 개념과 입출력을 위해 만들어진 계층이며 성공 데이터 또는 성공 / 실패 여부를 반환
*       (지금과 같이 주로 컬렉션으로 데이터를 관리함)*/
public class MemberRepository {

    /* 설명. 초기에 Member 파일이 없다면 만들어 더미데이터(dummy data)를 넣는다. */
    private final ArrayList<Member> memberList = new ArrayList<>();
    private final File file =
            new File("src/main/java/com/haenin/section04/testapp/db/memberDB.dat");
    // 필기. 파일객체로 만들면 파일이 존재하는지 exitst 확인가능

    /* 설명. 프로그램 구동 시 처음에 실행할 내용들 */
    public MemberRepository() {
        if(!file.exists()) {
            ArrayList<Member> defaultMemberList = new ArrayList<>();
            defaultMemberList.add(new Member(1,"user01","pass01",20,
                    new String[]{"발레", "수영"}, BloodType.A, AccountStatus.ACTIVE));
            defaultMemberList.add(new Member(2,"user02","pass02",10,
                    new String[]{"게임", "영화시청"}, BloodType.B, AccountStatus.ACTIVE));
            defaultMemberList.add(new Member(3,"user03","pass03",30,
                    new String[]{"음악감상", "독서", "영상"}, BloodType.AB, AccountStatus.ACTIVE));

            saveMembers(defaultMemberList);
        }
        loadMembers();
    }

    /* 설명. ArrayList<Member>를 받으면 파일로 컬렉션에 담긴 회원들을 출력하는 메소드 (덮어씌우는 기능) */
    private void saveMembers(ArrayList<Member> members) {
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
            for(Member member : members){
                oos.writeObject(member);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(oos!=null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    private void loadMembers() {
        try(ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)))) {
            while (true) {
                memberList.add((Member) ois.readObject());
            }
        }catch (EOFException e){
            System.out.println("회원 정보 읽어오기 완료");
        }
        catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        ;

    }
    public ArrayList<Member> findALlmembers() {
        return memberList;
    }

    public Member findMemberBy(int memNo) {
        for(Member member : memberList){
            if(member.getMemNO() == memNo){
                return member;
            }
        }
        return null;
    }

    public int findLastMemberNo() {
        return memberList.get(memberList.size()-1).getMemNO();
    }

    public int registMember(Member registMember) {

        MyObjectOutput moo = null;
        int result = 0;
        try {
            moo = new MyObjectOutput(new BufferedOutputStream(new FileOutputStream(file, true)));
            moo.writeObject(registMember);
            moo.flush();    //필기. 내부적으로 Buffered를 쓰고 있으니 객체 출력 강제화

            /* 설명. 컬렉션에 담긴 기존 회원을 지우고 다시 파일의 정보를 토대로 컬렉션이 회원으로 채워지도록 작성 */
            memberList.clear();
            loadMembers();
            
            result = 1;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if(moo != null) moo.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        return result;
    }
}