관리 메뉴

나만을 위한 블로그

[Android] 레트로핏을 이용한 회원가입, 로그인 기능 구현 (with MySQL, PHP) 본문

Android

[Android] 레트로핏을 이용한 회원가입, 로그인 기능 구현 (with MySQL, PHP)

참깨빵위에참깨빵 2020. 12. 12. 16:27
728x90
반응형

※ 아래 내용은 예제 수준의 내용이기 때문에 커스텀하기 전에 코드를 반드시 이해한 다음 쓰자.

 

2020.12.12 - 모든 코드 정상 작동 확인

 

예전에 Volley를 통해 회원가입, 로그인 기능을 구현하는 포스팅을 쓴 적이 있다.

onlyfor-me-blog.tistory.com/119

 

[Android] Volley를 이용한 회원가입, 로그인 기능 구현(with MySQL, PHP)

※ 이 글은 AWS 우분투 18.04 EC2 인스턴스를 만들고 작업한 내용임 ※ 이 글은 MySQL DB에 회원가입 정보를 저장하고, 로그인할 때 MySQL에 저장된 데이터를 읽어서 로그인하며 PHP 코드를 사용함 ※ 이

onlyfor-me-blog.tistory.com

 

이번 포스팅에선 Volley가 아닌 레트로핏을 사용해서 회원가입, 로그인 기능을 구현하는 예제를 포스팅하려 한다.

먼저 DB 구조는 아래와 같다. DB명은 my_app으로 지었다.

 

 

이렇게 만든 다음 PHP 파일을 만든다. 각 파일의 내용은 아래와 같다. PHP 파일명은 주석으로 써뒀으니 참고해서 작성할 때 사용하자.

 

<?php
// retrofit_config.php

$host = "xx.xxx.xxx.xx";
$user = "root";
$password = "비밀번호";
$db = "my_app";

$con = mysqli_connect($host, $user, $password, $db);

if ($con)
{
    echo "접속 성공";
}
else
{
    echo "접속 실패";
}

 

config 파일은 DB에 연결하기 위해 사용되는 PHP 파일이다. 자신의 서버(xampp를 사용 중이라면 localhost를 적는다) 주소, DB 비밀번호를 자신의 것으로 바꿔 입력한 뒤, 웹 브라우저 주소창에 이 파일의 주소를 입력하면 접속 성공 여부에 따라 접속했는지 실패했는지를 알 수 있다.

이 파일을 웹 브라우저에서 테스트할 때 만약 한글이 깨지는 현상이 발생한다면 파일의 문자 인코딩을 UTF-8로 설정했는지 확인하자. 비주얼 스튜디오 코드를 쓴다면 하단에 인코딩 형식이 EUC-KR로 되어있을 수 있는데, 이것이나 다른 형태로 되어 있다면 UTF-8로 인코딩을 바꿔 저장해주면 문제없이 한글이 출력된다.

 

<?php
// retrofit_simpleregister.php

if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
    include_once("retrofit_config.php");

    $name = $_POST['name'];
    $username = $_POST['username'];
    $password = $_POST['password'];
    $hobby= $_POST['hobby'];

    if($name == '' || $username == '' || $password == '' || $hobby == '')
    {
        echo json_encode(array(
            "status" => "false",
            "message" => "필수 인자가 부족합니다")
        );
    }
    else
    {
        $query= "SELECT * FROM retrofitRegister WHERE username='$username'";
        $result= mysqli_query($con, $query);

        if(mysqli_num_rows($result) > 0){  
        echo json_encode(array( "status" => "false","message" => "이미 존재하는 이름입니다") );
        }
        else
        { 
            $query = "INSERT INTO retrofitRegister (name,hobby,username,password) VALUES ('$name','$hobby','$username','$password')";
            if(mysqli_query($con,$query))
            {
                $query= "SELECT * FROM retrofitRegister WHERE username='$username'";
                $result= mysqli_query($con, $query);
                $emparray = array();
                if(mysqli_num_rows($result) > 0)
                {  
                    while ($row = mysqli_fetch_assoc($result))
                    {
                        $emparray[] = $row;
                    }
                }
                echo json_encode(
                    array(
                        "status" => "true",
                        "message" => "회원가입 성공",
                        "data" => $emparray)
                    );
            }
            else
            {
                echo json_encode(
                    array(
                    "status" => "false",
                    "message" => "에러가 발생했습니다. 다시 시도해 주세요"
                    )
                );
            }
    }
    mysqli_close($con);
    }
}

 

