본문 바로가기
BACK-END/JAVA

[JAVA]주소록 CRUD 프로그램 만들기

by 썬키 2022. 12. 28.

1. 개요

생성자를 이용해서 객체를 생성하고 Scanner 객체를 이용해서 간단한 주소록 CRUD 프로그램을 작성하였다.

아직 DB 관련 수업은 수강하지 않아서 생성된 데이터들은 txt 형식의 파일에 저장되는 방식으로 구현하였다.

컬렉션 프레임워크는 사용하지 않았다.

 

2. DTO, DAO, FileProc, Main

1) DTO(Data Transfer Object)

: DTO 클래스는 주소록에 데이터 등록을 하기 위해 필요한 필드와 JAVA의 객체지향특성 중 하나인

캡슐화에 의거하여 필드에 직접적인 접근을 막기 위해 getter, setter 메서드가 구현된 클래스이다.

(* 때에 따라 DTO가 아닌 VO를 쓰기도 하는데, DTO는 쓰기ㆍ읽기가 가능하고 VO는 읽기 전용이라고 한다.)

 

2) DAO(Data Access Object)

: 데이터에 접근하고 편집하는 클래스. 핵심적인 로직들이 담겨있는 클래스이다.

 

3) FileProc

: DAO에서 주소록에 등록된 데이터를 배열로 만들어 매개변수로 전달하면 txt형식의 파일을 생성해서

데이터를 저장해줄 메소드가 담겨있는 클래스이다.

 

4) Main

: DAO에서 작성한 메서드들을 호출해줄 클래스이다.

 

3. 소스

 

- DTO

public class HumanDto {
	
    // 외부로부터 직접접근을 막기위해 private을 사용
	private String name;		// 이름
	private int age;			// 나이
	private String tel;			// 전화번호
	private String address;		// 주소
	private String memo;		// 메모
	
	/* 기본 생성자
    생성자가 하나도 없을 시에, 컴파일러가 자동으로 기본 생성자를 추가해주는데
    아래에 매개변수가 있는 생성자가 존재하므로 기본 생성자를 추가해준다.
    */
	public HumanDto() {
		
	}
	
	// 매개변수가 있는 생성자
	public HumanDto(String name, int age, String tel, String address, String memo) {
		this.name = name;
		this.age = age;
		this.tel = tel;
		this.address = address;
		this.memo = memo;
	}


	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public int getAge() {
		return age;
	}


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


	public String getTel() {
		return tel;
	}


	public void setTel(String tel) {
		this.tel = tel;
	}


	public String getAddress() {
		return address;
	}


	public void setAddress(String address) {
		this.address = address;
	}


	public String getMemo() {
		return memo;
	}


	public void setMemo(String memo) {
		this.memo = memo;
	}


	@Override
	public String toString() {
		return name + "*" + age + "*" + tel + "*" + address + "*" + memo;
	}
}

toString 메서드를 위와 같이 오버라이드 한 이유는 가독성 있게 데이터를 저장하기 위함이다.

DTO가 완성이 되었으면 HumanDto를 가지고 DAO에서 객체 배열을 생성한다.

 

- DAO

public class AddressDao {
	
	Scanner scanner = new Scanner(System.in);
	
	// humanArr 배열 100개 생성
	private HumanDto[] humanArr = new HumanDto[100];
	private int count;
	
	// File 객체 생성
	private FileProc fp = null;
	
	public AddressDao() {
    
		fp = new FileProc("address");
		
		humanArr[0] = new HumanDto("홍길동", 24, "123-4567", "서울시", "지인1");
		humanArr[1] = new HumanDto("성춘향", 16, "234-5678", "경기도", "지인1");
		humanArr[2] = new HumanDto("일지매", 22, "345-6789", "전라도", "지인1");
		humanArr[3] = new HumanDto("홍길동", 24, "123-4567", "광주", "지인1");
		
		count = 0;
        
	}
	
	// 검색
	public void select() {
		System.out.print("검색할 지인의 이름 : ");
		String name = scanner.next();
		
		int index = search(name);
		
		if(index == -1) {
			System.out.println("지인의 정보를 찾을 수 없습니다.");
		}
	}
	// 자주 쓰는 메소드이므로, 함수로 따로 빼서 정의
	private int search(String name) {
		int index = -1;
		for (int i = 0; i < humanArr.length; i++) {
			if(humanArr[i] != null && name.equals(humanArr[i].getName())) {
				index = i;
				System.out.println(humanArr[index].toString());
				break;
			}  
		}
		return index;
	}
	
