[Android Studio] Firebase를 이용한 회원가입/로그인 구현

지우개·2024년 2월 29일
0

Android Studio

목록 보기
2/3

FireBase Authentication

FireBase Authentication는 회원과 로그인을 위한 인증과 관련된 서비스로

  • email/password을 통한 회원가입방식
  • 핸드폰 번호 인증 방식
  • OAuth2를 통한 SNS 인증 또는 타서비스 인증

3개의 회원가입 방식이 있음.

그중 email/password을 이용한 회원가입/로그인 기능을 구현할 것임.


세부 구현 내용

  • 초기 로그인 액티비티에서 회원가입 버튼을 눌러 회원가입 액티비티를 띄우고, 회원가입 화면에서 회원가입을 완료한 뒤, 다시 로그인 화면으로 돌아와 가입한 정보로 로그인에 성공하게되면 홈 액티비티로 이동하도록 구현
  • Authentication에 등록하기 위해서는 이메일, 비밀번호만 있으면 되지만, 추후 구현할 아이디 찾기와 비밀번호 재설정 액티비티를 위해서 회원가입 부분에 추가적으로 이름과 전화번호도 입력받을 수 있도록 함.
  • 그래서 이메일, 이름, 전화번호는 Firebase RealtimeDatabase에 따로 저장할 것임. 때문에 이러한 회원 정보를 저장하기 위해 사용할 객체 만들어줌.

Firebase RealtimeDatabase에 회원 정보를 저장하기 위해 회원 정보를 담을 객체
UserAccount.java

public class UserAccount {
    public UserAccount() {}
    private String id;
    private String name;
    private String number;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}

회원가입 UI

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_marginStart="20dp"
    android:layout_marginEnd="20dp"
    tools:context=".SignUpActivity">

    <TextView
        android:id="@+id/signUpTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:textSize="32dp"
        android:text="회원가입"
        android:textStyle="bold"
        android:textColor="#000000"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"></TextView>
    <LinearLayout
        android:id="@+id/signUp_linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/signUpTextView">
        <TextView
            android:id="@+id/signUp_idTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="이메일 *"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/signUp_idEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="예) apple@gmail.com"></EditText>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/signUp_linearLayout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/signUp_linearLayout1">
        <TextView
            android:id="@+id/signUp_pwTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="비밀번호 *"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/signUp_pwEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="비밀번호를 입력해주세요."
            android:inputType="textPassword"></EditText>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/signUp_linearLayout3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/signUp_linearLayout2">
        <TextView
            android:id="@+id/signUp_pwChkTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="비밀번호 확인 *"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/signUp_pwChkEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="비밀번호를 한 번 더 입력해주세요."
            android:inputType="textPassword"></EditText>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/signUp_linearLayout4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/signUp_linearLayout3">
        <TextView
            android:id="@+id/signUp_nameTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="이름 *"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/signUp_nameEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="예) 홍길동"></EditText>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/signUp_linearLayout5"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/signUp_linearLayout4">
        <TextView
            android:id="@+id/signUp_numberTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="전화번호 *"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/signUp_numberEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="예) 01012345678"></EditText>
    </LinearLayout>

    <android.widget.Button
        android:id="@+id/signUpBtn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginTop="15dp"
        android:text="회원가입"
        android:textColor="#000000"
        android:background="@drawable/button_rounded_corners"
        app:layout_constraintTop_toBottomOf="@+id/signUp_linearLayout5"></android.widget.Button>


</androidx.constraintlayout.widget.ConstraintLayout>

회원가입 액티비티
SignUpActivity.java

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

import java.util.HashMap;
import java.util.Map;

public class SignUpActivity extends AppCompatActivity {
    Button signUpBtn;

    EditText edtId, edtPw, edtPwChk, edtName, edtNumber;

