[Java] 로그인&회원가입&탈퇴 프로그램(Swing, GUI)

이지·2023년 12월 8일
0

solo-project

목록 보기
1/2

**자바만 사용해서 만든 프로그램

학원 다닌지 한달 조금 지났을때 처음 진행해본 개인 프로젝트!
실제 웹페이지에서 필수요소인 계정생성의 흐름을 느껴보고 싶어서 주제로 잡고 진행했다.

PT자료 만들고 발표까지 총 40시간 걸렸고,
중간에 '탈퇴'기능을 넣으면서 난이도가 확! 오른 느낌이 들었다. 오류도 많았고, 이리저리 수정해보면서 성공했을때 성취감👍🏻

PT자료 확인

클래스는 총 5개로 구성 되어 있다
1. LoginForm
2. JoinForm
3. User
4. InfotmationForm
5. UsersData

1. LoginForm

로그인 화면을 나타낸다.
UsersData와 관련이 있으며 사용자 데이터를 관리하기 위해
"회원가입" 버튼이 클릭될 때 JoinForm의 인스턴스를 생성한다.
로그인에 성공하면 InformationForm의 인스턴스를 생성한다.


package login.project;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

// ID 와 PW 를 입력해서 로그인 하는 화면
// 위 정보 입력 후 로그인 OR 회원가입 
// 중복 ID 거를 수 있어야 함 

public class LoginForm extends JFrame {

	private UsersData users;
	private JLabel idLabel;
	private JLabel pwLabel;
	private JTextField idTxt;
	private JPasswordField pwTxt;
	private JButton logBtn;
	private JButton joinBtn;
	private LayoutManager flowLeft;
	
	public LoginForm() {
		
		users = new UsersData();
		
		init(); 
		setDisplay();	// UI 화면을 설정하는 메서드 
		addListners();	// 리스너를 추가하는 메서드
		showFrame();	// 프레임을 화면에 표시하는 메서드
		
	}
	
	public void init() {
		
		// 사이즈 통일 
		Dimension labelSize= new Dimension(80, 30);
		int txtSize = 10;
		Dimension btnSize = new Dimension(100, 25);
		
		idLabel = new JLabel("아이디");
		idLabel.setPreferredSize(labelSize);
		pwLabel = new JLabel("암호");
		pwLabel.setPreferredSize(labelSize);
		
		idTxt = new JTextField(txtSize);
		pwTxt = new JPasswordField(txtSize);
				
		logBtn = new JButton("로그인");
		logBtn.setPreferredSize(btnSize);
		joinBtn = new JButton("회원가입");
		joinBtn.setPreferredSize(btnSize);
		
		flowLeft = new FlowLayout(FlowLayout.LEFT);
		
	}
	
	public UsersData getUsers() {
		return users;
	}
	
	public String getidTxt() {
		return idTxt.getText();
	}
	
	public void setDisplay() {
		// 컴포넌트를 왼쪽 정렬로 배치
		FlowLayout flowLayout = new FlowLayout(FlowLayout.LEFT);
		
		JPanel northPanel = new JPanel(new GridLayout(0,1));
		
		JPanel idPanel = new JPanel(flowLeft);
		idPanel.add(idLabel);
		idPanel.add(idTxt);
		
		JPanel pwPanel = new JPanel(flowLeft);
		pwPanel.add(pwLabel);
		pwPanel.add(pwTxt);
		
		northPanel.add(idPanel);
		northPanel.add(pwPanel);
		
		JPanel southPanel = new JPanel();
		southPanel.add(logBtn);
		southPanel.add(joinBtn);
		
		northPanel.setBorder(new EmptyBorder(0, 20, 0, 20));
		southPanel.setBorder(new EmptyBorder(0, 0, 10, 0));
		
		add(northPanel, BorderLayout.NORTH);
		add(southPanel, BorderLayout.SOUTH);
		
	}
	
