본문 바로가기

노력을 이기는 재능은 없고
노력을 외면하는 결과도 없다.
- 이창호 9단

D E V E L O P M E N T/Android

[Andriod] 안드로이드 Retrofit, 웹서버를 이용한 로그인 만들기

  Junesker   2021. 6. 21.
반응형

회사에서 기존에 만들어진 어플에 로그인 기능이 없어서 새롭게 추가하게 되었다. 안드로이드 앱은 작게나마 만들어봐서 깊은 지식은 없지만, 이번에 또 한가지 배워가는것 같아 의미가 있었던 작업이다. 처음엔 Retrofit을 사용하지 않고 다른 방법을 사용했는데, 여러가지 정보를 찾아보니 속도나 통신방법 등 Retrofit이 성능적으로 더 좋다는 내용이 있었다.

 

 

 

 

Retrofit, 웹 서버를 이용한 로그인 만들기 순서
1. 프로젝트 생성
2. Activity화면들 생성(로그인, 결과페이지)
3. 라이브러리 및 환경설정
4. 페이지별 컨트롤러 및 서비스, VO 등 생성
5. 웹 서버 구축(egovFramework 기반의 API 웹 서버 구축)
6. 테스트

 

 

 

 

 

로그인 어플리케이션 프로젝트 생성

 

 

 

 

 

1.  안드로이드 스튜디오를 통해 로그인 프로젝트를 만든다.

 

New Project 만들기

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 파일 생성

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

반응형

댓글