    private FirebaseAuth fAuth;
    private DatabaseReference dRef; // 실시간 데이터베이스

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_signup);

        fAuth = FirebaseAuth.getInstance(); // FirebaseAuth 초기화
        dRef = FirebaseDatabase.getInstance().getReference();

        signUpBtn = (Button) findViewById(R.id.signUpBtn);

        edtId = (EditText) findViewById(R.id.signUp_idEditText);
        edtPw = (EditText) findViewById(R.id.signUp_pwEditText);
        edtPwChk = (EditText) findViewById(R.id.signUp_pwChkEditText);
        edtName = (EditText) findViewById(R.id.signUp_nameEditText);
        edtNumber = (EditText) findViewById(R.id.signUp_numberEditText);

        signUpBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final String id = edtId.getText().toString().trim();
                final String pw = edtPw.getText().toString().trim();
                final String pwChk = edtPwChk.getText().toString().trim();
                final String name = edtName.getText().toString().trim();
                final String number = edtNumber.getText().toString().trim();

                if (id.isEmpty() || pw.isEmpty() || pwChk.isEmpty() || name.isEmpty() || number.isEmpty()) {
                    Toast.makeText(SignUpActivity.this, "모든 필드를 입력하세요.", Toast.LENGTH_SHORT).show();
                    return;
                }

                if (!pw.equals(pwChk)) {
                    Toast.makeText(SignUpActivity.this, "비밀번호가 일치하지 않습니다.", Toast.LENGTH_SHORT).show();
                    return;
                }

                // Firebase Authentication을 사용하여 사용자 등록
                fAuth.createUserWithEmailAndPassword(id, pw)
                        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                            @Override
                            public void onComplete(@NonNull Task<AuthResult> task) {
                                if (task.isSuccessful()) {
                                    // 사용자 등록 성공
                                    FirebaseUser user = fAuth.getCurrentUser();
                                    String userId = user.getUid();

                                    // UserAccount 객체 생성 및 속성 설정
                                    UserAccount userAccount = new UserAccount();
                                    userAccount.setId(id);
                                    userAccount.setName(name);
                                    userAccount.setNumber(number);

                                    dRef.child("UserAccount").child(userId).setValue(userAccount);
                                    Intent intent = new Intent(SignUpActivity.this, MainActivity.class);
                                    startActivity(intent);

                                } else {
                                    // 사용자 등록 실패
                                    Toast.makeText(SignUpActivity.this, "회원가입 실패: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
                                }
                            }
                        });
            }
        });
    }
}
  • 위의 코드는 Firebase Authentication을 사용하여 사용자의 이메일 주소와 비밀번호를 통해 회원가입을 처리하고, Firebase Realtime Database를 사용하여 사용자의 정보를 데이터베이스에 저장함.
  • FirebaseAuth.getInstance()를 호출하여 Firebase의 인증 서비스에 대한 인스턴스를 가져온 다음, 이를 사용하여 createUserWithEmailAndPassword() 메서드를 호출하여 신규 사용자를 등록함.
  • 등록이 성공하면 FirebaseUser 객체를 가져와서 해당 사용자의 고유 식별자인 UID를 사용하여 데이터베이스에 사용자 정보를 저장함.
  • setValue() 메서드를 사용하여 데이터베이스에 데이터를 저장하며, 여기서는 사용자 계정 정보를 "UserAccount" 노드 아래에 사용자의 uid를 키로 사용하여 저장

사용자 정보를 입력하고 회원가입 버튼을 누르면 위와 같이 Firebase의 Authentication과 Realtime Database에 사용자의 정보가 저장된 것을 볼 수 있음.


로그인 UI

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginStart="20dp"
    android:layout_marginEnd="20dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/loginTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:textSize="32dp"
        android:text="로그인"
        android:textStyle="bold"
        android:textColor="#000000"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"></TextView>
    <LinearLayout
        android:id="@+id/login_linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/loginTextView">
        <TextView
            android:id="@+id/login_idTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="아이디"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/login_idEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="ex) apple@gmail.com"></EditText>
    </LinearLayout>
    <LinearLayout
        android:id="@+id/login_linearLayout2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:orientation="vertical"
        app:layout_constraintTop_toBottomOf="@+id/login_linearLayout1">
        <TextView
            android:id="@+id/login_pwTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="12dp"
            android:text="비밀번호"
            android:textColor="#000000"></TextView>
        <EditText
            android:id="@+id/login_pwEditText"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:paddingLeft="16dp"
            android:paddingRight="16dp"
            android:textSize="12dp"
            android:background="@drawable/edittext_rounded_border"
            android:hint="비밀번호를 입력하세요."
            android:inputType="textPassword"></EditText>
    </LinearLayout>
    <android.widget.Button
        android:id="@+id/loginBtn"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginTop="15dp"
        android:text="로그인"
        android:textColor="#000000"
        android:background="@drawable/button_rounded_corners"
        app:layout_constraintTop_toBottomOf="@+id/login_linearLayout2"></android.widget.Button>
    <LinearLayout
        android:id="@+id/login_linearLayout3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="15dp"
        android:orientation="horizontal"
        android:gravity="center"
        app:layout_constraintTop_toBottomOf="@+id/loginBtn">
        <TextView
            android:id="@+id/findIdTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="15dp"
            android:text="아이디 찾기"
            android:textColor="#aeaeae"></TextView>
        <TextView
            android:id="@+id/findPwTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="15dp"
            android:text="비밀번호 찾기"
            android:textColor="#aeaeae"></TextView>
        <TextView
            android:id="@+id/signUpTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="회원가입"
            android:textColor="#aeaeae"></TextView>
    </LinearLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

