[Android Studio] 안드로이드에서 로그인 기능 구현하기 [1]

     


2020년 버전 업데이트 장고 + 코틀린 + retrofit으로 로그인 구현하기

https://cholol.tistory.com/470




안녕하세요~ 

요즘에 진행하는 프로젝트에서 회원가입/로그인 기능을 넣으려고 하는데, 가장 많이 쓰이는 기능임에도 따로 정리한 포스팅이 없어서 이번에 작성하려고 합니다. 


만들고자 하는 기능은 다음과 같습니다.


- 안드로이드에서 ID(이메일주소), PASSWORD를 입력하여 회원가입

- 입력된 ID와 PASSWORD를 DB에 저장하고 이메일 인증메일 발송

- 인증메일에 포함된 특정 URL클릭시 회원가입 완료

- 안드로이드에서 ID와 PASSWORD를 통해 로그인


기본적인 로그인과 다른점이라면 '이메일 인증'이 추가된 겁니다. 아마 회원가입을 하다보면 이메일로 인증메일이 발송되고 이메일 안에 어떤 URL을 클릭해야 회원가입이 되는 것을 몇번 경험해 본적이 있을겁니다. 이는 주민등록번호와 같은 개인정보를 수집하지 않는 사이트에서 본인인증방법으로 많이 쓰는 방법이에요. 저같은 경우는 회사 EMAIL을 ID로 사용하기 때문에 진짜 회사 EMAIL을 가지고 있는지 검증하기 위해 이메일 인증 기능을 적용하려고 합니다.


포스팅은 기본적인 기능들(안드로이드의 기본적인 메소드 사용법 등)에 관한 자세한 설명은 생략하고 어느정도 알고 있다는 가정하에 기능 위주의 설명을 해드리며 진행하도록 하겠습니다. 일단 가장 먼저 안드로이드 화면에서 ID와 PASSWORD를 입력받는 기능을 만들어야 겠지요? 저는 일단 아래처럼 만들었습니다.



매우 심플하지요? ㅎㅎ

추가적인 요소들을 많이 써야 하지만 일단 기능 구현이 우선이기 때문에 ID와 PASSWORD를 입력하고 PASSWORD를 한번 더 입력하는 화면을 만들어 보았습니다. 마지막으로 회원가입버튼을 하나 추가했구요. 화면을 위와같이 구성했다면 우리는 3개의 에디트텍스트 객체를 통해 입력값을 받을 수 있습니다.


public class JoinActivity extends AppCompatActivity {

EditText et_id, et_pw, et_pw_chk;
String sId, sPw, sPw_chk;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_join);

et_id = (EditText) findViewById(R.id.et_Id);
et_pw = (EditText) findViewById(R.id.et_Password);
et_pw_chk = (EditText) findViewById(R.id.et_Password_chk);

sId = et_id.getText().toString();
sPw = et_pw.getText().toString();
sPw_chk = et_pw_chk.getText().toString();


위 코드를 보시면 3개의 에디트텍스트에서 각각 입력된 텍스트값을 가져와서 String 변수에 넣는 것을 확인 할 수 있습니다. 근데 onCreate() 선언했기 때문에 화면이 뜨자마자 입력된 값을 불러오게 되는데, 화면이 뜨는 순간은 아무것도 입력된게 없겠지요? 아까 만들었던 Join버튼을 눌렀을때 값들을 불러와야 하기 때문에 버튼을 눌렀을 때 동작하도록 바꾸겠습니다.


클릭 이벤트는 안드로이드 프로그래밍이 발전하면서 상당히 여러가지 방법으로 구현이 가능한데요, 제가 자주 사용하는 방법은 레이아웃에서 onClick을 이용한 방법입니다. 


<Button
android:text="Join"
android:layout_width="100dp"
android:layout_height="48dp"
android:id="@+id/bt_Join"
android:clickable="true"
android:onClick="bt_Join"
android:textAlignment="center"
app:layout_constraintLeft_toLeftOf="@+id/activity_join"
android:layout_marginStart="16dp"
app:layout_constraintTop_toBottomOf="@+id/et_Password_chk"
android:layout_marginTop="32dp"
app:layout_constraintRight_toRightOf="@+id/activity_join"
android:layout_marginEnd="16dp"
tools:ignore="HardcodedText" />

