Spring Boot에서 프로젝트를 생성하여 Firestore에 있는 데이터 작업을 하려고 합니다.  


Firestore spring boot crud


Firebase에는 다음과 같이 collection을 만들어서 데이터를 입력 하였습니다.


Firestore spring boot crud


이 데이터베이스에 데이터를 조회, 추가, 수정, 삭제하는 기능을 Spring Boot를 이용하여 만들어 보려고 합니다.

 

Spring Boot에서 Spring Starter Project를 선택하여 신규 프로젝트를 생성 합니다.


Firestore spring boot crud


입력 사항은 테스트이니까 대충 적어 넣고 Next 버튼을 클릭 합니다.


Firestore spring boot crud


 

DependencySpring Web만 추가 했습니다.  Finish 버튼을 클릭 합니다.

 

pom.xmlfirebase를 추가 합니다현재 6.13.x 버전까지 나와있는데 한 단계 낮추어서 적어봤습니다.

 

               <dependency>

                   <groupId>com.google.firebase</groupId>

                   <artifactId>firebase-admin</artifactId>

                   <version>6.12.1</version>

                </dependency>

 

Firebase의 필드에 해당하는 Vo를 생성 합니다.

 

package com.copycoding.firebase;

 

public class Member {

        String id;

        String name;

        int age;

        String tel;

       

        public String getId() {

               return id;

        }

        public void setId(String id) {

               this.id = id;

        }

        public String getName() {

               return name;

        }

        public void setName(String name) {

               this.name = name;

        }

        public int getAge() {

               return age;

        }

        public void setAge(int age) {

               this.age = age;

        }

        public String getTel() {

               return tel;

        }

        public void setTel(String tel) {

               this.tel = tel;

        }

}

 

 

Service를 생성하기 위해 먼저 Interface 파일을 생성하고

 

package com.copycoding.firebase;

 

public interface FirebaseService {

 

        public insertMember(Member member) throws Exception;

       

        public Member getMemberDetail(String id) throws Exception;

       

        public String updateMember(Member member) throws Exception;

       

        public string deleteMember(String id) throws Exception;

}

 

 

 

Service Implement도 작성 합니다.

 

package com.copycoding.firebase;

 

import org.springframework.stereotype.Service;

 

import com.google.api.core.ApiFuture;

import com.google.cloud.firestore.DocumentReference;

import com.google.cloud.firestore.DocumentSnapshot;

import com.google.cloud.firestore.Firestore;

import com.google.cloud.firestore.WriteResult;

import com.google.firebase.cloud.FirestoreClient;

 

@Service

public class FirebaseServiceImpl implements FirebaseService {

 

        public static final String COLLECTION_NAME="member";

       

        @Override

        public String insertMember(Member member) throws Exception {

               Firestore firestore = FirestoreClient.getFirestore();

               ApiFuture<WriteResult> apiFuture = firestore.collection(COLLECTION_NAME).document(member.getId()).set(member);

               return apiFuture.get().getUpdateTime().toString();

        }

 

        @Override

        public Member getMemberDetail(String id) throws Exception {

               Firestore firestore = FirestoreClient.getFirestore();

               DocumentReference documentReference = firestore.collection(COLLECTION_NAME).document(id);

               ApiFuture<DocumentSnapshot> apiFuture = documentReference.get();

               DocumentSnapshot documentSnapshot = apiFuture.get();

               Member member = null;

               if(documentSnapshot.exists()) {

                       member = documentSnapshot.toObject(Member.class);

                       return member;

               } else {

                       return null;

               }

        }

 

        @Override

        public String updateMember(Member member) throws Exception {

               Firestore firestore = FirestoreClient.getFirestore();

               ApiFuture<WriteResult> apiFuture = firestore.collection(COLLECTION_NAME).document(member.getId()).set(member);

               return apiFuture.get().getUpdateTime().toString();

        }

 

        @Override

        public String deleteMember(String id) throws Exception {

               Firestore firestore = FirestoreClient.getFirestore();

               ApiFuture<WriteResult> apiFuture = firestore.collection(COLLECTION_NAME).document(id).delete();

              

               return "Document id :" + id + " delete";

        }

}

 

 

 

이제 마지막으로 Controller Rest Api 형식으로 작성 합니다.

 

package com.copycoding.firebase;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestParam;

import org.springframework.web.bind.annotation.RestController;

 

@RestController

public class FirebaseController {

 

        @Autowired

        FirebaseService firebaseService;

       

        @GetMapping("/insertMember")

        public String insertMember(@RequestParam Member member) throws Exception {

               return firebaseService.insertMember(member);

        }

       

        @GetMapping("/getMemberDetail")

        public Member getMemberDetail(@RequestParam String id) throws Exception {

               return firebaseService.getMemberDetail(id);

        }

       

