ํ์ฌ์์ ๊ธฐ์กด์ ๋ง๋ค์ด์ง ์ดํ์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ด ์์ด์ ์๋กญ๊ฒ ์ถ๊ฐํ๊ฒ ๋์๋ค. ์๋๋ก์ด๋ ์ฑ์ ์๊ฒ๋๋ง ๋ง๋ค์ด๋ด์ ๊น์ ์ง์์ ์์ง๋ง, ์ด๋ฒ์ ๋ ํ๊ฐ์ง ๋ฐฐ์๊ฐ๋๊ฒ ๊ฐ์ ์๋ฏธ๊ฐ ์์๋ ์์ ์ด๋ค. ์ฒ์์ Retrofit์ ์ฌ์ฉํ์ง ์๊ณ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋๋ฐ, ์ฌ๋ฌ๊ฐ์ง ์ ๋ณด๋ฅผ ์ฐพ์๋ณด๋ ์๋๋ ํต์ ๋ฐฉ๋ฒ ๋ฑ Retrofit์ด ์ฑ๋ฅ์ ์ผ๋ก ๋ ์ข๋ค๋ ๋ด์ฉ์ด ์์๋ค.
Retrofit, ์น ์๋ฒ๋ฅผ ์ด์ฉํ ๋ก๊ทธ์ธ ๋ง๋ค๊ธฐ ์์
1. ํ๋ก์ ํธ ์์ฑ
2. Activityํ๋ฉด๋ค ์์ฑ(๋ก๊ทธ์ธ, ๊ฒฐ๊ณผํ์ด์ง)
3. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐ ํ๊ฒฝ์ค์
4. ํ์ด์ง๋ณ ์ปจํธ๋กค๋ฌ ๋ฐ ์๋น์ค, VO ๋ฑ ์์ฑ
5. ์น ์๋ฒ ๊ตฌ์ถ(egovFramework ๊ธฐ๋ฐ์ API ์น ์๋ฒ ๊ตฌ์ถ)
6. ํ ์คํธ
๋ก๊ทธ์ธ ์ดํ๋ฆฌ์ผ์ด์ ํ๋ก์ ํธ ์์ฑ
1. ์๋๋ก์ด๋ ์คํ๋์ค๋ฅผ ํตํด ๋ก๊ทธ์ธ ํ๋ก์ ํธ๋ฅผ ๋ง๋ ๋ค.
File > New > New Project ๋ฉ๋ด๋ฅผ ์ ํํด ํ๋ก์ ํธ ์์ฑ์ ์งํํ๋ค. Activityํ๋ฉด์ ์ ํํ๋ ๋์์๋ ๋ก๊ทธ์ธ Activity๋ฅผ ์ ํํ๋ค๊ฐ ์๋กญ๊ฒ ํ๋ฉด๋ค์ ๊ตฌ์ฑํ๊ณ ์ Empty Activity๋ฅผ ์ ํํ๊ณ , RetrofitLoginTest ๋ผ๋ ์ด๋ฆ์ผ๋ก ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ค.
Name : RetrofitLoginTest
Package name : com.example.retrofitlogintest
Language : Java
Minimum SDK : API 16: Android 4.1
Use legacy android.support libraries - check!
๋ก๊ทธ์ธ ์ดํ๋ฆฌ์ผ์ด์ Activityํ๋ฉด๋ค ์์ฑ(๋ก๊ทธ์ธ, ๊ฒฐ๊ณผํ์ด์ง)
โ ๋ก๊ทธ์ธ ํ์ด์ง์์ฑ
2. res/layout/activity_main.xml ํ์ผ์ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์์ ํ๋ค.
activity_main.xml ํ์ผ ๋ด, Designํญ์์ ์ํ๋ ๋ก๊ทธ์ธ ํ๋ฉด์ ๊ตฌ์ฑํ๋ค. ์์ฑ์๋ ID,PW์ ๋ ฅ๋๊ณผ ๋ก๊ทธ์ธ ๋ฒํผ์ ๋์์ธํ๋ค.
๊ฐ ์ปดํฌ๋ํธ๋ค์ id์ Constraint Widget, Text๋ฅผ ์์ ํ๋ค.
Component Widget EditText 'ID'
id : editText_id
Constraint Widget : ์ผ(100), ์(340), ์ค(100), ์๋(10)
Text : ๊ณต๋ฐฑ
Component Widget EditText 'PW'
id : editText_pw
Constraint Widget : ์ผ(100), ์(10), ์ค(100), ์๋(10)
Text : ๊ณต๋ฐฑ
Component Widget Button 'Login'
id : btn_login
Constraint Widget : ์ผ(160), ์(10), ์ค(160), ์๋(215)
Text : LOGIN
[Activity_main.xml] Source
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
tools:context=".MainActivity">
<EditText
android:id="@+id/editText_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:layout_marginLeft="100dp"
android:layout_marginTop="340dp"
android:layout_marginEnd="100dp"
android:layout_marginRight="100dp"
android:layout_marginBottom="10dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintBottom_toTopOf="@+id/editText_pw"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/editText_pw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:layout_marginLeft="100dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="100dp"
android:layout_marginRight="100dp"
android:layout_marginBottom="10dp"
android:ems="10"
android:inputType="textPassword"
app:layout_constraintBottom_toTopOf="@+id/btn_login"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText_id" />
<Button
android:id="@+id/btn_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="160dp"
android:layout_marginLeft="160dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="160dp"
android:layout_marginRight="160dp"
android:layout_marginBottom="215dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText_pw" />
</android.support.constraint.ConstraintLayout>
โ ๋ก๊ทธ์ธ ๊ฒฐ๊ณผ ํ์ด์ง์์ฑ
3. activity_result.xml ํ์ผ์ ์๋กญ๊ฒ ์ถ๊ฐํ๋ค.
activity_result.xml ํ์ผ ๋ด, Designํญ์์ ์ํ๋ ๋ก๊ทธ์ธ ๊ฒฐ๊ณผ ํ๋ฉด์ ๊ตฌ์ฑํ๋ค. ์์ฑ์๋ ๋ก๊ทธ์ธ ํ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ ์ ์๋๋ก TextView์ ๋์์ธํ๋ค. ์ปดํฌ๋ํธ์ id์ Constraint Widget, Text๋ฅผ ์์ ํ๋ค.
Component Widget TextView 'Result'
id : textView_result
Constraint Widget : ์ผ(20), ์(320), ์ค(20), ์๋(320)
Text : ๊ณต๋ฐฑ
[Activity_result.xml] Source
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">
<TextView
android:id="@+id/textView_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="320dp"
android:layout_marginEnd="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="320dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
๋ก๊ทธ์ธ ์ดํ๋ฆฌ์ผ์ด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐ ํ๊ฒฝ์ค์
โ build.gradle
4. build.gradle, AndroidManifest.xml์์ ์ถ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐ ์ค์ ๊ฐ์ ์ ํ ํ๋ค.
[build.gradle] Source
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.retrofitlogintest"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
}
Retrofit์ ์ด์ฉํ ๋ก๊ทธ์ธ ์ดํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ๊ธฐ ์ํด ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐ ์ปดํ์ผ ์ค์ ๋ฑ๋ฑ์ ์ค์ ํ๊ธฐ ์ํด์ build.gradleํ์ผ์ ์ถ๊ฐ ๋ฐ ์์ ํฉ๋๋ค.
โ AndroidManifest.xml
[AndroidManifest.xml] Source
์ ํ๋ฆฌ์ผ์ด์ ์์ ๋คํธ์ํฌ ์์ ์ ์คํํ๋ ค๋ฉด ๋งค๋ํ์คํธ์ ๋ค์ ๊ถํ์ ํฌํจํด์ผ ํ๋ค.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.retrofitlogintest">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.RetrofitLoginTest"
android:usesCleartextTraffic="true">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ResultActivity"/>
</application>
</manifest>
android.permission.INTERNET, android.permission.ACCESS_NETWORK_STATE๋ฅผ ์ถ๊ฐํ๋ค.
๊ทธ๋ฆฌ๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ๋ฉด์ ๋ฐ์ํ๋ ๋ฌธ์ ์ ์ค์์, http://์ https://์ค์์ ๋ ์๋ฒ ๋ด, ์ ํ ๋ ์น ์๋ฒ๋ http://๋ก ๋์ด ์๋๋ฐ ์ด ์์ฒญ์ด ๊ฐ๋ฅํ๊ฒ ํ๊ธฐ ์ํด์๋ android:usesCleartextTraffic="true"์ค์ ๊ฐ์ด ํ์ํ๋ค๋๊ฑธ ์ฌ๋ฌ๊ฐ์ง ๊ฒ์์ ํตํด์ ์๊ฒ๋์๋ค. ๊ทธ๋ฆฌ๊ณ ์ฐ๊ฒฐ๋ ํ์ด์ง์ Activity๋ค๋ activity ํ๊ทธ๋ฅผ ์ด์ฉํด ์ถ๊ฐํด์ฃผ์ด์ผ ํ๋ค.
5. build.gradle์์ ์ถ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐ ์ค์ ๊ฐ์ ์ ํ ํ๋ค.
ํ๋ก์ ํธ ์ ์ฒด ๋ด์ฉ์ด๋ค. ํ์ด์ง์ ํ๊ฒฝ์ค์ ๋ถ๋ถ์ด ๋๋ฌ์ผ๋ ๊ด๋ จ ์ปจํธ๋กค๋ฌ ๋ฐ ์๋น์ค,VO๋ฅผ ์์ฑํ๋๋ก ํ๋ค. ํ๋ก์ ํธ ์ ์ฒด ๊ตฌ์กฐ๋ ์ ์ด๋ฏธ์ง์ ๊ฐ๋ค.
ํ์ด์ง๋ณ ์ปจํธ๋กค๋ฌ ๋ฐ ์๋น์ค, VO ๋ฑ ์์ฑ
6. MemberVO, ILoginService, MainActivity, ResultActivity ๋ฑ ์์ฑํ๋ค.
๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์์ ์๋๋ก ๋ฐ์ดํฐ ๊ณต๊ฐ์ ๋ง๋ค์ด์ค๋ค.
[MemberVO] Source
package com.example.retrofitlogintest.vo;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.SerializedName;
public class MemberVO implements Parcelable {
@SerializedName("mem_no")
private int mem_no;
@SerializedName("mem_id")
private String mem_id;
@SerializedName("mem_pw")
private String mem_pw;
@SerializedName("mem_name")
private String mem_name;
public MemberVO(String mem_id, String mem_pw){
this.mem_id = mem_id;
this.mem_pw = mem_pw;
}
public int getMem_no(){
return mem_no;
}
public void setMem_no(int mem_no){
this.mem_no = mem_no;
}
public String getMem_id(){
return mem_id;
}
public void setMem_id(String mem_id){
this.mem_id = mem_id;
}
public String getMem_pw(){
return mem_pw;
}
public void setMem_pw(String mem_pw){
this.mem_pw = mem_pw;
}
public String getMem_name(){
return mem_name;
}
public void setMem_name(String mem_name){
this.mem_name = mem_name;
}
protected MemberVO(Parcel in) {
mem_no = in.readInt();
mem_id = in.readString();
mem_pw = in.readString();
mem_name = in.readString();
}
public static final Creator<MemberVO> CREATOR = new Creator<MemberVO>() {
@Override
public MemberVO createFromParcel(Parcel in) {
return new MemberVO(in);
}
@Override
public MemberVO[] newArray(int size) {
return new MemberVO[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(mem_no);
parcel.writeString(mem_id);
parcel.writeString(mem_pw);
parcel.writeString(mem_name);
}
}
implements Parcelable์ ์ค์ ํ ์ด์ ๋ ๊ฐ๊ฐ์ Activity๋ก ํ๋ผ๋ฏธํฐ๋ฅผ ๋๊ฒจ์ค๋ ์ฌ์ฉํ๊ธฐ ์ํด์๋ค. MemberVO๋ฅผ ์์ฑํ ๋ ๊ธฐ๋ณธ ์์ด๋, ๋น๋ฐ๋ฒํธ๋ฅผ ๋ด์ ์ด๊ธฐํ ํ ์ ์๋๋ก ํด์ฃผ์๋ค.
[ILgoinService] Source
package com.example.retrofitlogintest.login;
import com.example.retrofitlogintest.vo.MemberVO;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface ILoginService {
@GET("app/getMember.do")
Call<MemberVO> getMember(@Query("mem_id") String mem_id, @Query("mem_pw") String mem_pw);
}
์ ๋ ฅํ ์์ด๋์ ๋น๋ฐ๋ฒํธ๋ฅผ ํตํด DB์ ์ ์ฅ๋์ด ์๋ ํ์์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํ ์ธํฐํ์ด์ค๋ฅผ ์์ฑํ๋ค. ์ฟผ๋ฆฌ ๋ด ํ๋ผ๋ฏธํฐ๋ฅผ ๋๊ธฐ๊ธฐ์ํด @Query ์ด๋ ธํ ์ด์ ์ผ๋ก ํ๋ผ๋ฏธํฐ๋ช ์ ์ ํ ํ๋ค.
[MainActivity] Source
package com.example.retrofitlogintest;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.example.retrofitlogintest.login.ILoginService;
import com.example.retrofitlogintest.vo.MemberVO;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
private EditText editTextID ,editTextPW; // ์์ด๋, ๋น๋ฐ๋ฒํธ ์
๋ ฅ์ฐฝ
private Button btnLogin; // ๋ก๊ทธ์ธ ๋ฒํผ
private Retrofit retrofit; // ์น์๋ฒ์ ํต์ ํ Retrofit
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("Retrofit Login");
setRetrofitInit(); // Retrofit ์ด๊ธฐํ
editTextID = findViewById(R.id.editText_id);
editTextPW = findViewById(R.id.editText_pw);
btnLogin = findViewById(R.id.btn_login);
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
login(); // ๋ฒํผ ํด๋ฆญ์, ๋ก๊ทธ์ธ์ ์งํํฉ๋๋ค.
}
});
}
private void setRetrofitInit(){
retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.0.105:8081")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
private void login(){
String id = editTextID.getText().toString();
String pw = editTextPW.getText().toString();
ILoginService service = retrofit.create(ILoginService.class);
Call<MemberVO> call = service.getMember(id, pw);
call.enqueue(new Callback<MemberVO>() {
@Override
public void onResponse(Call<MemberVO> call, Response<MemberVO> response) {
MemberVO memberVO = response.body(); // ์น์๋ฒ๋ก๋ถํฐ ์๋ต๋ฐ์ ๋ฐ์ดํฐ๊ฐ ๋ค์ด์๋ค.
if(memberVO != null){ // ํ์์
๋๋ค.
Intent intent = new Intent(getApplicationContext(), ResultActivity.class);
intent.putExtra("memberVO", memberVO);
startActivity(intent);
}else{ // ํ์์ด ์๋๋๋ค.
Toast.makeText(getApplicationContext(), "ํ์์ด ์๋๋๋ค!", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<MemberVO> call, Throwable t) {
Toast.makeText(getApplicationContext(), "๋ก๊ทธ์ธ์ ์คํจํ์์ต๋๋ค!", Toast.LENGTH_SHORT).show();
}
});
}
}
[ResultActivity] Source
package com.example.retrofitlogintest;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import com.example.retrofitlogintest.vo.MemberVO;
public class ResultActivity extends AppCompatActivity {
private TextView textView_result; // ๊ฒฐ๊ณผ
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
setTitle("Result");
textView_result = findViewById(R.id.textView_result);
Intent intent = getIntent(); // ๋ก๊ทธ์ธ ์, ๋๊ฒจ๋ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฐ๋๋ค.
MemberVO memberVO = intent.getParcelableExtra("memberVO");
textView_result.setText(memberVO.getMem_name() + "๋! ๋ฐ๊ฐ์ต๋๋ค!");
}
}
[์ ํ๋ฆฌ์ผ์ด์ ์คํ ๊ฒฐ๊ณผ]
์น ์๋ฒ ๊ตฌ์ถ(egovFramework ๊ธฐ๋ฐ์ API ์น ์๋ฒ ๊ตฌ์ถ)
7. egovframework ๊ธฐ๋ฐ์ ์น์๋ฒ ๊ตฌ์ถ์ ๊ฒ์๊ธ ๋งํฌ๋ก ๋์ ํ๋ค.
[์น ์๋ฒ ๋งํฌ๊ฐ ๋ค์ด๊ฐ ์๋ฆฌ]์น ์๋ฒ ๋งํฌ๋ ๊ณง ๊ฒ์๊ธ ์์ฑ ํ ๋น ๋ฅธ ์์ผ๋ด๋ก ์ ๋ก๋ ํ๋๋ก ํ๊ฒ ์ต๋๋ค!
[Andriod] ์๋๋ก์ด๋ Retrofit, ์น์๋ฒ๋ฅผ ์ด์ฉํ ๋ก๊ทธ์ธ ๋ง๋ค๊ธฐ
@Junesker
๋๊ธ