๊ด€๋ฆฌ ๋ฉ”๋‰ด

ruriruriya

[Android] ์•ˆ๋“œ๋กœ์ด๋“œ - Retrofit2 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์„ ์œ„ํ•œ ์„ค์ • ๋ฐฉ๋ฒ• ๋ณธ๋ฌธ

๐Ÿค–Android/Java

[Android] ์•ˆ๋“œ๋กœ์ด๋“œ - Retrofit2 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์„ ์œ„ํ•œ ์„ค์ • ๋ฐฉ๋ฒ•

๋ฃจ๋ฆฌ์•ผใ…‘ 2024. 1. 4. 14:11
๋ฐ˜์‘ํ˜•

Retrofit์€ ์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ์—์„œ ๋„คํŠธ์›Œํฌ ํ†ต์‹ ์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. ์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” Square์‚ฌ์—์„œ ๊ฐœ๋ฐœ๋˜์—ˆ์œผ๋ฉฐ, ์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ์—์„œ RESTful API์™€์˜ ํ†ต์‹ ์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

 

Retrofit์˜ ์ฃผ์š” ๊ธฐ๋Šฅ

  • API Interface ์ •์˜: Retrofit์„ ์‚ฌ์šฉํ•˜๋ฉด REST API์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ์ธํ„ฐํŽ˜์ด์Šค์—์„œ API ์—”๋“œํฌ์ธํŠธ, HTTP ์š”์ฒญ ๋ฉ”์†Œ๋“œ, ์š”์ฒญ ์‹œ ํ•„์š”ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋“ฑ์„ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.
  • HTTP ํด๋ผ์ด์–ธํŠธ ์„ค์ •: Retrofit์€ OkHttp์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์–ด, HTTP ํด๋ผ์ด์–ธํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์„ค์ •ํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค€๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ ์„ค์ •, ํƒ€์ž„์•„์›ƒ ๋“ฑ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Annotation ๊ธฐ๋ฐ˜์˜ ์š”์ฒญ ์ฒ˜๋ฆฌ: Retrofit์€ ์• ๋…ธํ…Œ์ด์…˜ ๊ธฐ๋ฐ˜์œผ๋กœ HTTP ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ๋ฉ”์†Œ๋“œ์— @GET, @POST, @PUT, @DELETE ๋“ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์˜ ์ข…๋ฅ˜์™€ ์š”์ฒญ URL์„ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ์ฒด ์ง๋ ฌํ™” ๋ฐ ์—ญ์ง๋ ฌํ™”: JSON ๋˜๋Š” XML๊ณผ ๊ฐ™์€ ๋ฐ์ดํ„ฐ ํ˜•์‹์„ ์•ˆ๋“œ๋กœ์ด๋“œ ์•ฑ์˜ ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ ๊ทธ ๋ฐ˜๋Œ€๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” Gson๊ณผ ๊ฐ™์€ ์ปจ๋ฒ„ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌ๋œ๋‹ค.
  • ๋น„๋™๊ธฐ์  ์‘๋‹ต ์ฒ˜๋ฆฌ: Retrofit์€ HTTP ์š”์ฒญ์„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ์ฐจ๋‹จํ•˜์ง€ ์•Š๊ณ  ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค. ์ฝœ๋ฐฑ, RxJava ๋“ฑ์„ ํ™œ์šฉํ•˜์—ฌ ์‘๋‹ต์„ ๋ฐ›๊ณ  ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

 

1. api ํŒจํ‚ค์ง€-NetworkClient.class ์ƒ์„ฑ

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ์„ ์œ„ํ•œ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ค๊ณ 
getRetrofitClient ํ•จ์ˆ˜๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ž‘์„ฑํ•œ๋‹ค.

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) // 1๋ถ„๋™์•ˆ ์ž‘์—…์„ ํ•˜๊ธฐ ์œ„ํ•ด ์—ฐ๊ฒฐ (์‚ฌ์ง„ ์ „์†ก ๋“ฑ)
                    .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;
    }
}

 

2. api ํŒจํ‚ค์ง€ - UserApi.class ์ƒ์„ฑ

- UserApi.class๋ฅผ ์ƒ์„ฑํ•œ ๋’ค Interface๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.

- register ํšŒ์›๊ฐ€์ž… api์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž…๋ ฅ๋ฐ›์€ ๋‚ด์šฉ์„ User user๋กœ ๋ฐ›์•„์˜ค๊ณ (์ด ๋•Œ, User ํด๋ž˜์Šค ์ƒ์„ฑ)
์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๊ฐ€ ๋๋‚˜๋ฉด UserRes๋กœ ์‘๋‹ต์„ ์ „๋‹ฌํ•œ๋‹ค.(์ด ๋•Œ, UserRes ํด๋ž˜์Šค ์ƒ์„ฑ) 

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