위와같이 레이아웃에 버튼객체에 android:onClick과 android:clickable 어트리뷰트를 추가합니다. clickable은 클릭을 가능하게 해주며, onClick의 경우 클릭했을 때 동작하는 메소드 이름을 정의합니다. 저는 bt_Join으로 이름지었어요. bt는 버튼을 줄인것입니다.(제맘대로.. ^^)


레이아웃 XML에서 위와같이 선언할 경우 해당하는 액티비티 소스에서 다음과 같이 메소드를 선언할 수 있습니다.


public class JoinActivity extends AppCompatActivity {

EditText et_id, et_pw, et_pw_chk;
String sId, sPw, sPw_chk;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_join);

et_id = (EditText) findViewById(R.id.et_Id);
et_pw = (EditText) findViewById(R.id.et_Password);
et_pw_chk = (EditText) findViewById(R.id.et_Password_chk);
}

/* onClick에서 정의한 이름과 똑같은 이름으로 생성 */
public void bt_Join(View view)
{
/* 버튼을 눌렀을 때 동작하는 소스 */
sId = et_id.getText().toString();
sPw = et_pw.getText().toString();
sPw_chk = et_pw_chk.getText().toString();
}

이제 Join버튼을 클릭할 때 에디트 텍스트에서 텍스트값을 불러오게 됩니다. 이 값들을 DB에 넣어야 하는데 넣기전에 비밀번호확인을 제대로 입력했는지 체크하는 것을 넣도록 하겠습니다.


/* onClick에서 정의한 이름과 똑같은 이름으로 생성 */
public void bt_Join(View view)
{
/* 버튼을 눌렀을 때 동작하는 소스 */
sId = et_id.getText().toString();
sPw = et_pw.getText().toString();
sPw_chk = et_pw_chk.getText().toString();

if(sPw.equals(sPw_chk))
{
/* 패스워드 확인이 정상적으로 됨 */

}
else
{
/* 패스워드 확인이 불일치 함 */

}
}

equals 메소드를 통해 입력된 PASSWORD와 CHK가 같은 값인지 확인하고 다를 경우 에러를 리턴하도록 만들고, 같으면 서버에 보내면 됩니다.


이제 서버로 값들을 전송하는 것을 만들 것인데.. 안드로이드에서 바로 DB로 넣지는 못하고 서버를 중계해서 DB로 넣도록 하겠습니다. 안드로이드 -> PHP -> MySql형태로 만들 것인데 이 부분에 내용은 해당 포스팅을 참고하시면 됩니다.


PHP를 이용해 MySql 연동하기


JSP를 이용해 MySql 연동하기


여기서는 PHP를 통해 서버와 연동시킬 계획입니다. 안드로이드에서는 4.0부터 서버와 통신할 때 쓰레드 사용을 권장하고 있습니다. 여기서는  AsynkTask를 통해 서버에 데이터를 전송해보도록 하겠습니다. 그러기 위해선 먼저 서버에서 데이터를 받는 프로그램을 만들어야 겠네요.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
snclib_join.php 
 <?
    header('content-type: text/html; charset=utf-8'); 
 
    // 데이터베이스 접속 문자열. (db위치, 유저 이름, 비밀번호)
    $connect=mysql_connect"db주소""로그인ID""로그인PW") or  
        die( "SQL server에 연결할 수 없습니다.");
    
    mysql_query("SET NAMES UTF8");
   // 데이터베이스 선택
   mysql_select_db("DB이름",$connect);
 
   // 세션 시작
   session_start();
 
 
 
   $id = $_REQUEST[u_id];
   $pw = $_REQUEST[u_pw]; 
   $sql = "INSERT INTO USERS(USERID, PASSWORD) VALUES('$id', '$pw')";
 
   $result = mysql_query($sql);
 
   if(!$result)
            die("mysql query error");
    else 
        echo("DB 입력 성공");
?>
cs