위에서 작성한 config 파일을 써서 INSERT문으로 테이블에 데이터를 넣거나, SELECT문으로 앱에서 입력한 username을 조회해 이미 존재한다면 그것을 알려주는 PHP 파일이다.

각 쿼리가 실행된 후에는 앱으로 보낼 메시지들을 배열에 넣은 뒤 이것을 JSON 형태로 보낸다.

 

<?php
// retrofit_simplelogin.php

if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
    include_once("retrofit_config.php");

    $username = $_POST['username'];
    $password = $_POST['password'];

    if( $username == '' || $password == '')
    {
        echo json_encode(array(
            "status" => "false",
            "message" => "Parameter missing!"
        ));
    }
    else
    {
        $query= "SELECT * FROM retrofitRegister WHERE username='$username' AND password='$password'";
        $result= mysqli_query($con, $query);
        
        if(mysqli_num_rows($result) > 0)
        {  
            $query= "SELECT * FROM retrofitRegister WHERE username='$username' AND password='$password'";
            $result= mysqli_query($con, $query);
            $emparray = array();
            if(mysqli_num_rows($result) > 0)
            {  
                while ($row = mysqli_fetch_assoc($result))
                {
                    $emparray[] = $row;
                }
            }
            echo json_encode(
                array(
                    "status" => "true",
                    "message" => "로그인 성공",
                    "data" => $emparray
                )
            );
            }
            else
            { 
                echo json_encode(
                    array(
                        "status" => "false",
                        "message" => "아이디 또는 비밀번호를 확인해 주세요")
                    );
            }
            mysqli_close($con);
    }
}
else
{
    echo json_encode(
        array(
            "status" => "false",
            "message" => "에러가 발생했습니다. 다시 시도해 주세요"
        )
    );
}

 

앱에서 입력한 username, password를 통해 로그인 처리를 수행하는 PHP 파일이다.

위의 retrofit_register.php 파일과 비슷한 내용이다.

 

이제 레트로핏을 써보자. 먼저 앱 수준 gradle에 아래 의존성 문장들을 추가해준다.

 

implementation 'com.squareup.retrofit2:retrofit:2.6.4'
implementation 'com.squareup.retrofit2:converter-gson:2.6.4'
implementation 'com.squareup.retrofit2:converter-scalars:2.6.4'

 

그리고 매니페스트에도 인터넷 권한을 명시해준다. 인터넷으로 웹 서버에 접근해야 하니까 당연한 처리다.

 

<uses-permission android:name="android.permission.INTERNET" />

 

추가로 application 태그 안의 속성으로 아래 속성을 추가한다.

 

android:usesCleartextTraffic="true"

 

다음은 앱 화면과 자바 파일을 코딩하기 전 먼저 만들어야 하는 파일들이다.

먼저 쉐어드를 사용하기 때문에 쉐어드 관련 메서드들을 모아놓은 헬퍼 클래스다.

 

import android.content.Context;
import android.content.SharedPreferences;

public class PreferenceHelper
{
    private final String INTRO = "intro";
    private final String NAME = "name";
    private final String HOBBY = "hobby";
    private SharedPreferences app_prefs;
    private Context context;

    public PreferenceHelper(Context context)
    {
        app_prefs = context.getSharedPreferences("shared", 0);
        this.context = context;
    }

    public void putIsLogin(boolean loginOrOut)
    {
        SharedPreferences.Editor edit = app_prefs.edit();
        edit.putBoolean(INTRO, loginOrOut);
        edit.apply();
    }

    public void putName(String loginOrOut)
    {
        SharedPreferences.Editor edit = app_prefs.edit();
        edit.putString(NAME, loginOrOut);
        edit.apply();
    }

    public String getName()
    {
        return app_prefs.getString(NAME, "");
    }

