군침이 싹 도는 코딩

retrofit2 라이브러리를 이용한 POST 형식 처리 본문

Android

retrofit2 라이브러리를 이용한 POST 형식 처리

mugoori 2023. 2. 9. 16:10
{
    "email": "lll@naver.com",
    "password": "1234",
    "nickname": "Mue"
}
{
    "result": "success",
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTY3NTkwNzE0NiwianRpIjoiNzA1MGZjYTItMjc5ZS00MDU2LWFkYmEtNDQzMjRlNzM4ZjRlIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6MTMsIm5iZiI6MTY3NTkwNzE0Nn0.xNmzizM7Aqfl4dmKYGceHHgR67pgMM1DHeJwHDPpclo"
}

# POST 형식의 이러한 body 데이터를 주면 아래와 같이 답을 해주는 API를 처리해보자

 

 

 

 

# 안드로이드 스튜디오의 구조를 이런식으로 짠다

model에는 body와 response에 들어갈 데이터를 config에는 노출되면 안되는 데이터

api에는 레트로핏 객체를 반환해줄 NetworkClient와  유저와 관련된 api 실행해줄 UserApi를 만든다

 

 

 

package com.mugoori.memoapp.model;

import java.io.Serializable;

// retrofit 라이브러리를 통해서 body 에 Json 으로 데이터를 보낼 클래스
// 1. Serializable 해준다
// 2. API 명세서를 보고 멤버변수를 만든다
// 3. 멤버 변수를 private 으로 해준다
// 4. Getter / Setter 만들어준다
public class User implements Serializable {
    private String email;
    private String password;
    private String nickname;

    public User(){

    }

    public User(String email, String password, String nickname) {
        this.email = email;
        this.password = password;
        this.nickname = nickname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }
}

# 회원가입을 할때 바디에 보내줄 데이터를 적을 user 클래스를 만들어준다

여기에 멤버변수는 모두 프라이빗으로 만들어주고  다른곳에서 사용하기위해 게터세터를 만들어준다

 

 

 

package com.mugoori.memoapp.model;



import java.io.Serializable;

// retrofit 라이브러리를 통해서 응답받는 클래스
public class UserRes implements Serializable {
    private String result;
    private String access_token;

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public String getAccess_token() {
        return access_token;
    }

    public void setAccess_token(String access_token) {
        this.access_token = access_token;
    }
}

# response 로 응답받는 클래스 UserRes를 만들어준다

마찬가지로 여기도 클래스를 직렬화해주고 프라이빗으로 멤버변수를 만들어준다

그리고 게터세터를 만든다

 

 

 

package com.mugoori.memoapp.config;

public class Config {

    public static final String DOMAIN = "도메인 주소";
    public static final String DOMAIN_TEST = "http://localhost:5000";
    public static final String PREFERENCE_NAME = "memo_app";
    public static final String ACCESS_TOKEN = "access_token";

}

# 컨픽 클래스를 만들어 중요한 정보를 저장한다

도메인 주소나 억세스키 프리페어런스 저장소 이름등을 저장해놓는다

 

 

 

 

package com.mugoori.memoapp.api;

import com.mugoori.memoapp.model.User;
import com.mugoori.memoapp.model.UserRes;

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;

// 유저 관련 API 들을 모아놓은 인터페이스
public interface UserApi {

    // 회원가입 API 함수 작성
    @POST("/user/register")
    // 리턴         함수이름       함수 파라미터
    Call<UserRes> register(@Body User user);
}

# 유저 관련 API 를 작성할 인터페이스 UserApi 를 만든다

@POST ( 경로 )

Call<반환받는 클래스> 함수이름(@Body 넘겨줄 객체) 를 써준다

 

 

 

package com.mugoori.memoapp.api;

import android.content.Context;

import com.mugoori.memoapp.config.Config;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class NetworkClient {

    public static Retrofit retrofit;

    public static Retrofit getRetrofitClient(Context context){
        if( retrofit == null ){
            // 통신로그 확인할때 필요한 코드
            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

            // 네트워크 연결관련 코드
            OkHttpClient httpClient = new OkHttpClient.Builder().connectTimeout(1, TimeUnit.MINUTES).readTimeout(1,TimeUnit.MINUTES)
                    .writeTimeout(1,TimeUnit.MINUTES).addInterceptor(loggingInterceptor).build();

            // 네트워크로 데이터를 보내고 받는 레트로핏 라이브러리 관련 코드
            retrofit = new Retrofit.Builder().baseUrl(Config.DOMAIN).client(httpClient).addConverterFactory(GsonConverterFactory.create()).build();

        }
        return retrofit;
    }
}

# 네트워크 통신에 필요한 레트로핏 라이브러리를 반환할 클래스 NetworkClient를 작성한다

 

 

 