	public void addListners() {
		// JOIN button 눌렀을때 
		joinBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				setVisible(false);
				new JoinForm(LoginForm.this);
				idTxt.setText("");
				pwTxt.setText("");
			}
		});
		// LOGIN button 눌렀을때
		
		logBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// ID 입력하지 않았을 경우 
				if (idTxt.getText().isEmpty()) {
					JOptionPane.showMessageDialog(LoginForm.this, "아이디를 입력하세요","JAVA LOGIN",JOptionPane.WARNING_MESSAGE);
				// 이미 존재하는 ID일 경우 	
				} else if (users.contains(new User(idTxt.getText()))) {
				// PW 입력하지 않았을 경우 
					if(String.valueOf(pwTxt.getPassword()).isEmpty()) {
						JOptionPane.showMessageDialog(LoginForm.this, "암호를 입력하세요","JAVA LOGIN",JOptionPane.WARNING_MESSAGE);
				// PW 틀렸을 경우 
					} else if (!users.getUser(idTxt.getText()).getPw().equals(String.valueOf(pwTxt.getPassword()))) {
						JOptionPane.showConfirmDialog(LoginForm.this, "암호가 일치하지 않습니다","RETRY", JOptionPane.WARNING_MESSAGE);
					} else {
						// 예시 코드, 실제 호출 부분에서 userId 값을 전달해야 함
						InformationForm informationForm = new InformationForm(LoginForm.this, "사용자ID값");

						//InformationForm informationForm = new InformationForm(LoginForm.this, title);
						informationForm.setcheck(users.getUser(idTxt.getText()).toString());
						setVisible(false);
						informationForm.setVisible(true);
						idTxt.setText("");
						pwTxt.setText("");
					}
				// 존재하지 않는 ID일 경우 		
					} else {
						JOptionPane.showMessageDialog(LoginForm.this, "존재하지 않는 ID 입니다", "JAVA LOGIN", JOptionPane.WARNING_MESSAGE);
					}
			}
		});
		
		addWindowListener(new WindowAdapter() {
		    @Override
		    public void windowClosing(WindowEvent we) {
		        int choice = JOptionPane.showConfirmDialog(
		            LoginForm.this, "다음에 또 만나요!", "BYE JAVA", JOptionPane.OK_CANCEL_OPTION);
		        if (choice == JOptionPane.OK_OPTION) {
		            System.exit(0);
		        }
		    }
		});

	}	
	public void showFrame() {
		setTitle("Welcome to JAVA");
		pack(); 										// 프레임의 크기를 컨텐츠에 맞게 조정 
//		setLocale(null);								// 시스템의 기본 로케일로 설정된다는 의미, 이 메서드는 주로 다국어 지원을 고려하여 프로그램 개발 될 때 사용 
		setLocationRelativeTo(null);					// 프레임을 화면 중앙에 위치 		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);	// 프레임이 닫힐 때 아무 동작도 하지 않도록 설정 
		setResizable(false);							// 프레임의 크기 고정
		setVisible(true);				
	}
	public static void main(String[] args) {
		new LoginForm();		
	} // main	
} 

2. JoinForm

회원가입을 위한 양식을 나타낸다.
LoginForm과 관련이 있으며 LoginForm에서 생성되며
성공적인 가입 후 다시 LoginForm으로 돌아간다.
ID 중복 확인, 새로운 가입자 추가 및 여러 유효성 검사
를 위해 UsersData를 사용한다.

package login.project;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;

// 필수 입력 정보 
// ID 중복 안됨 
// 비밀번호는 두번 확인 하도록 설정 

public class JoinForm extends JDialog {
	
	private LoginForm loginForm;
	private UsersData users;

	private JLabel titleLabel;
	private JLabel idLabel;
	private JLabel pwLabel; 
	private JLabel reLabel;
	private JLabel nameLabel;
	private JLabel nickNameLabel;
	private JLabel phoneNumberLabel;
	
	private JTextField idTxt;
	private JTextField pwTxt;
	private JTextField reTxt;
	private JTextField nameTextField;
	private JTextField nickNameTextField;
	private JTextField phoneNumberTextField;
	
	private JRadioButton yesRadioButton;
	private JRadioButton noRadioButton;
	
	private JButton joinBtn;
	private JButton cancelBtn;
	private JPanel mainCPanel;
	
	// 로그인 첫 화면 
	public JoinForm(LoginForm loginForm) {
		this.loginForm = loginForm;
        this.users = loginForm.getUsers();
		
//		super(loginForm, "JAVA JOIN", true);
//		this.loginForm = loginForm;
//		users = loginForm.getUsers();
		
		init();
		setDisplay();
		addListeners();
		showFrame();
		
	}
	
