[Android 공부] Spring Boot와 연계를 통한 회원가입 구현(3)

2025. 6. 2. 22:09Java/Android

저번에 이메일 중복 체크를 하였고, 이번에는 실제 회원가입을 구현해볼 겁니다.

백엔드 설정

1. 회원가입 요청/응답 DTO 추가

요청은 이메일(username), 비밀번호, 이름, 나이, 전화번호, 역할(유저 or 어드민) 값들을 정의하였고,

응답은 회원가입 성공 여부, 메시지를 정의하였습니다.

public class RegisterRequest {

	private String username;
	
	private String password;
	
	private String name;
	
	private int age;
	
	private String phoneNum;
	
	private String role;
	
	public String getUsername() {
		return username;
	}
	
	public String getPassword() {
		return password;
	}
	
	public String getName() {
		return name;
	}
	
	public int getAge() {
		return age;
	}
	
	public String getPhoneNum() {
		return phoneNum;
	}
	
	public String getRole() {
		return role;
	}
	
	public void setUsername(String username) {
		this.username = username;
	}
	
	public void setPassword(String password) {
		this.password = password;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public void setPhoneNum(String phoneNum) {
		this.phoneNum = phoneNum;
	}
	
	public void setRole(String role) {
		this.role = role;
	}
	
}
public class RegisterResponse {

	private boolean isSuccess;
	
	private String message;
	
	public RegisterResponse(boolean isSuccess, String message) {
		this.isSuccess = isSuccess;
		this.message = message;
	}
	
	public String getMessage() {
		return message;
	}

	public boolean isSuccess() {
		return isSuccess;
	}

}

2. 회원가입을 처리할 Controller 메서드 추가

모든 프로그램에서 비밀번호라는 값은 RAW 값을 DB에 저장해서는 절대 안됩니다!! 비밀번호라는 값이 넘어가게 되면 해당 회원의 개인정보들이 털릴 수 있기 때문에 최소한 비밀번호라도 암호화해서 넣는 것이 중요합니다.

암호화하는 로직은 Spring Security 의존성을 추가했다면 사용할 수 있는 BCrpytPasswordEncoder를 사용하여 진행해주시면 됩니다.

@PostMapping("/register")
public ResponseEntity<?> register(@RequestBody RegisterRequest request) {
    // 비밀번호 암호화 로직
    String inputPassword = request.getPassword();
    String encodedPassword = passwordEncoder.encode(inputPassword);

    request.setPassword(encodedPassword);

    try {
        authService.register(request);
        return ResponseEntity.ok(new RegisterResponse(true, "회원가입 성공"));
    } catch (Exception e) {
        e.printStackTrace();
        return ResponseEntity.ok(new RegisterResponse(false, "회원가입 실패"));
    }
}

3. 회원가입을 처리할 Service 메서드 추가

요청DTO를 파라미터로 받고, User 엔티티 객체를 생성한 후 JPA에서 기본 제공하는 save(entity) 메서드를 사용해 DB에 저장합니다.

public void register(RegisterRequest request) {
    User user = new User(request.getUsername(), request.getPassword(), request.getName(), request.getAge(),
            request.getPhoneNum(), request.getRole());

    userRepository.save(user);
}

프론트 설정

1. 회원가입 요청/응답 DTO 추가

public class RegisterRequest {

    private String username;
    private String password;
    private String name;
    private int age;
    private String phoneNum;

    private String role;

    public RegisterRequest() {

    }

    public RegisterRequest(String username, String password, String name, int age, String phoneNum, String role) {
        this.username = username;
        this.password = password;
        this.name = name;
        this.age = age;
        this.phoneNum = phoneNum;
        this.role = role;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public String getRole() {
        return role;
    }
}
public class RegisterResponse {
    public boolean isSuccess;
    public String message;

    public boolean isSuccess() {
        return isSuccess;
    }

    public String getMessage() {
        return message;
    }
}

2. RegisterActivity에 회원가입 버튼 클릭 이벤트 추가

유효성 확인은 기본적으로 진행하고, 회원가입이 정상적으로 되었다면, 로그인 페이지로 자동 이동할 수 있도록 하였습니다.

// "회원가입" 버튼 클릭 시 로직
registerButton.setOnClickListener(e2 -> {
    emailId = emailEditText.getText().toString().trim();
    selectedEmail = emailSpinner.getSelectedItem().toString();
    pwd = pwdEditText.getText().toString().trim();
    name = nameEditText.getText().toString().trim();
    age = ageEditText.getText().toString().trim();
    phoneNum = phoneNumEditText.getText().toString().trim();

    // 이메일 중복 확인을 안 했을 경우
    if (!isCheckEmail) {
        Toast.makeText(getApplicationContext(), "이메일 중복 확인을 진행해주세요.", Toast.LENGTH_SHORT).show();
        return;
    }

    // 비밀번호가 8자 미만일 경우
    if (pwd.length() < 8) {
        Toast.makeText(getApplicationContext(), "비밀번호는 8자 이상으로 입력해주세요.", Toast.LENGTH_SHORT).show();
        return;
    }

    // 이름 입력란이 비어있을 경우
    if (name.isEmpty()) {
        Toast.makeText(getApplicationContext(), "이름을 입력해주세요.", Toast.LENGTH_SHORT).show();
        return;
    }

    // 나이 값이 1 아래일 경우
    if (age.isEmpty() || Integer.parseInt(age) < 1) {
        Toast.makeText(getApplicationContext(), "나이를 입력해주세요.", Toast.LENGTH_SHORT).show();
        return;
    }

    // 전화번호가 11자가 아닐 경우 => 하이픈은 제외하고 숫자만 입력
    if (phoneNum.length() != 11) {
        Toast.makeText(getApplicationContext(), "전화번호는 하이픈 제외 11자로 입력해주세요.", Toast.LENGTH_SHORT).show();
        return;
    }

    // "기타(직접입력)" 이 선택되어있으면 이메일아이디 입력란으로 이메일 값 할당, 그게 아닐 경우 콤보박스 값까지 받아서 이메일 값 할당
    if (selectedEmail.equals("기타(직접입력)")) {
        fullEmailVal = emailId;
    } else {
        fullEmailVal = emailId + "@" + selectedEmail;
    }

    // 회원가입 진행 시 요청보낼 request 정의
    RegisterRequest request = new RegisterRequest(fullEmailVal, pwd, name, Integer.parseInt(age), phoneNum, "USER");

    // 회원가입 진행
    apiService.register(request).enqueue(new Callback<RegisterResponse>() {
        @Override
        public void onResponse(@NonNull Call<RegisterResponse> call, @NonNull Response<RegisterResponse> response) {
            if (response.isSuccessful() && response.body() != null) {
                Toast.makeText(getApplicationContext(), "회원가입이 완료되었습니다.", Toast.LENGTH_SHORT).show();
                Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
                startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(RegisterActivity.this).toBundle());
            } else {
                Toast.makeText(getApplicationContext(), "회원가입 실패. 오류 발생", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onFailure(@NonNull Call<RegisterResponse> call, @NonNull Throwable t) {
            Log.e("Retrofit", "Login Failed: " + t.getMessage(), t);
            Toast.makeText(getApplicationContext(), "서버 통신 오류", Toast.LENGTH_SHORT).show();
        }
    });
});

3. ApiService POST 요청 메서드 추가

@POST("/api/android/register")
Call<RegisterResponse> register(@Body RegisterRequest request);