        @GetMapping("/updateMember")

        public String updateMember(@RequestParam Member member) throws Exception {

               return firebaseService.updateMember(member);

        }

       

        @GetMapping("/deleteMember")

        public String deleteMember(@RequestParam String id) throws Exception {

               return firebaseService.deleteMember(id);

        }

}

 

여기 까지는 일반 프로젝트와 동일한 방식으로 작성을 하면 됩니다.

 

package com.copycoding.firebase;

 

import java.io.FileInputStream;

import javax.annotation.PostConstruct;

import org.springframework.stereotype.Service;

import com.google.auth.oauth2.GoogleCredentials;

import com.google.firebase.FirebaseApp;

import com.google.firebase.FirebaseOptions;

 

@Service

public class FirebaseInitialize {

 

        @PostConstruct

    public void initialize() {

        try {

        FileInputStream serviceAccount =

                  new FileInputStream("./copycodingServiceAccount.json");

 

                FirebaseOptions options = new FirebaseOptions.Builder()

                  .setCredentials(GoogleCredentials.fromStream(serviceAccount))

                  .setDatabaseUrl("https://copycoding-bca04.firebaseio.com")

                  .build();

 

                FirebaseApp.initializeApp(options);

            } catch (Exception e) {

                e.printStackTrace();

            }

       

        }

}

 

추가로 Firebase에 접속하기 위한 설정 파일을 하나 생성해주면 됩니다.

이렇게 해서 프로그램이 완성 되었습니다.


이제 테스트를 해 봅니다.

귀찮으니 조회만 해 봅니다.


Firestore spring boot crud


조회가 잘 되는 군요.

성의가 없는 것 같아 삭제도 해 봅니다.


Firestore spring boot crud


삭제가 되었다고 하는데 Firebase 데이터베이스에 들어가 확인해 봅니다.


Firestore spring boot crud


document 2번이 삭제 되어 있습니다이런 식으로 작업을 하면 됩니다.


- copy coding -


오라클을 설치하지 않은 경우 간단하게 database를 테스트 할 수 있도록 oracle에서 제공하는 사이트가 있습니다어떻게 보면 별로 소용이 없을 수도 있지만 table 생성이나 쿼리 조회가 자유롭지 못한 환경에서는 자유롭게 테스트 하는데 유용할 수도 있습니다.

 

일단 사이트에 접속을 합니다.

https://livesql.oracle.com/


oracle sql test online


상단 우측 Sing In을 클릭하고 로그인을 진행 합니다오라클에 계정이 없다면 신규로 생성합니다.  


oracle sql test online


계정 생성이 귀찮을 수 있지만 오라클에서 제공하는 프로그램을 다운로드 받는 경우 필요하기 때문에 하나 만들어 두는 것도 좋습니다.


oracle sql test online


livesql 사이트에 처음 접속하는 경우에는 면책조항 확인을 합니다.


좌측 메뉴에서 SQL Worksheet를 선택하면 일반적인 퀴리 테스트가 가능 합니다.


oracle sql test online


select to_char(sysdate, 'YYYY-MM-DD') from dual;을 입력하고 상단 우측 Run 버튼을 클릭해서 테스트를 진행 합니다.

 

물론 신규 테이블 생성도 가능 합니다.


oracle sql test online

CREATE TABLE customers

( customer_id number(10) NOT NULL,

  customer_name varchar2(50) NOT NULL,

  city varchar2(50),

  CONSTRAINT customers_pk PRIMARY KEY (customer_id)

); 


생성한 테이블에 데이터 입력도 가능 합니다.


oracle sql test online

insert into customers(customer_id, customer_name, city) values(100, 'test1', 'city1');

insert into customers(customer_id, customer_name, city) values(200, 'test2', 'city2');

insert into customers(customer_id, customer_name, city) values(300, 'test3', 'city3');

insert into customers(customer_id, customer_name, city) values(400, 'test4', 'city4');

insert into customers(customer_id, customer_name, city) values(500, 'test5', 'city5'); 


쿼리의 일부만 실행 하려면 마우스로 드래그 해서 영역을 설정하고 Run 버튼을 클릭 합니다.

 

이제 입력한 데이터를 조회하면 됩니다.


oracle sql test online

select * from customers;

 

Table을 생성하고 데이터를 입력하는 작업이 귀찮으면 기존에 오라클에서 제공하는 테이블을 선택해서 쿼리 테스트를 진행해도 됩니다.


oracle sql test online


상단 Find를 선택하고 팝업창에서 Schema를 확장하면 내가 생성한 My Schema와 오라클에서 제공하는 친숙한 HRSCOTT도 보이는 군요.

 

oracle sql test online


My Session 메뉴에는 지금까지 작업한 log 정보를 확인할 수 있습니다.


oracle sql test online