	private void init() {
		int txtSize = 10;
		
		Dimension labelSize = new Dimension(80, 30);
		// btnSize 모든 GUI 통일
		Dimension btnSize = new Dimension(100, 25);
		
		titleLabel = new JLabel("- 개인 정보를 입력하세요 -", JLabel.CENTER);
		
		idLabel = new JLabel("아이디", JLabel.LEFT);
		idLabel.setPreferredSize(labelSize);
		
		pwLabel = new JLabel("암호", JLabel.LEFT);
		pwLabel.setPreferredSize(labelSize);
		
		reLabel = new JLabel("암호 재입력", JLabel.LEFT);
		reLabel.setPreferredSize(labelSize);
		
		nameLabel = new JLabel("이름", JLabel.LEFT);
		nameLabel.setPreferredSize(labelSize);
		
		nickNameLabel = new JLabel("닉네임", JLabel.LEFT);
		nickNameLabel.setPreferredSize(labelSize);
		
		phoneNumberLabel = new JLabel("연락처", JLabel.LEFT);
		phoneNumberLabel.setPreferredSize(labelSize);
		
		idTxt = new JTextField(txtSize);
		pwTxt = new JPasswordField(txtSize);
		reTxt = new JPasswordField(txtSize);
		nameTextField = new JTextField(txtSize);
		nickNameTextField = new JTextField(txtSize);
		phoneNumberTextField = new JTextField(txtSize);
		
		yesRadioButton = new JRadioButton("SMS 수신 동의", true);
		noRadioButton = new JRadioButton("SMS 수신 미동의", false);
		ButtonGroup group = new ButtonGroup();
		group.add(yesRadioButton);
		group.add(noRadioButton);
		
		joinBtn = new JButton("JOIN");
		joinBtn.setPreferredSize(btnSize);
		cancelBtn = new JButton("CANCEL");
		cancelBtn.setPreferredSize(btnSize);
		
		// 레이아웃의 열과 행을 설정, 0은 열의 값을 제한하지 않는다 
		mainCPanel = new JPanel(new GridLayout(0, 1));
	}
	
	private void setDisplay() {
		
		FlowLayout flowLeft = new FlowLayout(FlowLayout.LEFT);
		
		JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
		northPanel.add(titleLabel);
		
		JPanel idPanel = new JPanel(flowLeft);
		idPanel.add(idLabel);
		idPanel.add(idTxt);
		
		JPanel pwPanel = new JPanel(flowLeft);
		pwPanel.add(pwLabel);
		pwPanel.add(pwTxt);
		
		JPanel rePanel = new JPanel(flowLeft);
		rePanel.add(reLabel);
		rePanel.add(reTxt);
		
		JPanel namePanel = new JPanel(flowLeft);
		namePanel.add(nameLabel);
		namePanel.add(nameTextField);
		
		JPanel nickNamePanel = new JPanel(flowLeft);
		nickNamePanel.add(nickNameLabel);
		nickNamePanel.add(nickNameTextField);
		
		JPanel phoneNumberPanel = new JPanel(flowLeft);
		phoneNumberPanel.add(phoneNumberLabel);
		phoneNumberPanel.add(phoneNumberTextField);
		
		mainCPanel.add(idPanel);
		mainCPanel.add(pwPanel);
		mainCPanel.add(rePanel);
		mainCPanel.add(namePanel);
		mainCPanel.add(nickNamePanel);
		mainCPanel.add(phoneNumberPanel);
		
		JPanel smsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
		smsPanel.add(yesRadioButton);
		smsPanel.add(noRadioButton);
		smsPanel.setBorder(new TitledBorder("SMS 수신 동의"));
		
		JPanel southPanel = new JPanel();
		southPanel.add(joinBtn);
		southPanel.add(cancelBtn);
		
		mainCPanel.add(northPanel, BorderLayout.NORTH);
		mainCPanel.add(smsPanel, BorderLayout.CENTER);
		mainCPanel.add(southPanel, BorderLayout.SOUTH);
		
		mainCPanel.setBorder(new EmptyBorder(0, 20, 0, 20));
		smsPanel.setBorder(new EmptyBorder(0, 0, 10, 0));
		
		add(northPanel, BorderLayout.NORTH);
		add(mainCPanel, BorderLayout.CENTER);
		add(southPanel, BorderLayout.SOUTH);
	
	}
	