로그인 액티비티
MainActivity.java

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

public class MainActivity extends AppCompatActivity {

    private FirebaseAuth fAuth; // 파이어베이스 인증
    private DatabaseReference dRef; // 실시간 데이터베이스

    Button loginBtn;
    TextView findIdTextView, findPwTextView, signUpTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText edtId, edtPw;

        fAuth = FirebaseAuth.getInstance();
        dRef = FirebaseDatabase.getInstance().getReference();

        edtId = findViewById(R.id.login_idEditText);
        edtPw = findViewById(R.id.login_pwEditText);

        loginBtn = (Button) findViewById(R.id.loginBtn);
        findIdTextView = (TextView) findViewById(R.id.findIdTextView);
        findPwTextView = (TextView) findViewById(R.id.findPwTextView);
        signUpTextView = (TextView) findViewById(R.id.signUpTextView);

        loginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final String id = edtId.getText().toString();
                final String pw = edtPw.getText().toString();

                if (id.isEmpty() || pw.isEmpty()) {
                    Toast.makeText(MainActivity.this, "아이디와 비밀번호를 입력하세요.", Toast.LENGTH_SHORT).show();
                    return;
                }

                fAuth.signInWithEmailAndPassword(id, pw).addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d("MainActivity", "로그인 시도 완료");
                        if (task.isSuccessful()) {
                            Log.d("MainActivity", "로그인 성공");
                            Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                            startActivity(intent);
                        } else {
                            Log.d("MainActivity", "로그인 실패", task.getException());
                            Toast.makeText(MainActivity.this, "로그인 실패: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }
        });

        findIdTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // findIdTextView를 클릭했을 때의 동작
                Intent intent = new Intent(MainActivity.this, FindIdActivity.class);
                startActivity(intent);
            }
        });

        findPwTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // findPwTextView를 클릭했을 때의 동작
                Intent intent = new Intent(MainActivity.this, FindPasswordActivity.class);
                startActivity(intent);
            }
        });

        signUpTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // signUpTextView를 클릭했을 때의 동작
                Intent intent = new Intent(MainActivity.this, SignUpActivity.class);
                startActivity(intent);
            }
        });
    }
}
  • FirebaseAuth와 DatabaseReference를 초기화하여 Firebase의 인증 및 데이터베이스 서비스를 사용할 수 있도록 함.
fAuth.signInWithEmailAndPassword(id, pw).addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        Log.d("MainActivity", "로그인 시도 완료");
                        if (task.isSuccessful()) {
                            Log.d("MainActivity", "로그인 성공");
                            Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                            startActivity(intent);
                        } else {
                            Log.d("MainActivity", "로그인 실패", task.getException());
                            Toast.makeText(MainActivity.this, "로그인 실패: " + task.getException().getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    }
                });
  • 위 코드는 Firebase Authentication을 사용하여 사용자가 제공한 이메일 주소와 비밀번호로 로그인을 시도함.

  • fAuth.signInWithEmailAndPassword(id, pw)
    여기서 fAuth는 FirebaseAuth 객체를 나타내고, signInWithEmailAndPassword() 메서드는 이메일 주소와 비밀번호를 인자로 받아 사용자를 로그인함.

  • 사용자가 로그인 버튼을 클릭하면 사용자가 입력한 아이디와 비밀번호를 사용하여 Firebase 인증을 시도함. 로그인이 성공하면 SecondActivity로 이동하고, 실패하면 사용자에게 실패 이유를 알림

  • 사용자가 각각의 텍스트뷰를 클릭하면 해당 화면(아이디 찾기, 비밀번호 찾기, 회원가입 화면)으로 이동

0개의 댓글