
gradle eclipse 명령을 수행하여 이클립스 설정 파일을 준비한다.gradle eclipse 명령을 수행하여 이클립스 설정 파일을 준비한다.private BoardDao boardDao;
  private String fileName;
  public BoardServlet(String dataName){
    fileName = dataName + ".json";
    boardDao = new BoardDao(fileName); 
    try{
      boardDao.load();
    }catch(Exception e) {
      System.out.printf("%s 파일 로딩 중 오류 발생!\n", fileName);
      e.printStackTrace();
    }
  }
case "findAll": 
          Board[] boards = boardDao.findAll();
          out.writeUTF(SUCCESS); // client에게 응답
          out.writeUTF(new Gson().toJson(boards)); //client에게 전송
          break;
case "findByNo":
          no = in.readInt(); // client가 보낸 데이터 추가로 읽기
          board = boardDao.findByNo(no);
          if(board != null) {
            out.writeUTF(SUCCESS);
            out.writeUTF(new Gson().toJson(board));
          }else {
            out.writeUTF(FAIL);
          }
          break;
case "insert": 
          json = in.readUTF(); // json 형식의 문자열 읽기
          board = new Gson().fromJson(json, Board.class); // 객체의 타입정보 알려주기
          boardDao.insert(board);
          boardDao.save();
          out.writeUTF(SUCCESS);
          break;
case "update":
          json = in.readUTF(); // json 형식의 문자열 읽기
          board = new Gson().fromJson(json, Board.class); // 객체의 타입정보 알려주기
          if(boardDao.update(board)) {
            boardDao.save();
            out.writeUTF(SUCCESS);
          }else {
            out.writeUTF(FAIL);
          }
          break;
case "delete": 
          no = in.readInt(); // client가 보낸 데이터 추가로 읽기
          if(boardDao.delete(no)) {
            boardDao.save();
            out.writeUTF(SUCCESS);
          } else {
            out.writeUTF(FAIL);
          }
          break;
public boolean update(Board board) {
    for (int i = 0; i < list.size(); i++) {
      Board b = list.get(i);
      if (b.no == board.no) {
        list.set(i, board);
        return true;
      }
    }
    return false;
  }
// 게시글 데이터를 로딩한 후, 마지막 게시글 번호를 설정해 준다.
// 새 게시물의 번호 설정
boardNo = arr[arr.length-1].no; 
public interface Servlet {
  String SUCCESS = "success";
  String FAIL = "fail";
  ...
}

private void onList() throws Exception{
    out.writeUTF(dataName); // 데이터명
    out.writeUTF("findAll"); // command
    if(in.readUTF().equals("fail")) {
      System.out.println("목록을 가져오는데 실패했습니다!");
      return;
    }
    String json = in.readUTF();
    Board[] boards = new Gson().fromJson(json, Board[].class);
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
    System.out.println("번호\t제목\t조회수\t작성자\t등록일");
    for (Board board : boards) {
      Date date = new Date(board.createdDate);
      String dateStr = formatter.format(date); 
      System.out.printf("%d\t%s\t%d\t%s\t%s\n",
          board.no, board.title, board.viewCount, board.writer, dateStr);
    }
  }
private void onDetail() throws Exception{
    int boardNo = 0;
    while (true) {
      try {
        boardNo = Prompt.inputInt("조회할 게시글 번호? ");
        break;
      } catch (Exception ex) {
        System.out.println("입력 값이 옳지 않습니다!");
      }
    }
	// 서버에 데이터 요청 정보 전송
    out.writeUTF(dataName);
    out.writeUTF("findByNo");
    out.writeInt(boardNo);
    
    // 서버로부터 요청했던 데이터 받기
    if(in.readUTF().equals("fail")) {
      System.out.println("해당 번호의 게시글이 없습니다!");
      return;
    }
    String json = in.readUTF();
    Board board = new Gson().fromJson(json, Board.class);
    System.out.printf("번호: %d\n", board.no);
    System.out.printf("제목: %s\n", board.title);
    System.out.printf("내용: %s\n", board.content);
    System.out.printf("조회수: %d\n", board.viewCount);
    System.out.printf("작성자: %s\n", board.writer);
    Date date = new Date(board.createdDate);
    System.out.printf("등록일: %tY-%1$tm-%1$td %1$tH:%1$tM\n", date);
  }
private void onInput() throws Exception{
    // 사용자로부터 입력 받기
    Board board = new Board();
    board.title = Prompt.inputString("제목? ");
    board.content = Prompt.inputString("내용? ");
    board.writer = Prompt.inputString("작성자? ");
    board.password = Prompt.inputString("암호? ");
    board.viewCount = 0;
    board.createdDate = System.currentTimeMillis();
    out.writeUTF(dataName);
    out.writeUTF("insert");
    String json = new Gson().toJson(board);
    out.writeUTF(json); // json 서버로 보내기
    if(in.readUTF().equals("success")) {
      System.out.println("게시글을 등록했습니다.");
    } else {
      System.out.println("게시글 등록에 실패했습니다!");
    }
  }
