기능:
1. 회원 가입 (Create)
2. 회원 조회 (Read)
3. 회원 수정 (Update)
4. 회원 삭제 (Delete)
5. 전체 목록 (Read All)
세 클래스로 나눈 이유
Member — "무엇을 저장하는가"
데이터의 모양만 정의. id, name, email, age가 한 묶음이라는 사실을 코드로 표현한다.
이 클래스는 저장 방법도, 화면 출력 방법도 모름. 데이터 구조만 담당한다.
MemberRepository — "어떻게 저장하고 꺼내는가"
실제 데이터 관리를 전담. save(), findById(), delete() 같은 기능이 모두 여기 있다.
사용자 입력이 어떻게 들어오는지는 관심 없고, 그냥 데이터를 받아서 보관하고 꺼내주기만 한다.
MemberMain — "사용자와 어떻게 소통하는가"
사용자 입력을 받고, Repository에 일을 시키고, 결과를 출력한다.
데이터가 내부적으로 어떻게 저장되는지는 모름. 그냥 repo.save()를 호출할 뿐이다.
Member 코드
package collection;
import lombok.AllArgsConstructor;
import lombok.Data;
//자동으로 기본 생성자 만들어 주나?
@AllArgsConstructor
@Data
public class Member {
private int id;
private String name;
private String email;
private int age;
//필요하다면 직접 생성자 생성 가능
public Member(String name, String email, int age) {
this.name = name;
this.email = email;
this.age = age;
}
}
MemberRepository 코드
package collection;
import java.util.*;
//역할 - 데이터를 보관하고 관리하는 클래스
public class MemberRepository {
private List<Member> memberList = new ArrayList<>(); //전체 목록
private Map<Integer, Member> memberMap = new HashMap<>(); // ID -> 회원정보
private Set<String> emailSet = new HashSet<>(); // 이메일 중복 체크
//회원 가입하면 ID를 자동으로 1씩 증가하는 방법으로 회원에게 할당할 예정
private int nextId = 1;
//회원가입
public boolean save(String name, String email, int age) {
//이메일 중복 확인
if (emailSet.contains(email)) {
System.out.println("[오류] 이미 사용중인 이메일 입니다" + email);
return false;
}
Member member = new Member(nextId, name, email, age);
memberList.add(member);
memberMap.put(nextId, member);
emailSet.add(email);
nextId++;
System.out.println("[완료] 회원가입 : " + member.getName());
return true;
}
//ID로 회원 조회 -- 1 (입력) --> 반환 (Member)
public Member findById(int id) {
return memberMap.get(id);
}
//전체 회원 목록 조회 -- 받아야 할 정보? 모든 Member 정보 리턴 --? List 사용
public List<Member> findAll() {
return memberList;
}
//이름으로 회원 조회
public List<Member> findByName(String name) {
List<Member> result = new ArrayList<>();
for (Member member : memberList) {
if (member.getName().equalsIgnoreCase(name)) {
result.add(member);
}
}
return result;
}
//도전과제 나이 범위로 검색
// 1.전체 순회
public List<Member> findByAgeRange(int max, int min) {
List<Member> findAge = new ArrayList<>(); //3.잠시 어딘가에 저장
for (Member member : memberList) {
if (member.getAge() >= min && member.getAge() <= max) {// 2.전체 순회하면서 만약 조건이 맞다면 즉 max 보다 작거나 같고 min보다 크거나 같다면 true
findAge.add(member);//4.전체 순회 종료
}
}
return findAge;//5.결과값 반환
}
// 이메일로 회원 찾기
// 이메일 하나만 찾으면 됨 (유니크함) 리스트 쓸 필요 x
// public List<Member> findByEmail(String email) {
// List<Member> result = new ArrayList<>();
// for (Member member : memberList) {
// if (member.getEmail().equalsIgnoreCase(email)) {
// result.add(member);
// }
// }
// return result;
//
// }
public Member findByEmail(String email) {
//전체 순회 전에 존재 여부부터 확인 --> 빠르게 존재 여부 확인
if (emailSet.contains(email) == false) {
return null;
}
for (Member m : memberList) {
if (m.getEmail().equalsIgnoreCase(email)){
return m;
}
}
return null;
}
//회원 정보 수정
//id 기준으로 회원 정보 조회
//2. 새로운 이름 정보 필요
//3. 새로운 나이 정보 필요
//4. 이메일은 중복 처리 때문에 수정 불가하게 막을 예정.
public boolean update(int id, String newName, int newAge) {
//수정을 하려면 반드시 먼저 조회를 해야한다
Member member = memberMap.get(id);
if (member == null) {
System.out.println("존재하지 않는 회원입니다 ID : " + id);
return false;
}
member.setName(newName);
member.setAge(newAge);
System.out.println("[완료] tnwjdehla: " + member);
return true;
}
//회원 ID 번호로 삭제
public boolean delete(int id) {
//먼저 조회부터 하고 삭제하기
Member member = memberMap.get(id);
if (member == null) {
System.out.println("존재하지 않는 회원입니다 ID : " + id);
return false;
}
//list, map , set 에서 다 삭제 해줘야 하니 동기화 처리 중요
memberList.remove(id - 1);// 인덱스 번호로 삭제하기 때문에 보여지는 값에서 -1 (오류 발생 지점)
memberMap.remove(id);
emailSet.remove(member.getEmail());
System.out.println("삭제 됨 : " + member.getEmail());
return true;
}
//전체 회원 수
public int count() {
return memberList.size();
}
}
MemberMain 코드
package collection;
import java.util.List;
import java.util.Scanner;
public class MemberMain {
public static void main(String[] args) {
MemberRepository repo = new MemberRepository();
//샘플 데이터 만들어 보기
Member member1 = new Member("홍길동1", "a@naver.com", 10);
Member member2 = new Member("홍길동2", "b@naver.com", 22);
Member member3 = new Member("홍길동3", "c@naver.com", 44);
repo.save(member1.getName(), member1.getEmail(), member1.getAge());
repo.save(member2.getName(), member2.getEmail(), member2.getAge());
repo.save(member3.getName(), member3.getEmail(), member3.getAge());
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("\n=== 회원 관리 시스템 ===");
System.out.println("전체 회원: " + repo.count() + "명");
System.out.println("1. 회원 가입");
System.out.println("2. ID 로 조회");
System.out.println("3. 이름으로 조회");
System.out.println("4. 나이 범위로 조회");
System.out.println("5. 이메일로 조회");
System.out.println("6. 회원 수정");
System.out.println("7. 회원 삭제");
System.out.println("8. 전체 목록");
System.out.println("9. 종료");
System.out.print("선택 : ");
String choice = sc.nextLine();
if (choice.equals("1")) {
System.out.print("이름 : ");
String name = sc.nextLine();
System.out.print("이메일 : ");
String email = sc.nextLine();
System.out.print("나이 : ");
int age = Integer.parseInt(sc.nextLine());
repo.save(name.trim(), email.trim(), age);
//유효성 체크 -- 메모리나 DB 안에 들어가는 데이터들을 무결성을 위하면
//앞에서 뒤에서 들어오는 데이터가 유효한지 체크하는 코드를 반드시 작성해야한다.
} else if (choice.equals("2")) {
System.out.print("조회할 ID : ");
int id = Integer.parseInt(sc.nextLine());
Member member = repo.findById(id);
if (member != null) {
System.out.println("조회 결과: " + member);
} else {
System.out.println("해당 회원이 없습니다.");
}
} else if (choice.equals("3")) {
System.out.print("조회할 이름 : ");
String name = sc.nextLine();
List<Member> result = repo.findByName(name);
if (result.isEmpty()) {
System.out.println("해당 이름의 회원이 없습니다.");
} else {
for (Member m : result) {
System.out.println(m);
}
}
//나이 범위로 검색
} else if (choice.equals("4")) {
System.out.print("최소 나이 :");
int min = sc.nextInt();
System.out.print("최대 나이 :");
int max = sc.nextInt();
sc.nextLine();
List<Member> findAge = repo.findByAgeRange(max, min);
System.out.println("결과: ");
if (findAge.isEmpty()) {
System.out.println("해당 나이의 회원이 없습니다");
} else {
for (Member m : findAge) {
System.out.println(m);
}
}
//결과 조회 추가
} else if (choice.equals("5")) {
System.out.print("조회할 이메일 : ");
String email = sc.nextLine();
Member member = repo.findByEmail(email);
if (member != null){
System.out.println("조회 결과 : " + member);
}else {
System.out.println("없는 이메일 입니다");
}
} else if (choice.equals("6")) {
System.out.print("수정할 ID : ");
int id = Integer.parseInt(sc.nextLine());
System.out.print("새 이름 : ");
String newName = sc.nextLine();
System.out.print("새 나이 : ");
int newAge = Integer.parseInt(sc.nextLine());
repo.update(id, newName, newAge);
} else if (choice.equals("7")) {
System.out.print("삭제할 ID : ");
int id = Integer.parseInt(sc.nextLine());
repo.delete(id);
} else if (choice.equals("8")) {
System.out.println("\n=== 전체 회원 목록 ===");
List<Member> all = repo.findAll();
if (all.isEmpty()) {
System.out.println("등록된 회원이 없습니다.");
} else {
for (Member m : all) {
System.out.println(m);
}
}
} else if (choice.equals("9")) {
System.out.println("시스템을 종료합니다.");
break;
}
}
}
}