티스토리 뷰


0. 들어가기 앞서
이번에 소개할 프로젝트는 대학교 3학년 여름 방학동안 4명의 동기들과 함께 진행했던 등산 보조 안드로이드 어플 제작 프로젝트다. 아이디어 구상부터 서비스 구현, 시연 발표까지 전 과정을 열심히 준비한 팀 프로젝트로 작년 교내 소프트웨어 경진 대회에서 입상까지 한 작품이다. 안드로이드 어플을 제작한 경험은 이전에 한 번 있었는데 훨씬 높은 수준의 어플을 동기들과 협력해 구현하면서 많은 것을 배울 수 있었다.

*데모 영상: https://www.youtube.com/watch?v=nayPppPBjAQ


1. 프로젝트 소개
코로나의 여파로 인해 실내 운동보다 야외 운동을 선호하는 경향이 높아졌다. 실제로 통계 자료에 따르면 19년도 평균 등산객 수보다 21년도 평균 등산객 수가 더 증가했다. 평균 등산객 수의 증가로 21년도 산악 사고도 증가했는데 여기서 우리 팀은 등산 코스에 대한 올바른 가이드, 등산 정보를 교환할 수 있는 등산 커뮤니티의 필요성을 느꼈고, 이를 하나에 담은 산포유 안드로이드 어플을 제작하게 되었다. 산포유는 말 그대로 산 for you, '당신을 위한 산'이다.

San For You 메인 화면



2. 서비스 구현 방법
우리 서비스는 크게 다섯 가지 부분으로 나눌 수 있다. 첫 번째, 회원 가입&로그인, 두 번째 등산 리뷰, 세 번째 등산 지도, 네 번째는 산 정보, 마지막은 마이 페이지다.

내가 담당한 부분은 '마이 페이지'와 '산바구니'다. 마이 페이지는 로그인한 회원의 정보를 DB에서 불러와 띄워주는 부분이고 산바구니는 산 정보 페이지에서 마음에 드는 산을 담아두고 다음에 한 번에 볼 수 있도록 하는 기능이다.(귀여운 이름을 지어준 동기들 고마워^.^)

서버는 Amazon AWS를 사용했고, Android Studio를 사용해서 JAVA로 서비스를 구현했다. DB에는 MySQL, 협업툴은 Github를 사용했다.


(1) 마이 페이지
우선 우리 앱은 하나의 Main Activity 리모컨 위에서 크게 네 가지 화면(지도, 정보, 리뷰, 마이 페이지)으로 구성되어야 하기 때문에 이를 어떻게 구현해야할지 고민이 많았다. 우리는 이를 안드로이드 3.0부터 추가된 '프래그먼트(Fragment)'를 사용해서 해결했다. 프래그먼트는 하나의 액티비티 내에서 화면 UI의 일부를 나타낸다. 각 화면을 구성할 때 각각의 액티비티를 생성하는 것이 아닌, 하나의 액티비티 안에서 네 개의 프래그먼트로 UI를 구성함으로써 레이아웃을 분리해 관리할 수 있고, 레이아웃 복잡도도 줄일 수 있었다.

마이페이지 UI 구성: 각 버튼을 클릭하면 해당하는 화면으로 이동한다.

 

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment_mypage, container, false);
        rootView = (ViewGroup) inflater.inflate(R.layout.fragment_mypage, container, false);

        //마이 페이지에서 현재 로그인한 사용자의 닉네임 띄우기
        memberID= (TextView) rootView.findViewById(R.id.text1);
        mFirebaseAuth= FirebaseAuth.getInstance();
        FirebaseUser user = mFirebaseAuth.getCurrentUser();
        if (user != null) {
            // User is signed in
            memberID.setText(user.getEmail());
        } else {
            // No user is signed in
            System.out.println("user는 null");
        }

        //'산바구니' 버튼 클릭시 수행
        btn_cart= rootView.findViewById(R.id.bt1_cart);
        btn_cart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                activity.changeFragment(1);
            }
        });

        //'내가 쓴 리뷰' 버튼 클릭시 수행
        btn_review= rootView.findViewById(R.id.bt2_myReview);
        btn_review.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                activity.changeFragment(2);
            }
        });

        //'로그아웃' 버튼 클릭시 수행
        btn_logout= rootView.findViewById(R.id.bt3_logOut);
        btn_logout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getActivity(), "로그아웃 완료", Toast.LENGTH_SHORT).show();
                mFirebaseAuth.signOut();
                Intent intent = new Intent(getActivity(), SignInActivity.class);
                startActivity(intent);
            }
        });

        return rootView;
    }

 