	private void addListeners() {
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent we) {
				dispose();
				loginForm.setVisible(true);
			}
		});
		
		cancelBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent ae) {
				dispose();
				loginForm.setVisible(true);
			}
		});
		

		joinBtn.addActionListener(new ActionListener() {
		    @Override
		    public void actionPerformed(ActionEvent ae) {
		        if(isBlank()) {
		            JOptionPane.showMessageDialog(JoinForm.this, "모든 정보를 입력해주세요","RETRY",JOptionPane.WARNING_MESSAGE);
		        } else {
		            if(users.isIdOverlap(idTxt.getText())) {
		                JOptionPane.showMessageDialog(JoinForm.this, "이미 존재하는 아이디입니다","RETRY",JOptionPane.WARNING_MESSAGE);
		                idTxt.requestFocus();
		            } else if (!String.valueOf(((JPasswordField) pwTxt).getPassword()).equals(String.valueOf(((JPasswordField) reTxt).getPassword()))) {
		                JOptionPane.showMessageDialog(JoinForm.this, "암호가 일치하지 않습니다");
		                pwTxt.requestFocus();
		            } else {
		                users.addUser(new User(idTxt.getText(),
		                		String.valueOf(((JPasswordField) pwTxt) .getPassword()), 
		                		nameTextField.getText(), 
		                		nickNameTextField.getText(), 
		                		phoneNumberTextField.getText(),
		                		getGroup()));
		                JOptionPane.showMessageDialog(JoinForm.this, "회원가입을 완료했습니다","WELCOME",JOptionPane.PLAIN_MESSAGE);
		                dispose();
		                loginForm.setVisible(true);
		            }
		        }
		    }
		});
		
	}
	
	public boolean isBlank() {
        boolean result = false;
        if(idTxt.getText().isEmpty()) {
        	idTxt.requestFocus();
            return true;
        }
        if(String.valueOf(pwTxt.getText()).isEmpty()) {
        	pwTxt.requestFocus();
            return true;
        }
        if(String.valueOf(reTxt.getText()).isEmpty()) {
        	reTxt.requestFocus();
            return true;
        }
        if(nameTextField.getText().isEmpty()) {
        	nameTextField.requestFocus();
            return true;
        }
        if(nickNameTextField.getText().isEmpty()) {
        	nickNameTextField.requestFocus();
            return true;
        }
        return result;
    }
    
    public String getGroup() {
        if(yesRadioButton.isSelected()) {
            return yesRadioButton.getText();
        }
        return noRadioButton.getText();
    }
    
	private void showFrame() {
		pack();
        setLocationRelativeTo(loginForm); 						// loginForm이 있는 위치를 기준으로 위치를 조정함 
        setDefaultCloseOperation(DISPOSE_ON_CLOSE); // 다이얼로그를 닫을 때 해당 다이얼로그만 닫히고 프로그램이 종료되지는 않음
        setResizable(false); 													// 창 크기를 조절할 수 없도록 설정함 
        setVisible(true);
	
	}

	
}

3. User

ID, 비밀번호, 이름, 닉네임, 전화번호 및
사용자 데이터를 저장하고 관리하기 위해 UsersData에서 사용된다.
SMS 동의와 같은 속성을 가진 사용자를 나타낸다

package login.project;

import java.io.Serializable;
import java.util.Objects;

// 회원 정보를 String으로 받음
// ID, PW, NAME, NICKNAME, PHONENUMBER
// SMS 수신동의는 Yes OR No 로 선택 가능 