본인이 생성한 Table 정보는 Schema에서 확인하고 작업할 수 있습니다.

 

, Schema 정보는 Oracle 사이트에 Session이 연결된 동안만 존재 합니다.  Session을 저장 하려면 SQL Worksheet 상단에 있는 Save 버튼을 이용해서 저장을 해놓으세요.


- copy coding -


TensorBoard를 어떻게 작동시키는지 알아보려고 합니다.

아나콘다를 설치하고 tensorflow도 설치 했으니 이건 식은죽 먹기 입니다.

 

1. TensorBoard 실행


먼저 Anaconda Prompt를 실행 합니다.



Tensorflow를 설치한 가상환경으로 이동 합니다.

>activate tensorflow

 

tensorboard 실행 명령어를 입력 합니다.



명령어를 살펴 보겠습니다.

(tensorflow) C:\Users\will>tensorboard --logdir=./path/logs/

 

log의 위치가

C:\Users\will\path\logs\

여기이고 이곳의 파일을 사용하라는 뜻입니다.


각자 알아서 path를 생성해 줍니다.

엔터키를 눌러 명령을 실행 합니다.



tensorboard가 실행이 되었다는군요.

종료는 키보드 Ctrl + C 를 누르면 되고 기본 Port6006 이라네요.

 


2. TensorBoard 브라우저

 

텐서보드는 콘솔로 띄우고 화면을 보는것은 웹브라우저에서 봐야 합니다.

브라우저를 하나 열고 http://localhost:6006을 입력 합니다.



아직 아무 작업도 하지 않아서 그냥 텍스트 안내만 나오고 있습니다.

 


3. TensorBoard port 변경 하기


만약 기존에 다른 프로그램에서 port 6006을 사용하고 있다면

텐서보드 기동시 변경을 해주면 됩니다.

(tensorflow) C:\Users\will>tensorboard --logdir=./path/logs/ --port=9999




변경된 port로 잘 실행 됩니다.

 


4. Tensorboard 메뉴


어떤 메뉴들이 있는지 확인해 볼까요?



다양한 메뉴들이 존재 합니다.

조만간 하나씩 사용해 봐야 겠네요.

 

 

5. Tensorboard 테스트

 

간단한 프로그램으로 텐서보드를 사용해 보겠습니다.

먼저 프로그램 작성 전에 아무 곳이나 log 저장할 위치를 설정해야 합니다.


저는 F:\tensordata\log로 결정 했습니다.

jupyter notebook에 프로그램을 작성합니다.



그냥 더하기 입니다.

그래프 저장은 절대값으로 입력해 보았습니다.

tensorflow가 덧셈을 잘 하는군요.

그래프가 로그 디렉토리에 생성이 되었는지 한번 가봅니다.



생성이 되어있네요.

그럼 이미지로 보도록 하겠습니다.

 

텐서보드를 띄우고



브라우저를 열어서 확인해 봅니다.

 

http://localhost:9999

url이 자동으로 변경이 되었습니다.

http://localhost:9999/#graphs&run=.


tensorboard


단순한 이미지지만 처음 만들었으니 용서가 됩니다.

 

tensorflow 코딩만 할 수 있으면 tensorboard도 잘 사용할 수 있겠습니다.


- copy coding -


1. 프로젝트 생성

 

1.1 프로젝트 만들기

 

전에 google map을 사용할 수 있는 API key를 생성했는데요.


[안드로이드] google map 사용을 위한 API 생성(2018.11)


이제 키가 잘 작동 하는지 테스트를 해보겠습니다.

안드로이드 프로젝트를 하나 생성 합니다.


MapTest 이라는 이름으로 생성을 하겠습니다.


프로젝트 명을 입력하는 화면 하단에 Package name이 있습니다.

com.example.컴퓨터이름.프로젝트명 이런식으로 나타나는데 [Edit] 버튼을 누르면 편집이 가능 합니다.



필요하면 편집을 하고 [Done] 버튼을 누르면 반영이 됩니다.



com.android.google.maptest 이렇게 변경을 해 보았습니다.



Android 4.0으로 선택을 했는데 각자 알아서 선택을 하면 됩니다.



Empty Activity를 선택 합니다.



모두 기본으로 놓았는데 변경이 필요하면 수정 합니다.

이제 [Finish] 버튼을 눌러 프로젝트를 생성 합니다.

 

수정한 Package name으로 생성이 되었는지 확인해 볼까요?



잘 되어 있군요.

 

1.2 패키지 이름 등록

 

새로 만든 프로젝트에서 구글 맵을 사용 하려면 패키지 이름을 API 키에 등록해야 합니다.

google에 로그인을 하고 https://console.developers.google.com 에 접속 합니다.



사용자 인증 정보 만들기에서 API1을 선택 합니다. 등록할 때 이름을 변경 했다면 다른 이름이겠죠.

 