SanForYou/app/src/main/java/com/sswu/sanforyou/mypage/MyPageFragment.java


위의 코드는 Mypage Fragment를 구현한 MyPageFragment.java의 일부이다. 처음에 현재 로그인한 사용자 정보를 불러와야 하는데 여기서 Firebase를 유용하게 사용했다. Android Studio와 연동하는 것에서 정말 많은 애를 먹었지만, 막상 해보니 Firebase가 여러 유용한 매서드를 지원해준 덕에 잘 사용했다. 특히 '현재 로그인한 회원' 정보를 바로 불러와주는 'FirebaseAuth.getInstance()'를 사용해서 마이페이지에 유저 데이터를 쉽게 띄워줄 수 있었다.
마이 페이지에서는 로그아웃, 사용자의 산바구니, 사용자가 작성한 리뷰를 볼 수 있는 각 화면으로 넘겨주는 버튼이 있는데, 이를 구현한 방법은 각 버튼 ID에 onClick 이벤트를 부여해서 changeFragment를 사용해 화면 전환을 구현했다.


(2) 산바구니
산 정보 Fragment에 각 산 정보 객체들의 오른쪽 위에는 '산바구니' 버튼이 있다. 사용자가 마음에 드는 산을 고르면 해당 버튼을 클릭해 자신의 산바구니에 저장할 수 있다. 이후 사용자는 마이페이지의 '산바구니' 프래그먼트에서 자신이 담아둔 산들을 확인할 수 있다.

산바구니 UI


MySQL DB에 산바구니 객체 삽입과 선택은 PHP 파일을 사용해 JSON 파싱을 해서 진행했다. 아래는 산바구니 버튼을 눌렀을 때, onClick 이벤트로 발생하는 산바구니 객체 삽입 JSON 파싱을 처리하는 PHP 파일이다. 산바구니 테이블에 사용자 ID, 산 이름을 인스턴스로 삽입하는 mySQL 구문이 실행된다.

<?php
	//mysql 연결 부분 생략  
	$memberID = $_POST["memberID"];
	$mountainName = $_POST["mountainName"];

	$sql="INSERT INTO cartTBL(memberID, mountainName) 
		VALUES('$memberID', '$mountainName')" ;

	$result=mysqli_query($conn,$sql);
   
	if($result){
		echo "산바구니에 담았습니다";
	}else{
		echo "산바구니에 이미 존재합니다";
	}		 
	mysqli_close($conn);
?>

Insert_cart.php


아래는 사용자가 자신의 산바구니를 확인해보려고 할 때, 이 요청을 처리하는 PHP 파일이다. SELECT문을 분석해보면, (1) 먼저 cartTBL에서 현재 로그인한 사용자를 속성 값으로 포함하고 있는 인스턴스를 불러오고(SELECT mountainName FROM cartTBL WHERE memberID = $memberID), (2) IN 연산자를 사용해서 1번 결과에 포함된 인스턴스들의 mountainName 값을 모두 불러온 뒤, (3) mountainTBL에서 2번의 산들의 정보를 불러와 row에 담아 보낸다.

<?php
	//mysql 연결 부분 생략
	$memberID = $_GET[memberID];
 
	$sql="SELECT mountainName, address FROM mountainTBL 
		WHERE mountainName IN (SELECT mountainName FROM cartTBL 
		WHERE memberID = $memberID)" ;
 
	$result=mysqli_query($conn,$sql);
	$data = array();   
	if($result){  
   		 while($row=mysqli_fetch_array($result)){
        		array_push($data, 
        	    	array('mountainName'=>$row[0],
            		'address'=>$row[1]));
		}
    	header('Content-Type: application/json; charset=utf8');
		$json = json_encode(array("cart"=>$data), JSON_PRETTY_PRINT+JSON_UNESCAPED_UNICODE);
		echo $json;
	}else{  
    		echo "SQL문 처리중 에러 발생 : "; 
    		echo mysqli_error($conn);
	} 
	mysqli_close($conn);
?>

cart.php

 


그럼 저는 또 다른 프로젝트를 들고 오겠습니다. 궁금한 점은 댓글 남겨주세요!
읽어주셔서 감사합니다 :)

*GitHub Link: https://github.com/SanForYou/SanForYou

 

GitHub - SanForYou/SanForYou: feat: 프로젝트 생성

feat: 프로젝트 생성. Contribute to SanForYou/SanForYou development by creating an account on GitHub.

github.com

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/09   »
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 30
글 보관함