package com.mugoori.memoapp;

import androidx.appcompat.app.AppCompatActivity;

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

import com.mugoori.memoapp.api.NetworkClient;
import com.mugoori.memoapp.api.UserApi;
import com.mugoori.memoapp.config.Config;
import com.mugoori.memoapp.model.User;
import com.mugoori.memoapp.model.UserRes;

import java.util.regex.Pattern;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;

public class RegisterActivity extends AppCompatActivity {

    EditText editEmail;
    EditText editPassword;
    EditText editNickname;
    Button btnRegister;
    TextView txtLogin;

    // 네트워크를 통해서 로직처리를 할때 보여주는 프로그레스 다이얼로그
    ProgressDialog dialog;


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

        editEmail = findViewById(R.id.editEmail);
        editPassword = findViewById(R.id.editPassword);
        editNickname = findViewById(R.id.editNickname);
        btnRegister = findViewById(R.id.btnRegister);
        txtLogin = findViewById(R.id.txtLogin);

        btnRegister.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 이메일 가져와서 형식 체크
                String email = editEmail.getText().toString().trim();
                Pattern pattern = Patterns.EMAIL_ADDRESS;
                if (pattern.matcher(email).matches() == false){
                    Toast.makeText(RegisterActivity.this, "이메일 형식이 올바르지 않습니다", Toast.LENGTH_SHORT).show();
                    return;
                }

                // 비밀번호 체크
                String password = editPassword.getText().toString().trim();
                // 우리 기획에는 비번길이가 4~12 만 허용
                if ( password.length() < 4 || password.length() > 12) {
                    Toast.makeText(RegisterActivity.this, "4자리 이상 12자리 이하로 입력해주세요", Toast.LENGTH_SHORT).show();
                    return;
                }

                // 닉네임 가져온다
                String nickname = editNickname.getText().toString().trim();

                if ( nickname.isEmpty() ){
                    Toast.makeText(RegisterActivity.this, "닉네임을 입력해주세요", Toast.LENGTH_SHORT).show();
                    return;
                }

                // 회원가입 API 를 호출

                // 1. 다이얼로그를 화면에 보여준다
                showProgress("회원가입 중입니다...");

                // 2. 서버로 데이터를 보낸다
                // 2-1 레트로핏 변수 생성
                Retrofit retrofit = NetworkClient.getRetrofitClient(RegisterActivity.this);

                // 2-2 api 패키지에 있는 인터페이스 생성
                UserApi api = retrofit.create(UserApi.class);

                // 2-3 보낼 데이터 만들기 => 클래스의 객체 생성
                User user = new User(email, password, nickname);

                // 2-4 api 호출
                Call<UserRes> call = api.register(user);

                // 2.5 서버로부터 받아온 응답 처리하는 코드 작성
                call.enqueue(new Callback<UserRes>() {
                    @Override
                    public void onResponse(Call<UserRes> call, Response<UserRes> response) {
                        // 프로그레스 다이얼로그가 있으면 나타나지 않게 해준다
                        dismissProgress();

                        // 서버에서 보낸 응답이 200 OK 일때 처리하는 코드
                        if (response.isSuccessful()){
                            Log.i("MEMO_APP",response.toString());

                            // 서버가 보낸 데이터를 받는 방법
                            UserRes res = response.body();

                            Log.i("MEMO_APP",res.getResult());
                            Log.i("MEMO_APP",res.getAccess_token());

                            // 억세스 토큰은 api 호출할때마다 헤더에서 사용하므로 회원가입이나 로그인이 끝나면 파일로 꼭 저장해야한다
                            SharedPreferences sp = getApplication().getSharedPreferences(Config.PREFERENCE_NAME,MODE_PRIVATE);
                            SharedPreferences.Editor editor = sp.edit();
                            editor.putString(Config.ACCESS_TOKEN,res.getAccess_token());
                            editor.apply();

                            // 3. 데이터를 이상없이 처리하면 메인액티비티를 화면에 나오게 한다
                            finish();

                        }else{
                            Log.i("MEMO_APP",response.toString());
                        }

                    }

                    @Override
                    public void onFailure(Call<UserRes> call, Throwable t) {
                        // 프로그레스 다이얼로그가 있으면 나타나지 않게 해준다
                        dismissProgress();
                    }
                });


            }
        });
    }

    // 네트워크 로직 처리시에 화면에 보여주는 함수
    void showProgress(String message){
        dialog = new ProgressDialog(this);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.setMessage(message);
        dialog.show();
    }

    // 로직처리가 끝나면 화면에서 사라지는 함수
    void dismissProgress(){
        dialog.dismiss();
    }
}

# 회원가입 액티비티를 작성한다