위는 GET방식을 사용하여 안드로이드로부터 입력받은 ID와 PW를 DB에 입력하는 PHP코드입니다. 이런 개인적인 프로젝트에서는 ID, PW를 GET방식으로 받아도 상관없는데, 서비스하는 프로그램일 경우 GET방식으로 ID나 PW를 받으면 상당히 위험합니다. URL에 전송되는 값들이 노출되기 때문이죠. 한번 POST형태로 바꿔볼까요?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
snclib_join.php 
<?
    header('content-type: text/html; charset=utf-8'); 
    // 데이터베이스 접속 문자열. (db위치, 유저 이름, 비밀번호)
    $connect=mysql_connect"db주소""로그인ID""로그인PW") or  
        die( "SQL server에 연결할 수 없습니다.");
    
    mysql_query("SET NAMES UTF8");
   // 데이터베이스 선택
   mysql_select_db("DB이름",$connect);
 
   // 세션 시작
   session_start();
 
   $id = $_POST[u_id];
   $pw = $_POST[u_pw]; 
 
   $sql = "INSERT INTO USERS(USERID, PASSWORD) VALUES('$id', '$pw')";
 
   $result = mysql_query($sql);
 
   if(!$result)
            die("mysql query error");
   else
        echo "insert success"
 
?>
cs


네~ 사실 데이터를 받는 쪽에서는 별로 수정할 것이 없습니다. ㅎㅎ 주는 쪽에서는 많이 수정해야 하지요. 이제 안드로이드에서 어떻게 서버에 데이터를 전송하는지 볼까요?



public class registDB extends AsyncTask<Void, Integer, Void> {

@Override
protected Void doInBackground(Void... unused) {

/* 인풋 파라메터값 생성 */
String param = "u_id=" + sId + "&u_pw=" + sPw + "";
try {
/* 서버연결 */
URL url = new URL(
"http://서버주소/snclib_join.php");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.connect();

/* 안드로이드 -> 서버 파라메터값 전달 */
OutputStream outs = conn.getOutputStream();
outs.write(param.getBytes("UTF-8"));
outs.flush();
outs.close();

/* 서버 -> 안드로이드 파라메터값 전달 */
InputStream is = null;
BufferedReader in = null;
String data = "";

is = conn.getInputStream();
in = new BufferedReader(new InputStreamReader(is), 8 * 1024);
String line = null;
StringBuffer buff = new StringBuffer();
while ( ( line = in.readLine() ) != null )
{
buff.append(line + "\n");
}
data = buff.toString().trim();
Log.e("RECV DATA",data);

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

return null;
}

}

앞서 말했듯이 서버에 접속할 때는 쓰레드가 필요합니다. 따라서 AsynkTask를 이용해서 서버에 접속하게되는데요, 자주 사용하는 메소드니 레퍼런스를 읽어보시는게 좋습니다. 여기서는 입력인자가 없는 AsynkTask를 만들었습니다. 서버주소는 현재 서버프로그램이 저장된 서버URL주소를 적으시면 되구요 snclib_join.php는 아까 만든 서버프로그램을 입력하시면 됩니다. 파라메터가 서버에 전달되는 것은 주석을 읽어보면 이해되실 겁니다. 사실 서버에서 클라이언트로 주는 값은 딱히 없지만 성공 실패 여부나 기타 로그를 찍기위해 만들었습니다. 


이제 Join버튼을 클릭했을때 이 메소드가 실행되게 해봅시다.


public void bt_Join(View view)
{
/* 버튼을 눌렀을 때 동작하는 소스 */
sId = et_id.getText().toString();
sPw = et_pw.getText().toString();
sPw_chk = et_pw_chk.getText().toString();

if(sPw.equals(sPw_chk))
{
/* 패스워드 확인이 정상적으로 됨 */
registDB rdb = new registDB();
rdb.execute();
}
else
{
/* 패스워드 확인이 불일치 함 */

}
}


위에서 만든 AsynkTask 클래스를 선언한뒤 execute()해주면 실행되게됩니다. 이제 안드로이드에서 ID와 PASSWORD를 입력하면 DB에 저장되게 됩니다. 테스트해볼까요?



테스트를 위해 testtest/testtest를 입력했을 때 모습입니다. DB에 정상적으로 입력된 것이 확인되는군요!.

이것으로 일단 ID와 PW를 입력받아 DB에 저장하는 기능을 구현했습니다!!


다음 포스팅에서는 로그인 구현 및 인증 이메일 전송을 구현하도록 하겠습니다.

반응형

댓글

Designed by JB FACTORY