    public void putHobby(String loginOrOut)
    {
        SharedPreferences.Editor edit = app_prefs.edit();
        edit.putString(HOBBY, loginOrOut);
        edit.apply();
    }

    public String getHobby()
    {
        return app_prefs.getString(HOBBY, "");
    }
}

 

다음은 레트로핏을 쓰는 데 꼭 필요한 RegisterInterface, LoginInterface란 이름의 인터페이스다.

하나의 인터페이스에 회원가입과 로그인을 처리하는 레트로핏 메서드를 만들어도 되지만 2개로 나눴다.

 

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface RegisterInterface
{
    String REGIST_URL = "http://xx.xxx.xxx.xx/";

    @FormUrlEncoded
    @POST("retrofit_simpleregister.php")
    Call<String> getUserRegist(
            @Field("name") String name,
            @Field("hobby") String hobby,
            @Field("username") String username,
            @Field("password") String password
    );
}
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface LoginInterface
{
    String LOGIN_URL = "http://xx.xxx.xxx.xx/";

    @FormUrlEncoded
    @POST("retrofit_simplelogin.php")
    Call<String> getUserLogin(
            @Field("username") String username,
            @Field("password") String password
    );
}

 

각 String 변수에는 자신의 서버 주소를 입력한다. 마찬가지로 xampp를 쓴다면 http://localhost/를 입력하면 된다.

여기서 정의한 메서드를 통해 PHP 파일에 접근해서 인자들을 PHP 파일로 전달하고, PHP 파일은 DB에 접근해 데이터를 추가/조회해서 회원가입, 로그인 처리를 수행하게 된다.

@Field는 POST로 서버에 값을 보낼 때 붙여야 하는 어노테이션이다. 또한 @Field() 안의 큰따옴표 안에는 PHP 파일에서 $_POST['username']; 의 [''] 안에 있는 것과 똑같은 이름을 넣어야 한다. 다른 이름을 넣으면 앱이 뻑날 수 있다.

다른 어노테이션들의 의미를 모른다면 구글링 ㄱㄱ

 

다음은 앱 코드다. 앱 화면은 회원가입을 처리하는 MainActivity, 로그인을 처리하는 LoginActivity 2가지다.

 

<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="레트로핏 회원가입"
        android:textColor="#fff"
        android:textSize="29sp" />

    <EditText
        android:id="@+id/etname"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        android:background="#fff"
        android:hint="아이디"
        android:paddingLeft="5dp" />

    <EditText
        android:id="@+id/ethobby"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="20dp"
        android:background="#fff"
        android:hint="Enter Hobby"
        android:paddingLeft="5dp" />

    <EditText
        android:id="@+id/etusername"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="20dp"
        android:background="#fff"
        android:hint="유저 이름"
        android:paddingLeft="5dp" />

    <EditText
        android:id="@+id/etpassword"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="20dp"
        android:background="#fff"
        android:hint="비밀번호"
        android:inputType="textPassword"
        android:paddingLeft="5dp" />

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="20dp"
        android:background="@color/colorPrimary"
        android:text="회원가입"
        android:textColor="#fff" />

    <TextView
        android:id="@+id/tvlogin"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="이미 아이디가 있으시다면 여길 눌러 로그인하세요"
        android:textColor="#fff"
        android:textSize="20sp" />
        
</LinearLayout>
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 org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.scalars.ScalarsConverterFactory;

public class MainActivity extends AppCompatActivity
{
    public final String TAG = "MainActivity";
    
    private EditText etname, ethobby, etusername, etpassword;
    private Button btnregister;
    private TextView tvlogin;
    private PreferenceHelper preferenceHelper;

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

        preferenceHelper = new PreferenceHelper(this);

        etname = (EditText) findViewById(R.id.etname);
        ethobby = (EditText) findViewById(R.id.ethobby);
        etusername = (EditText) findViewById(R.id.etusername);
        etpassword = (EditText) findViewById(R.id.etpassword);

        btnregister = (Button) findViewById(R.id.btn);
        tvlogin = (TextView) findViewById(R.id.tvlogin);