	// 추가
	public void insert() {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		System.out.println("지인을 추가합니다.");
		System.out.print("이름 : ");
		String name = scanner.next();

		System.out.print("나이 : ");
		int age = scanner.nextInt();
		
		System.out.print("연락처 : ");
		String tel = scanner.next();
		
		System.out.print("주소 : ");
		String address = "";
		try {
			address = br.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.print("메모 : ");
		String memo = scanner.next();
		
		humanArr[count] = new HumanDto(name, age, tel, address, memo);
		count++;
	}

	// 수정(연락처, 주소만 수정가능)
	public void update() {
		System.out.print("수정할 지인의 이름 : ");
		String name = scanner.next();
		
		int index = -1;
		
		for (int i = 0; i < humanArr.length; i++) {
			if(name.equals(humanArr[i].getName())) {
				index = i;
				
				System.out.println("1. 연락처 수정");
				System.out.println("2. 주소 수정");
				System.out.println("3. 취소");
				System.out.print(" >> ");
				
				int choice = scanner.nextInt();
				
				if(choice == 1) {
					System.out.print("연락처를 수정해 주세요 > ");
					String tel = scanner.next();
					humanArr[i].setTel(tel);
					System.out.println("성공적으로 변경 되었습니다!");
					break;
				} else if(choice == 2) {
					System.out.print("주소를 수정해 주세요 > ");
					String address = scanner.next();
					humanArr[i].setAddress(address);
					System.out.println("성공적으로 변경 되었습니다!");
					break;
				} else {
					break;
				}
			} else if(index == -1) {
				System.out.printf("%s을(를) 찾을 수 없습니다." , name);
				break;
			}
		}
	}
	
	// 삭제
	public void delete() {
		System.out.print("삭제할 지인의 이름 : ");
		String name = scanner.next();
		
		// 검색
		int index = search(name);
		
		if(index == -1) {
			System.out.println("해당 지인의 정보를 찾을 수 없습니다.");
		} else {
			// 삭제
			humanArr[index].setName("");
			humanArr[index].setAge(0);
			humanArr[index].setTel("");
			humanArr[index].setAddress("");
			humanArr[index].setMemo("");
			
			System.out.println("지정한 지인을 삭제하였습니다.");
		}
		
	}
	
	public void allDataPrint() {
		for (int i = 0; i < humanArr.length; i++) {
			if(humanArr[i] != null && !(humanArr[i].getName().equals(""))) {
				System.out.println(humanArr[i].toString());
			}
		}
	}
	
	public void fileSave() {
    	// humanArr에 있는 데이터만큼 count를 증가시킨다.
		int count = 0;
		for (int i = 0; i < humanArr.length; i++) {
			if(humanArr[i] != null && !(humanArr[i].getName().equals(""))) {
				count++;
			}
		}
        // 그 count를 가지고 매개변수로 넘겨줄 dataArr를 생성한다.
		String[] dataArr = new String[count];

		// count 초기화
		count = 0;
		for (int i = 0; i < humanArr.length; i++) {
			if(humanArr[i] != null && !(humanArr[i].getName().equals(""))) {
				dataArr[count] = humanArr[i].toString();
				count++;
			}
		}
		fp.write(dataArr);
		System.out.println("파일에 저장되었습니다.");
	}
	
}

 

-Main

public class MainClass {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner scanner = new Scanner(System.in);
		
		AddressDao dao = new AddressDao();
		
		// menu
		loop : 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("6. 데이터 저장");
			System.out.println("7. 종료");
			
			System.out.print(">> ");
			int choice = scanner.nextInt();
			
			switch(choice) {
				case 1 :
					dao.insert();
					break;
				case 2 :
					dao.delete();
					break;
				case 3 :
					dao.select();
					break;
				case 4 :
					dao.update();
					break;
				case 5 :
					dao.allDataPrint();
					break;
				case 6 :
					dao.fileSave();
					break;
				case 7 : 
					break loop;
				default :
					System.out.println("잘못 입력하셨습니다.");
					break;
			} // end of switch
		
		} // end of while
		
	} // end of main
} // end of class

7.종료를 선택하면 while문을 아예 빠져나오기 위해 while문 앞에 라벨을 붙였다.

 

- FileProc

public class FileProc {
	
	private File file = null;
	
	public FileProc(String fileName) {
		file = new File("c:\\tmp\\" + fileName + ".txt");
		
		try {
			if(file.createNewFile()) {
				System.out.println("파일이 생성되었습니다.");
			} else {
				System.out.println("파일이 이미 존재합니다.");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public void write(String[] data) {
		
		try {
			PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
			
			for (int i = 0; i < data.length; i++) {
				pw.println(data[i]);
			}
			
			pw.close();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
}

4. 테스트

token이나 replace를 이용해 수정하면 더 좋을듯하다.

5. 개선할 점

: 오로지 배열만을 이용하여 구현하는 프로그램이다보니, new HumanDto[100] 으로 인하여 메모리 낭비를 많이 하게 되었다. 컬렉션 프레임워크를 배우면 가변 배열을 이용할 수 있다고 하니 그 때 다시 코드를 수정해보면 좋을거 같다.

댓글