public class User implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	private String id;
	private String pw;
	private String name;
	private String nickName;
	private String phoneNumber;
	private String smsOk;
	
	public User(String id, String pw, String name, String nickName, String phoneNumber, String smsOk) {
		setId(id);
		setPw(pw);
		setName(name);
		setNickName(nickName);
		setPhoneNumber(phoneNumber);
		setSmsOk(smsOk);
	}
	
	public User(String id) {
		setId(id);
	}
	
	public String getId() {
        return id;
    }
	 public void setId(String id) {
        this.id = id;
    }
    public String getPw() {
        return pw;
    }
    public void setPw(String pw) {
        this.pw = pw;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    public String getnickName() {
        return nickName;
    }
    
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
    
    public String getphoneNumber() {
        return phoneNumber;
    }
    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getSmsOk() {
        return smsOk;
    }
    
    public void setSmsOk(String smsOk) {
        this.smsOk = smsOk;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        User user = (User) obj;
        return Objects.equals(id, user.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
    @Override
    public String toString() {
        String info = "아이디: " + id + "\n";
        info += "암호: " + pw + "\n";
        info += "이름: " + name + "\n";
        info += "닉네임: " + nickName + "\n";
        info += "연락처: " + phoneNumber + "\n";
        info += "SMS 수신 동의: " + smsOk + "\n";
        return info;
    }
}

4. InfotmationForm

로그인 성공 후 사용자 정보를 표시하는 양식을 나타낸다.
LoginForm에서 생성되며 로그아웃 후 LoginForm으로 돌아간다.
탈퇴 시 사용자 정보 삭제를 위해 UsersData를 사용한다.

package login.project;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

// 로그인 성공 시 개인 정보가 출력되는 GUI 화면 
// LOGOUT 과 WITHDRAW 기능
// LOGOUT 클릭 시 LOGINFORM 화면으로 이동
// WITHDRAW 클릭 시 탈퇴 및 정보 삭제

public class InformationForm extends JDialog {
	
	private LoginForm owner;
	private UsersData users;
	 private String userId; 
	private JTextArea check;
	private JButton btnLogout;
	private JButton btnWithdraw;
	
	public InformationForm(LoginForm owner, String Id) {
		 this.owner = owner;
		 this.userId = owner.getidTxt(); // 사용자 ID 저장
	     this.users = owner.getUsers();
//		super(owner, "HELLO JAVA", true);
//		this.owner = owner;
//		users = owner.getUsers();
		
		init();
		setDisplay();
		addListners();
		setcheck("사용자 정보 텍스트 등"); // 수정된 부분
		showFrame();
	}
	
	private void init() {
		Dimension btnsize = new Dimension(100, 25);
		
		check = new JTextArea(10, 30);
		check.setEditable(false);
		
		btnLogout = new JButton("로그아웃");
		btnLogout.setPreferredSize(btnsize);
		
		btnWithdraw = new JButton("탈퇴하기");
		btnWithdraw.setPreferredSize(btnsize);
	}

	private void setDisplay() {
		LineBorder lBorder = new LineBorder(Color.GRAY, 1);
		TitledBorder border = new TitledBorder(lBorder, "안녕하세요! 본인의 정보를 확인 할 수 있습니다");
		check.setBorder(border);
		
		JPanel southPanel = new JPanel();
		southPanel.add(btnLogout);
		southPanel.add(btnWithdraw);
		
		JPanel mainPanel = new JPanel(new BorderLayout());
		mainPanel.add(new JScrollPane(check), BorderLayout.NORTH);
		mainPanel.add(southPanel, BorderLayout.CENTER);
		
		add(mainPanel, BorderLayout.CENTER);
	}
	
	private void addListners() { 
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent we) {
				dispose();
			}
		});
		
		btnWithdraw.addActionListener(new ActionListener() {
			
			@Override
			  public void actionPerformed(ActionEvent ae) {
		        try {
		            // 예외처리 추가
		            String userId = InformationForm.this.userId;
		            if (userId != null && !userId.isEmpty()) {
		               // System.out.println("Withdraw button clicked: " + userId);
		                // User 객체를 생성하여 ID 가져오기
		                User userForWithdraw = new User(userId);
		                // withdraw 메서드 호출
		                users.withdraw(userForWithdraw.getId());
		                
		                JOptionPane.showMessageDialog(InformationForm.this, "회원 정보가 삭제되었습니다" + "\n" + "다음에 또 만나요!", "BYE JAVA", JOptionPane.PLAIN_MESSAGE);
		                dispose();
		                owner.setVisible(true);
		            } else {
		                System.out.println("Withdraw button clicked: userId is null or empty");
		            }
		        } catch (Exception e) {
		            e.printStackTrace();
		        }
		    }
		});
		
		btnLogout.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(InformationForm.this, "로그아웃 되었습니다" + "\n" + "다음에 또 만나요!","BYE JAVA",JOptionPane.PLAIN_MESSAGE);
				dispose();
				owner.setVisible(true);
			}
		});
	}
	
	public void setcheck(String userInfo) {
		check.setText(userInfo);
	}
	
	private void showFrame() {
		pack();
		setLocationRelativeTo(owner);								// loginForm이 있는 위치를 기준으로 위치를 조정함 
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);	// 다이얼로그를 닫을 때 해당 다이얼로그만 닫히고 프로그램이 종료되지는 않음
		setResizable(false);					 								// 창 크기를 조절할 수 없도록 설정함 
	}
}

5. UsersData

사용자 정보가 담긴 데이터를 파일로 저장합니다.
사용자 관련 작업을 수행하기 위해 LoginForm 및
JoinForm에서 사용된다.

package login.project;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;

public class UsersData {
    private ArrayList<User> users;
    private static final String FILE_PATH = "경로/파일이름.파일형식";
	private static final String IdTxt = null;

    public UsersData() {
        users = new ArrayList<>();
        loadUserData();
    }

    public void addUser(User newUser) {
        users.add(newUser);
        saveUserData();
    }