        tvlogin.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent intent = new Intent(MainActivity.this, LoginActivity.class);
                startActivity(intent);
                finish();
            }
        });

        btnregister.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                registerMe();
            }
        });
    }

    private void registerMe()
    {
        final String name = etname.getText().toString();
        final String hobby = ethobby.getText().toString();
        final String username = etusername.getText().toString();
        final String password = etpassword.getText().toString();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(RegisterInterface.REGIST_URL)
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

        RegisterInterface api = retrofit.create(RegisterInterface.class);
        Call<String> call = api.getUserRegist(name, hobby, username, password);
        call.enqueue(new Callback<String>()
        {
            @Override
            public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response)
            {
                if (response.isSuccessful() && response.body() != null)
                {
                    Log.e("onSuccess", response.body());

                    String jsonResponse = response.body();
                    try
                    {
                        parseRegData(jsonResponse);
                    }
                    catch (JSONException e)
                    {
                        e.printStackTrace();
                    }

                }
            }

            @Override
            public void onFailure(@NonNull Call<String> call, @NonNull Throwable t)
            {
                Log.e(TAG, "에러 = " + t.getMessage());
            }
        });
    }

    private void parseRegData(String response) throws JSONException
    {
        JSONObject jsonObject = new JSONObject(response);
        if (jsonObject.optString("status").equals("true"))
        {
            saveInfo(response);
            Toast.makeText(MainActivity.this, "회원가입 성공", Toast.LENGTH_SHORT).show();
        }
        else
        {
            Toast.makeText(MainActivity.this, jsonObject.getString("message"), Toast.LENGTH_SHORT).show();
        }
    }

    private void saveInfo(String response)
    {
        preferenceHelper.putIsLogin(true);
        try
        {
            JSONObject jsonObject = new JSONObject(response);
            if (jsonObject.getString("status").equals("true"))
            {
                JSONArray dataArray = jsonObject.getJSONArray("data");
                for (int i = 0; i < dataArray.length(); i++)
                {
                    JSONObject dataobj = dataArray.getJSONObject(i);
                    preferenceHelper.putName(dataobj.getString("name"));
                    preferenceHelper.putHobby(dataobj.getString("hobby"));
                }
            }
        }
        catch (JSONException e)
        {
            e.printStackTrace();
        }
    }

}

 

<!-- activity_login.xml -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="#000"
    android:orientation="vertical">

    <EditText
        android:id="@+id/etusername"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="20dp"
        android:background="#fff"
        android:hint="아이디"
        android:paddingLeft="5dp" />

    <EditText
        android:id="@+id/etpassword"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="20dp"
        android:background="#fff"
        android:hint="비밀번호"
        android:inputType="textPassword"
        android:paddingLeft="5dp" />

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp"
        android:layout_marginTop="10dp"
        android:layout_marginRight="20dp"
        android:background="@color/colorPrimary"
        android:text="로그인"
        android:textColor="#fff" />

    <TextView
        android:id="@+id/tvreg"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="회원가입은 여기로"
        android:textColor="#fff"
        android:textSize="20sp" />

</LinearLayout>
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 org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.scalars.ScalarsConverterFactory;

public class LoginActivity extends AppCompatActivity
{
    private final String TAG = "LoginActivity";
    
    private EditText etUname, etPass;
    private Button btnlogin;
    private TextView tvreg;
    private PreferenceHelper preferenceHelper;

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

        preferenceHelper = new PreferenceHelper(this);

        etUname = (EditText) findViewById(R.id.etusername);
        etPass = (EditText) findViewById(R.id.etpassword);

        btnlogin = (Button) findViewById(R.id.btn);
        tvreg = (TextView) findViewById(R.id.tvreg);