public interface UserApi {
    // ํšŒ์›๊ฐ€์ž… Api
    @POST("/user/register")
    Call<UserRes> register(@Body User user); 

}

 

3. model ํŒจํ‚ค์ง€ - User.class ์ƒ์„ฑ

์ƒ์„ฑ์ž๊นŒ์ง€ ๋ฏธ๋ฆฌ ์ƒ์„ฑํ•ด์ค€๋‹ค.

public class User {

    public String email;
    public String password;
    public String nickname;

    public User(){

    }

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

 

4. model ํŒจํ‚ค์ง€ - UserRes.class ์ƒ์„ฑ

์‘๋‹ต ๋ฐ›์„ ๋ณ€์ˆ˜๋“ค์„ ๋งŒ๋“ค์–ด์ค€๋‹ค.

public class UserRes {

    // ์‘๋‹ต...!
    public String result;
    public String access_token;

}

 

5. ํ•ด๋‹น Activity ์„ค์ •

๋ณธ์ธ์€ ํšŒ์›๊ฐ€์ž…์„ ์œ„ํ•œ Activity๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

  1. retrofit ์‚ฌ์šฉ์„ ์œ„ํ•œ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  2. api ํŒจํ‚ค์ง€์— ์žˆ๋Š”, Interface๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  3. ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌถ์Œ ์ฒ˜๋ฆฌํ•ด์„œ ๋งŒ๋“ ๋‹ค.
  4. api ํ˜ธ์ถœํ•œ๋‹ค.
  5. ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
btnRegister.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String email = editEmail.getText().toString().trim();
        String password = editPassword.getText().toString().trim();
        String nickname = editNickname.getText().toString().trim();

        // ๋„คํŠธ์›Œํฌ ํšŒ์›๊ฐ€์ž… API๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. โ˜…โ˜…โ˜…โ˜…โ˜…
        
        // 1. retrofit ๋ณ€์ˆ˜ ์ƒ์„ฑ
        Retrofit retrofit = NetworkClient.getRetrofitClient(RegisterActivity.this);

        // 2. api ํŒจํ‚ค์ง€์— ์žˆ๋Š”, Interface ์ƒ์„ฑ
        UserApi api = retrofit.create(UserApi.class);

        // 3. ๋ณด๋‚ผ ๋ฐ์ดํ„ฐ ๋งŒ๋“ ๋‹ค. => ๋ฌถ์Œ ์ฒ˜๋ฆฌ : ํด๋ž˜์Šค์˜ ๊ฐ์ฒด ์ƒ์„ฑ.

        User user = new User(email, password, nickname);

        // 4. api ํ˜ธ์ถœ
        Call<UserRes> call = api.register(user);

        // 5. ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ ์ž‘์„ฑ.
        call.enqueue(new Callback<UserRes>() {
            @Override
            public void onResponse(Call<UserRes> call, Response<UserRes> response) {
            
                // ์„œ๋ฒ„์—์„œ ๋ณด๋‚ธ ์‘๋‹ต์ด 200 OK์ผ ๋•Œ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ
                if(response.isSuccessful()){
                    UserRes userRes = response.body();

                    SharedPreferences sp = getSharedPreferences(Config.PREFERENCE_NAME,MODE_PRIVATE);
                    SharedPreferences.Editor editor = sp.edit();
                    editor.putString("token",userRes.access_token);
                    editor.apply();

                    // ์ด์ƒ ์—†์œผ๋ฏ€๋กœ ๋ฉ”์ธ ์•กํ‹ฐ๋น„ํ‹ฐ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
                    Intent intent = new Intent(RegisterActivity.this,MainActivity.class);
                    startActivity(intent);
                    finish();
                }


            }

            @Override
            public void onFailure(Call<UserRes> call, Throwable t) {

                // ์œ ์ €ํ•œํ…Œ ๋„คํŠธ์›Œํฌ ํ†ต์‹  ์‹คํŒจํ–ˆ๋‹ค๊ณ  ์•Œ๋ ค์ค€๋‹ค.
                Toast.makeText(RegisterActivity.this,"๋„คํŠธ์›Œํฌ ํ†ต์‹  ์‹คํŒจ.",Toast.LENGTH_SHORT).show();

            }
        });


    }
});

 

๋ฐ˜์‘ํ˜•