    public boolean isIdOverlap(String userId) {
        return users.stream().anyMatch(user -> user.getId().equals(userId));
    }
    
    public void withdraw(String userId) {
        try {
          //  System.out.println("withdraw 메서드 호출: " + userId);

            User userToRemove = null;

            for (User user : users) {
                if (user.getId().equalsIgnoreCase(userId)) {
                    userToRemove = user;
                    break;
                }
            }

            if (userToRemove != null) {
                users.remove(userToRemove); // 사용자 목록에서 사용자 제거
                removeUserFromFile(IdTxt); // 파일에서 사용자 제거
                saveUserData(); // 변경된 사용자 목록을 파일에 저장
               // System.out.println("withdraw 메서드 종료");
            } else {
                System.out.println("ID에 해당하는 사용자를 찾을 수 없습니다. (입력된 ID: " + IdTxt + ")");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    private void removeUserFromFile(String id) {
        try (BufferedReader reader = new BufferedReader(new FileReader(FILE_PATH));
             BufferedWriter writer = new BufferedWriter(new FileWriter(FILE_PATH + ".tmp"))) {

            String line;
            while ((line = reader.readLine()) != null) {
                String[] userData = line.split(",");
                if (!userData[0].equals(id)) {
                    writer.write(line + "\n");
                } else {
                    System.out.println("User to remove: " + line);
                }
            }

        } catch (FileNotFoundException e) {
            // 파일이 없을 경우, 처음 실행하는 경우일 수 있으므로 무시
        } catch (IOException e) {
            e.printStackTrace();
        }
     // 임시 파일을 원본 파일로 복사
        try {
            Files.copy(Paths.get(FILE_PATH + ".tmp"), Paths.get(FILE_PATH), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 임시 파일 삭제
        try {
            Files.delete(Paths.get(FILE_PATH + ".tmp"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public User getUser(String id) {
        return users.stream().filter(user -> user.getId().equals(id)).findFirst().orElse(null);
    }

    // 사용자가 users 목록에 포함되어 있는지를 확인 
    public boolean contains(User user) {
        return users.contains(user);
    }

    //FILE_PATH에서 사용자 데이터를 읽어와 users 목록을 user 객체로채움 
    private void loadUserData() {
        try (BufferedReader reader = new BufferedReader(new FileReader(FILE_PATH))) {
            String line;
            while ((line = reader.readLine()) != null) {
                String[] userData = line.split(",");
                if (userData.length == 6) {
                    String id = userData[0];
                    String pw = userData[1];
                    String name = userData[2];
                    String nickName = userData[3];
                    String phoneNumber = userData[4];
                    String smsOk = userData[5];
                    User user = new User(id, pw, name, nickName, phoneNumber, smsOk);
                    users.add(user);
                } else {
                    System.out.println("잘못된 형식의 데이터 " + line);
                }
            }
        } catch (FileNotFoundException e) {
            // 파일이 없을 경우, 처음 실행하는 경우일 수 있으므로 무시
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // users 목록에서 사용자 데이터를 파일로 씀(기존 내용을 덮어쓰기), 메서드가 호출될때마다 파일을 업데이트함 
    private void saveUserData() {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(FILE_PATH))) {
            for (User user : users) {
                writer.write(user.getId() + ",");
                writer.write(user.getPw() + ",");
                writer.write(user.getName() + ",");
                writer.write(user.getnickName() + ",");
                writer.write(user.getphoneNumber() + ",");
                writer.write(user.getSmsOk() + "\n");
            }
            System.out.println("User list before writing to file:");
            users.forEach(System.out::println);

            writer.flush();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }  
}

작업하면서 열심히 주석을 추가하려고 했는데,
지금 보니 부족해보이기도 해서 아쉽다.

아직 배운게 적어서 주먹구구식으로 코드를 짠것 같기도 하고!😭

벨로그에 기록하기 이제 점점 늘어가려나?!

profile
코린이인줄 알았는데 코치원생임

1개의 댓글

comment-user-thumbnail
2024년 5월 13일

안녕하세요. Java 언어를 배우고 있는 학생들입니다.
다름이 아니라 현재 학습 목적으로 구현 중인 코드에, 본 게시글에서 작성하신 코드를 사용하고 싶어 댓글을 작성합니다. 괜찮으시다면 본 코드를 저희 조가 참고하거나 사용해서 프로그램을 구현해도 될지 여쭤보고 싶습니다! 감사합니다

답글 달기