private void onDelete() throws Exception{
    // 삭제할 게시글 번호 받기
    int boardNo = 0;
    while (true) {
      try {
        boardNo = Prompt.inputInt("삭제할 게시글 번호? ");
        break;
      } catch (Exception ex) {
        System.out.println("입력 값이 옳지 않습니다!");
      }
    }
    out.writeUTF(dataName);
    out.writeUTF("delete");
    out.writeInt(boardNo);
    if(in.readUTF().equals("success")) {
      System.out.println("삭제하였습니다.");
    } else {
      System.out.println("해당 번호의 게시글이 없습니다!");
    }
  }
board.title = Prompt...와 같이 수정 안됐는데, 이제 실제 수정은 서버에서 이루어직 때문에 가능하다.private void onUpdate() throws Exception{
    //    변경할 번호 입력 받기
    int boardNo = 0;
    while (true) {
      try {
        boardNo = Prompt.inputInt("변경할 게시글 번호? ");
        break;
      } catch (Throwable ex) {
        System.out.println("입력 값이 옳지 않습니다!");
      }
    }
    // 변경할 게시글 가져오기
    out.writeUTF(dataName);
    out.writeUTF("findByNo");
    out.writeInt(boardNo);
    if(in.readUTF().equals("fail")) {
      System.out.println("해당 번호의 게시글이 없습니다!");
      return;
    }
    String json = in.readUTF();
    Board board = new Gson().fromJson(json, Board.class);
    board.title = Prompt.inputString("제목?(" + board.title + ") ");
    board.content= Prompt.inputString(String.format("내용?(%s) ", board.content));
    String input = Prompt.inputString("변경하시겠습니까?(y/n) ");
    if (input.equals("y")) {
      // 게시글 변경하기
      out.writeUTF(dataName);
      out.writeUTF("update");
      out.writeUTF(new Gson().toJson(board));
      if(in.readUTF().equals("success")) {
        System.out.println("변경했습니다.");
      }else {
        System.out.println("변경 실패했습니다!");
      }
    } else {
      System.out.println("변경 취소했습니다.");
    }

public class MemberServlet implements Servlet {
  private MemberDao memberDao;
  private String fileName;
  public MemberServlet(String dataName) {
    fileName = dataName + ".json";
    memberDao = new MemberDao(fileName);
    try {
      memberDao.load();
    }catch(Exception e) {
      System.out.printf("%s 파일 로딩 중 오류 발생!\n", fileName);
      e.printStackTrace();
    }
  }
  @Override
  public void service(DataInputStream in, DataOutputStream out){
    try {
      String command = in.readUTF();
      // 여러 군데에서 사용하기 위해 여기서 선언
      Member member = null; 
      String email = null;
      String json = null;
      switch (command) {
        case "findAll": 
          Member[] members = memberDao.findAll();
          out.writeUTF(SUCCESS); // client에게 응답
          out.writeUTF(new Gson().toJson(members)); //client에게 전송
          break;
        case "findByEmail":
          email = in.readUTF(); // client가 보낸 데이터 추가로 읽기
          member = memberDao.findByEmail(email);
          if(member != null) {
            out.writeUTF(SUCCESS);
            out.writeUTF(new Gson().toJson(member));
          }else {
            out.writeUTF(FAIL);
          }
          break;
        case "insert": 
          json = in.readUTF(); // json 형식의 문자열 읽기
          member = new Gson().fromJson(json, Member.class); // 객체의 타입정보 알려주기
          memberDao.insert(member);
          memberDao.save();
          out.writeUTF(SUCCESS);
          break;
        case "update":
          json = in.readUTF(); // json 형식의 문자열 읽기
          member = new Gson().fromJson(json, Member.class); // 객체의 타입정보 알려주기
          if(memberDao.update(member)) {
            memberDao.save();
            out.writeUTF(SUCCESS);
          }else {
            out.writeUTF(FAIL);
          }
          break;
        case "delete": 
          email = in.readUTF(); // client가 보낸 데이터 추가로 읽기
          if(memberDao.delete(email)) {
            memberDao.save();
            out.writeUTF(SUCCESS);
          } else {
            out.writeUTF(FAIL);
          }
          break;
        default:
          out.writeUTF(FAIL);
      }//switch
    }catch(Exception e) {
      throw new RuntimeException(e); 
    }//try-catch
  }
}
public class MemberDao {
  ...
  public boolean update(Member member) {
    for (int i = 0; i < list.size(); i++) {
      Member m = list.get(i);
      if (m.email.equals(member.email)) {
        list.set(i, member);
        return true;
      }
    }
    return false;
  }
  ...
  
}
// 클라이언트 요청을 처리할 memberServlet 객체 준비
 MemberServlet memberServlet = new MemberServlet("member");
// switch문에 memberServlet의 경우 추가하기
switch(dataName) {
            ...
            
            case "member":memberServlet.service(in, out);break;
            
            default:
              out.writeUTF("fail");
          }
public class MemberHandler extends AbstractHandler {
  String dataName;
  DataInputStream in;
  DataOutputStream out;
  public MemberHandler(String dataName, DataInputStream in, DataOutputStream out) {
    super(new String[] {"목록", "상세보기", "등록", "삭제", "변경"});
    this.dataName = dataName;
    this.in = in;
    this.out =out;
  }
  @Override
  public void service(int menuNo){
    try{
      switch (menuNo) {
        case 1: this.onList(); break;
        case 2: this.onDetail(); break;
        case 3: this.onInput(); break;
        case 4: this.onDelete(); break;
        case 5: this.onUpdate(); break;
      }
    }catch(Exception e) {
      throw new RuntimeException();
    }
  }
  private void onList() {
    try {
      out.writeUTF(dataName);
      out.writeUTF("findAll");
      if(in.readUTF().equals("fail")) {
        System.out.println("목록을 가져오는데 실패했습니다!");
        return;
      }
      String json = in.readUTF();
      Member[] members = new Gson().fromJson(json, Member[].class);
      System.out.println("이메일       이름");
      for (Member member : members) {
        System.out.printf("%s   %s\n",
            member.email, member.name);
      }
    }catch(Exception e) {
      throw new RuntimeException(e);
    } // try-catch
  }
  private void onDetail() {
    try {
      String email = Prompt.inputString("조회할 회원 이메일? ");
      out.writeUTF(dataName);
      out.writeUTF("findByEmail");
      out.writeUTF(email);
      if(in.readUTF().equals("fail")) {
        System.out.println("해당 이메일의 회원이 없습니다!");
        return;
      }
      String json = in.readUTF();
      Member member = new Gson().fromJson(json, Member.class);
      System.out.printf("이름: %s\n", member.name);
      System.out.printf("이메일: %s\n", member.email);
      Date date = new Date(member.createdDate);
      System.out.printf("등록일: %tY-%1$tm-%1$td %1$tH:%1$tM\n", date);
    }catch(Exception e) {
      throw new RuntimeException(e);
    }
  }
  private void onInput() throws Exception{
    try {
      Member member = new Member();
      member.name = Prompt.inputString("이름? ");
      member.email = Prompt.inputString("이메일? ");
      member.password = Prompt.inputString("암호? ");
      member.createdDate = System.currentTimeMillis();
      out.writeUTF(dataName);
      out.writeUTF("insert");
      String json = new Gson().toJson(member);
      out.writeUTF(json); // json 서버로 보내기
      if(in.readUTF().equals("success")) {
        System.out.println("회원을 등록했습니다.");
      }else {
        System.out.println("회원 등록에 실패했습니다!");
      }
    }catch(Exception e) {
      throw new RuntimeException(e);
    }
  }
  private void onDelete() throws Exception{
    try {
      String email = Prompt.inputString("삭제할 회원 이메일? ");
      out.writeUTF(dataName);
      out.writeUTF("delete");
      out.writeUTF(email);
      if(in.readUTF().equals("success")) {
        System.out.println("삭제하였습니다.");
      } else {
        System.out.println("해당 이메일의 회원이 없습니다!");
      }
    }catch(Exception e) {
      throw new RuntimeException(e);
    }
  }
  private void onUpdate() throws Exception{
    try {
      String email = Prompt.inputString("변경할 회원 이메일? ");
      out.writeUTF(dataName);
      out.writeUTF("findByEmail");
      out.writeUTF(email);
      if(in.readUTF().equals("fail")) {
        System.out.println("해당 이메일의 회원이 없습니다!");
        return;
      }
      String json = in.readUTF();
      Member member = new Gson().fromJson(json, Member.class);
      member.name = Prompt.inputString("이름?(" + member.name + ") ");
      String input = Prompt.inputString("변경하시겠습니까?(y/n) ");
      if (input.equals("y")) {
        // 회원 변경하기
        out.writeUTF(dataName);
        out.writeUTF("update");
        out.writeUTF(new Gson().toJson(member));
        if(in.readUTF().equals("success")) {
          System.out.println("변경했습니다.");
        }else {
          System.out.println("변경 실패했습니다!");
        }
      } else {
        System.out.println("변경 취소했습니다.");
      }
    }catch(Exception e) {
      throw new RuntimeException(e);
    }
  }
}
// 핸들러를 담을 레퍼런스 배열을 준비한다.
      Handler[] handlers = new Handler[] { // 파일명을 목적에 맞게 각각 전달
      
          ...
          
          new MemberHandler("member", in, out) // 회원
      };
| 목록관리 | List | Set | Map | 
|---|---|---|---|
| 데이터 저장 및 조회시 사용하는 인덱스 | 값: 0부터 순차적으로 증가하는 정수 값 (양수)  | key: hash 알고리즘으로 계산한 정수값 | hash 알고리즘으로 계산한 정수값 | 
| 입력 순서 유지 | O | X | X | 
| 객체 중복 저장 | O | X | Key가 중복되지 않는다. | 
| 특징 | 입력 순서 유지 | 중복 제거 | 빠른 조회 → key를 이용 | 
| - ArrayList - LinkedList - Vector  | HashSet | - HashMap: key, value, null 허용 - HashTable:key, value, null 불가!  |