라디오 버튼 중 Android 앱을 선택합니다.

[+ 패키지 이름 및 지문 추가]를 선택하면 패키지 이름과 SHA-1 인증서 지문이 하나 추가 됩니다.



신규 생성한 내용을 추가 합니다.

빨간색 박스가 이번에 만든 패키지인증서 지문 입니다.

[저장] 버튼을 선택 하면 패키지 이름으로 생성된 프로젝트 에서 지도를 사용할 수 있습니다.

 


2. 프로젝트 개발

 

2.1 API 키 등록

 

구글 맵을 사용하기 위한 키를 등록 해야 권한을 이용 하여 앱에 지도가 표시 됩니다.


AndroidMainifest.xml


<meta-data
   
android:name="com.google.android.geo.API_KEY"
   
android:value="생성된 API 키 입력" />


2.2 Layout 작성

 

activity_main.xml


지도를 표시할 fragment 를 추가합니다.

그런데 빨간색으로 오류가 나오는 군요.

map 관련 class가 없어서 발생 하니 추가해야 합니다.



build.gradle

implementation 'com.google.android.gms:play-services:10.0.1'


를 추가 합니다.

그러면 상단에 Sync를 맞추라고 합니다. [Sync Now]를 클릭 합니다.



다시 activity_main.xml에 가봅니다.



빨간색이 없어졌습니다.



2.3 지도 사용

 

이제 지도를 그려 보겠습니다.

MainActivity.java implements OnMapReadyCallback를 이용해 보겠습니다.

 

onCreate()함수에 Fragment를 추가 하고


FragmentManager fragmentManager = getFragmentManager();
MapFragment mapFragment = (MapFragment)fragmentManager
        .findFragmentById(R.id.
map);
mapFragment.getMapAsync(this);


onMapReady() 함수에 지도를 그려줍니다OnMapReadyCallback이걸 추가하면 map 기능이 추가되어서 onMapReady() 함수에서 작업하면 됩니다.  이 함수에서 정거장 위치, 약속장소등을 어떻게 표시하는지 기회가 되면 설명 드리겠습니다.


@Override
public void onMapReady(final GoogleMap map) {

    LatLng SEOUL =
new LatLng(37.56, 126.97);

   
MarkerOptions markerOptions = new MarkerOptions();
   
markerOptions.position(SEOUL);
   
markerOptions.title("서울");
   
markerOptions.snippet("한국 수도");

   
map.addMarker(markerOptions);
   
map.moveCamera(CameraUpdateFactory.newLatLng(SEOUL));
   
map.animateCamera(CameraUpdateFactory.zoomTo(14));
}


실행을 해볼까요?

아직 오류가 발생합니다.

 

Error: Program type already present: android.support.v4.app.BackStackRecord$Op

 

android.support.v4 오류이군요.

gradle에 아래 내용을 추가 합니다.


implementation 'com.android.support:support-v4:27.1.0'


오류가 없어졌습니다.


왔다 갔다. 이것 저것 추가하고 혼란 스러운가요?


하단에 추가한 전체 소스가 그리 길지 않습니다.


전체 소스를 보면서 읽으면 별거 없습니다.



2.4  결과


android google map

 

이제 잘 나오는 군요.

지도의 좌표를 임의로 설정해서 나온 결과 입니다.

다음 번에는 핸드폰의 위치를 지도에 표시 해보도록 하겠습니다.

 

 

3. Source Code

 

3.1 AndroidManifest.xml


개인이 발급 받은 API 키 값을 넣으세요.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.google.maptest">

    <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/AppTheme">

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="AIzxxxxx API 키 값xxxxxxxxxx_L8" />


        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


3.2 activity_main.xml

<?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">

    <fragment
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.MapFragment" />

</android.support.constraint.ConstraintLayout>

3.3 build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.android.google.maptest"
        minSdkVersion 14
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'com.google.android.gms:play-services:10.0.1'
    implementation 'com.android.support:support-v4:27.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}


3.4 MainActivity.java

package com.android.google.maptest;

import android.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FragmentManager fragmentManager = getFragmentManager();
        MapFragment mapFragment = (MapFragment)fragmentManager
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);

    }

    @Override
    public void onMapReady(final GoogleMap map) {

        LatLng SEOUL = new LatLng(37.56, 126.97);

        MarkerOptions markerOptions = new MarkerOptions();
        markerOptions.position(SEOUL);
        markerOptions.title("서울");
        markerOptions.snippet("한국 수도");

        map.addMarker(markerOptions);
        map.moveCamera(CameraUpdateFactory.newLatLng(SEOUL));
        map.animateCamera(CameraUpdateFactory.zoomTo(14));
    }

}

- copy coding -


12

+ Recent posts