        tvreg.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                startActivity(intent);
                LoginActivity.this.finish();
            }
        });

        btnlogin.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                loginUser();
            }
        });
    }

    private void loginUser()
    {

        final String username = etUname.getText().toString().trim();
        final String password = etPass.getText().toString().trim();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(LoginInterface.LOGIN_URL)
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

        LoginInterface api = retrofit.create(LoginInterface.class);
        Call<String> call = api.getUserLogin(username, password);
        call.enqueue(new Callback<String>()
        {
            @Override
            public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response)
            {
                if (response.isSuccessful() && response.body() != null)
                {
                    Log.e("onSuccess", response.body());

                    String jsonResponse = response.body();
                    parseLoginData(jsonResponse);
                }
            }

            @Override
            public void onFailure(@NonNull Call<String> call, @NonNull Throwable t)
            {
                Log.e(TAG, "에러 = " + t.getMessage());
            }
        });

    }

    private void parseLoginData(String response)
    {
        try
        {
            JSONObject jsonObject = new JSONObject(response);
            if (jsonObject.getString("status").equals("true"))
            {
                saveInfo(response);

                Toast.makeText(LoginActivity.this, "Login Successfully!", Toast.LENGTH_SHORT).show();
            }
        }
        catch (JSONException e)
        {
            e.printStackTrace();
        }

    }

    private void saveInfo(String response)
    {
        preferenceHelper.putIsLogin(true);
        try
        {
            JSONObject jsonObject = new JSONObject(response);
            if (jsonObject.getString("status").equals("true"))
            {
                JSONArray dataArray = jsonObject.getJSONArray("data");
                for (int i = 0; i < dataArray.length(); i++)
                {
                    JSONObject dataobj = dataArray.getJSONObject(i);
                    preferenceHelper.putName(dataobj.getString("name"));
                    preferenceHelper.putHobby(dataobj.getString("hobby"));
                }
            }
        }
        catch (JSONException e)
        {
            e.printStackTrace();
        }
    }

}

 

각 자바 파일을 보면 JSONException을 처리하는 걸 볼 수 있다.

서버에서 JSON 형태로 값이 날아오기 때문인데, 이걸 처리하는 방법은 try-catch문을 사용하거나 메서드의 () 뒤에 throws JSONException을 써주는 2가지 방법이 있다. 둘 중 하나를 선택하면 된다.

위 처리를 했다면 JSONObject에 response.body()를 담아서 getString()으로 JSON 문자열 안의 Key 값을 빼온 다음, 그것의 Value를 통해 회원가입/로그인 성공 여부를 확인해 토스트로 출력해서 확인한다. 토스트가 안 나오더라도 로그를 통해서 회원가입/로그인 여부를 확인하면 된다.

 

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(LoginInterface.LOGIN_URL)
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

 

이 부분은 따로 클래스로 떼어내서 만들어도 된다. 클래스로 만든다면 아래와 같이 만들 수 있다.

 

public class ApiClient {

    private static final String BASE_URL = "http://xx.xxx.xxx.xx/";
    private static Retrofit retrofit;

    public static Retrofit getApiClient()
    {
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

        if (retrofit == null)
        {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(new NullOnEmptyConverterFactory())
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
        }

        return retrofit;
    }

}

 

static으로 만들었기 때문에 ApiClient를 입력하고 도트(.)를 입력하면 바로 getApiClient()가 나온다. 그리고 다시 도트를 입력하면 create()가 나오기 때문에, 도트와 엔터를 빠르게 번갈아 치면 제법 편하게 코드를 칠 수 있다.

이렇게 한 다음 액티비티에서 사용하고 인터페이스를 호출하는 법은 아래처럼 할 수 있다.

 

ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<String> call = apiInterface.methodName();
        call.enqueue(new Callback<String>() {
            @Override
            public void onResponse(Call<String> call, Response<String> response)
            {
                if (response.isSuccessful() && response.body() != null)
                {
                    getResults(response.body());
                }
            }

            @Override
            public void onFailure(Call<String> call, Throwable t)
            {
                damnError(t.getLocalizedMessage());
            }
        });

 

위 과정들을 따라왔다면 앱을 실행한 후 회원가입을 진행한 뒤 로그인을 하면 로그캣에 아래와 같은 로그가 찍힌다.

 

 

그리고 DB에도 아래처럼 값이 저장돼 있는 걸 볼 수 있다.

 

 

서버에서 JSON 형태로 날아오는 값을 파싱해 사용하는 방법은 편하기도 해서 자주 쓰이는 방법이니, 파싱하는 방법은 꼭 알아두자.

쉐어드를 쓸 필요가 없겠다 싶으면 액티비티에서 사용된 헬퍼 클래스의 메서드들만 지우면 된다.

반응형
Comments