국비교육(22-23)

76일차(1)/Android App(33) : SQLite 활용(1)

서리/Seori 2023. 1. 26. 18:27

76일차(1)/Android App(33) : SQLite(1)

 

 

** App에서 문자열을 영구 저장하는 방법

  (영구 저장이란 앱을 종료하고 다시 시작해도 불러올 수 있는 문자열)

 1. 파일 입출력을 이용해서 저장
 2. android 내장 DataBase를 이용해서 저장

  - SQLite DataBase (안드로이드에 기본으로 내장된 프로그램)
 3. SharedPreference를 이용해서 저장 (느리지만 간단히 저장하고 불러올 수 있다)
  - 내부적으로 xml 문서를 만들어서 문자열을 저장하고 불러온다.
  - 저장된 문자열을 boolean, int, double, String type 으로 변환해서 불러올 수 있다.

 

 

- 3번 SharedPreference는 느리지만 간단히 저장해서 불러오기가 가능하다.

- xml 문서를 따로 저장해서 만들기 때문에, 파일을 불러오는 것만큼 느리다.

- xml파일을 FileReader를 사용해서 읽어오는 것이다.

 

- 그러면 어떤정보가 빠르고 정확하게 관리되어야 한다면?

 → 2번 SQLite DataBase 를 활용한다.

- 속도가 중요한 데이터를 관리해야 하는 경우, 빈번하게 수정이 일어나는 정보인 경우

ex)가계부

 


 

- 내장 데이터베이스 활용하기.

- SQL문을 사용한다.

 

- step14sqlite 모듈 생성

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical">

    <ListView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:id="@+id/listView"/>
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="할일 입력..."
        android:id="@+id/inputText"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="추가"
            android:id="@+id/addBtn"/>
    </LinearLayout>

</LinearLayout>

 

- 리니어 레이아웃으로 바꾸고 ListView, EditText 조합

- 할일을 입력하면 ListView 목록으로 출력되고, 그것이 실제로 DB에 저장되도록 해볼 예정!

 

 

- DB를 활용해서 입력/수정/삭제/목록보기 작업을 할 수 있다.

- 오라클을 설치해서 되는 것처럼! 안드로이드에는 미니 DB가 내장되어 있다.

- 자기만의 DB 파일을 만들어서 내장 어플리케이션을 사용해서 DB를 관리할 수 있다.

 


MainActivity.kt

package com.example.step14sqlite

import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import android.widget.*
import android.widget.AdapterView.OnItemLongClickListener
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() , View.OnClickListener {

    //필요한 필드 정의하기

    //lateinit 예약어를 사용하면 null을 넣을필 요없이 값을 나중에 넣을 수 있다.
    //null을 대입했다가 나중에 값을 바꾸려면 번거롭다.
    lateinit var inputText:EditText
    lateinit var listView: ListView
    lateinit var adapter: TodoAdapter
    lateinit var helper: DBHelper

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //필요한 UI의 참조값 얻어와서 필드에 저장하기
        inputText=findViewById(R.id.inputText)
        listView=findViewById(R.id.listView)
        //버튼 리스너 등록하기
        findViewById<Button>(R.id.addBtn).setOnClickListener(this)
        //DBhelper 객체의 참조값을 필드에 저장하기
        //version값이 증가되면 onUpgrade() 메소드가 자동 호출되면서 db가 초기화된다.
        helper = DBHelper(this, "MyDB.sqlite", null, 2)
        //할일 목록 얻어오기
        var list:List<Todo> = TodoDao(helper).getList()
        //listView 동작 준비하고, 할일 목록 출력하기
        adapter=TodoAdapter(this, R.layout.listview_cell, list)
        //listView에 아답타 연결하기
        listView.adapter=adapter        
    }

    override fun onClick(v: View?) {
        //1. 입력한 문자열을 읽어와서
        val msg=inputText.text.toString()
        //2. Todo 객체에 담아서
        val data=Todo(0, msg, "")
        //3. TodoDao객체를 이용해서 DB에 저장한다.
        TodoDao(helper).insert(data)
        //4. 목록을 새로 얻어와서
        val list=TodoDao(helper).getList()
        //5. 아답타에 넣어주고
        adapter.list=list
        //6. 모델의 내용이 바뀌었다고 아답타에 알려서 ListView가 업데이트되도록 한다.
        adapter.notifyDataSetChanged()
        //7. Toast 띄우기
        Toast.makeText(this, "저장했습니다.", Toast.LENGTH_SHORT).show()
        inputText.setText("")        

    }    
}

 

- inputText 필드를 정의(null이 들어갈수 있게)

- inputText의 참조값을 찾아와서 넣어줌

 

lateinit var inputText:EditText

- 번거로우면 이렇게! lateinit 예약어 사용

- 값을 나중에 넣는다는 것을 가정하고 그대로 두는 것. null을 넣거나 ? 표기를 하지 않아도 된다.

- 초기화를 나중에 할 것이다. 필드에 뒤늦은 초기화를 할때 사용한다.

 

inputText=findViewById(R.id.inputText)
listView=findViewById(R.id.listView)

- 이렇게 만들어둔 필드에 직접 값을 넣어준다.

- 뷰 바인딩을 쓸 때는 이렇게 쓸 필요 없다.

 

- 버튼리스너 등록!  View.OnClickListener 를 구현하고 메소드 오버라이드 

- 버튼 객체에 리스너 등록하기

 


 

- 입력받은 할일 하나하나를 객체로 관리한다.

 

- Todo 라는 data class 생성. java의 TodoDto 와 같은 것이라고 보면 된다.

 

Todo.kt

package com.example.step14sqlite

// data class는 java에서 TodoDto라고 생각하면 된다.
data class Todo(var num:Int, var content:String, var regdate:String)

 

- 이렇게 작성하면 setter, getter 가 자동으로 만들어진다.

 


 

Todoadapter 생성(listView에 연결할 것)

 -> 이전에 만든 CountryAdapter (java 코드로 작성) 와 비교하며 보기 

package com.example.step14sqlite

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView

/*
    Context type, Int type, list<Todo> type 을 인자로 전달받는 대표 생성자
    인자로 전달받은 내용을 자동으로 필드에 저장한다.
    BaseAdapter 추상 클래스를 상속받아서 만든다.
 */
class TodoAdapter(var context: Context, var layoutRes: Int, var list:List<Todo>) : BaseAdapter(){


    //전체 sell의 갯수 리턴
    override fun getCount(): Int {
        return list.size
    }
    //인자로 전달된 position에 해당하는 아이템 리턴하기
    override fun getItem(position: Int): Any {
        return  list.get(position)
    }
    //인자로 전달된 position 에 해당하는 아이템의 아이디 리턴하기
    override fun getItemId(position: Int): Long {
        return list.get(position).num.toLong()  // Int type을 Long type으로 casting해서 리턴
    }
    //인자로 전달된 cell view를 리턴하는 메소드
    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        //kotlin에서 메소드의 매개변수는 상수(val)이기 때문에 값 변경이 불가하다.
        var resultView:View = if(convertView == null) LayoutInflater.from(context).inflate(layoutRes, parent, false)
                              else convertView


        //position에 해당하는 할일 정보를 얻어와서
        val data=list.get(position)

        //TextView에 출력하고
        val text_content=resultView.findViewById<TextView>(R.id.text_content)
        val text_regdate=resultView.findViewById<TextView>(R.id.text_regdate)

        text_content.text=data.content
        text_regdate.text=data.regdate

        //해당 View를 리턴해준다.
        return resultView
    }

}

 

- BaseAdapter를 상속하고, 메소드 4개 override

 

- 대표 생성자만 선언해주면 된다.

- 그러면 인자로 전달받은 내용이 자동으로 필드에 저장된다.

- this.xxx 라는 코드를 넣을 필요가 없다.

 

- 저 대표생성자 1줄로 CountryAdapter의 이 코드를 대체할 수 있다.

- 코틀린의 코드 단축, 효율성

 

- java였다면 들어가야 하는 코드! 이런 코드가 필요없다.

 

- Any (=object) 타입을 받으므로 position값으로 가져온 아이템을 리턴

 

 

- toLong() 으로 Long 타입으로 리턴

- java의 Long 타입과 같다.

 

- java에서는 좁은 범위의 타입을 넓은 범위의 타입에 담는것이 가능했다.

 

- 하지만 코틀린에서는 다르다! 위와 같이 int타입을 Long타입에 담으면 오류가 발생한다.

- 이런 경우 var num2:Long = num1.toLong() 형태로 넣어주어야 한다.

 

- CountryAdapter 에도 view를 리턴해주는 메소드가 있는데,

  TodoAdapter에서도 position에 해당되는 뷰를 리턴

 

- java에서는 view를 받아서 view가 null이면 전개할 것을 받아서 리턴

 메소드의 인자로 전달된 view 값을 조건부로 수정하기도 한다.(inflater로)

 

 

- 하지만 코틀린에서는? position에 다른값을 집어넣으려고 하면 오류가 발생한다! 다른 값을 넣을 수 없다.

- 지금 여기 들어가 있는 값은 상수화되어 있다(val). 따라서 인자로 전달된 값을 그대로 써야한다.

 

 

- 그래서 view타입 변수(resultView)를 만들어서 convertView를 넣어주는 방식으로 작성했다.

- inflater를 사용해서 레이아웃 전개하기

 

var resultView:View = if(convertView == null) LayoutInflater.from(context).inflate(layoutRes, parent, false)
                       else convertView

 

- 위 코드를 이런 코드로 수정해볼 수 있다.

- null 이면 초록색 박스의 리턴값을 대입하고,

  null이 아니면 분홍색 화살표 convertView를 대입한다!

- 해당 값이 담긴 resultView가 최종적으로 리턴된다.

 

- java에서는 사용할 수 없는 방식. 문법이 유연하다.

- 코틀린에서도 if~else 를 활용해서 3항연산자와 비슷하게 사용할 수 있다.

 

- position이 값을 찾아오는 primary key 역할을 한다.

 


- cell 레이아웃 만들어주기

new- layout resource file

 

listview_cell.xml 생성

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/text_content"
        android:textSize="20sp"
        android:text="내용입니다..."
        android:layout_margin="10dp"/>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/text_regdate"
        android:textColor="#999999"
        android:gravity="right"
        android:text="등록일입니다..."
        android:layout_margin="10dp"/>
</LinearLayout>

 

- 여기에서 부여한 id를 사용해 xml 문서를 전개해서 화면을 구성

 

- id를 사용해 참조값을 얻어와서 textView에 출력하기

 

- Custom Adapter에서 java 코드로 했던 작업이다.

- 코틀린으로 작성해본 것!

 

- 데이터에 list를 연결해줄 준비중 !

 


 

- 새 클래스 생성

DBHelper

package com.example.step14sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;
/*
    DB 생성 및 리셋을 도와주는 도우미 클래스 만들기
    - SQLiteOpenHelper 추상클래스를 상속받아서만든다.
 */
public class DBHelper extends SQLiteOpenHelper {
    public DBHelper(@Nullable Context context, @Nullable String name,
                    @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }
    //App에서 DB를 처음 사용할때 호출되는 메소드
    @Override
    public void onCreate(SQLiteDatabase db) {
        //사용할 테이블을 만들면 된다.
        //1. 실행할 sql문을 준비하고
        String sql="CREATE TABLE todo "+
                "(num INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT, regdate TEXT)";
        //2. SQLiteDataBase 객체를 이용해서 실행한다.
        db.execSQL(sql);

    }
    //DB를 리셋(업그레이드)할때 호출되는 메소드
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //업그레이드할 내용을 작성하면 된다.
        db.execSQL("DROP TABLE IF EXISTS todo"); //만일 테이블이 존재하면 삭제한다.
        //다시 만들어질 수 있도록 onCreate() 메소드를 호출한다.
        onCreate(db);
    }
}

 

- DBHelper 클래스를 만드는 이유는? DB를 초기화하기 위해서

- 초기화하고 필요에 따라서 업그레이드를 하기위해서 이 클래스가 필요하다.

 

- SQLiteOpenHelper 클래스 상속

- SQLite : 데이터를 영구저장하고 관리할 수 있다. 안드로이드 기기 속 미니 DB라고 생각하면 된다!

 

- 메소드 2개(onCreate, onUpgrade) override하고 생성자도 가져와주기

 

- onCreate() : DB를 처음 호출할때 사용된다. sql문을 사용할 수 있다.

 

- execSQL() : onCreate 안에서 사용하는 sql문을 사용할 수 있는 메소드

 

- Primary Key 오라클과 동일하게 사용

- 데이터타입이 오라클과 다르다. INTEGER, TEXT => num, varchar2 라고 보면 된다.

- SQLite에는 날짜 타입이 없다. 대신 날짜 타입처럼 사용할 수 있는 문자열을 만들어서 사용한다.

 

- 오라클에서는 시퀀스를 만들어야 했지만,

  SQLite에서는 AutoIncrement 하면 자동 증가되는 값이 알아서들어간다.

- 내부적으로 시퀀스를 만들어서 알아서 값을 넣어준다.

 

- DBHelper 클래스의 도움을받아서 DB 데이터 연결

 

 

- onUpgrade() : DB를 업그레이드한다. 업그레이드가 되면 onCreate가 다시 시작된다.

- table을 drop해버리고 다시 만들도록 코딩했다.

 

- onCreate() 는 일반적으로 최초에 한번만 호출된다.

- 호출할때 버전의 숫자가 바뀌지 않는 이상!


 

TodoDao

package com.example.step14sqlite

import android.database.Cursor

/*
    TodoDao 클래스의 대표생성자(primary constructor) 의 인자로 DBHelper 객체를 전달받아서
    필드에 넣어두고 메소드에서 활용하는 구조이다.

    insert, update, delete 작업을 할때는
        val db:SQLiteDataBase = helper.getWritableDataBase()
        val db:SQLiteDataBase = helper.writableDataBase()
    select 작업을 할때는
       val db:SQLiteDataBase = helper.readableDataBase()

    java의 JDBC에서 PreparedStatement 객체와 비슷한 기능을 하는 객체가 SQLiterDataBase 객체이다.
 */
class TodoDao(var helper:DBHelper) {
    
    //할일 정보를 저장하는 메소드
    fun insert(data:Todo){
        //java => SQLiteDataBase db=helper.getWritableDataBase()
        val db=helper.writableDatabase
        // ? 에 바인딩할 인자를 Any 배열로 얻어내기
        //java => Object[] args = { data.getContent() }
        var args= arrayOf<Any>(data.content)
        //실행할 sql문
        // SQLiteDB => datetime('now', 'localtime'), oracle => SYSDATE
        val sql = "INSERT INTO todo (content, regdate)" +
                " VALUES(?, datetime('now', 'localtime'))"
        //sql문 실행하기
        db.execSQL(sql, args)
        db.close() //close() 를 호출해야 실제로 반영된다.

    }
    //할일 목록을 리턴하는 함수
    fun getList():List<Todo>{
        //수정가능한 todo type을 담을 수 있는 리스트
        val list= mutableListOf<Todo>()
        val db=helper.readableDatabase
        //실행할 select 문 구성 (binding 할것은 없음)
        val sql="SELECT num, content, regdate FROM todo ORDER BY num ASC"
        //query 문을 수행하고 결과를 Cursor 객체로부터 얻어내기 (selection 인자는 없다.)
        val result:Cursor = db.rawQuery(sql, null)

        //Cursor 객체의 메소드를 이용해서 담긴 내용을 반복문 돌면서 호출한다.
        while (result.moveToNext()){
            //0번째는 num, 1번째는 content, 2번째는 regdate이다.
            val data=Todo(result.getInt(0), result.getString(1), result.getString(2))
            //할일 정보가 담긴 Todo 객체를 List에 추가한다.
            list.add(data)
        }
        //할일 목록을 리턴해주기
        return list
    }
}

 

class TodoDao(var helper:DBHelper) { }

 

- 대표 생성자의 인자로 DBHelper를 전달받게 한다.

- todo를 전달받아서 DB에 저장한다.

 

- getter 메소드를 이렇게 필드를 참조하는 모양으로 사용한다.

- DBHelper 객체를 통해서 SQL 데이터베이스 객체를 얻어낸다!

- JDBC에서 사용하던 PreparedStatement와 비슷한 역할을 한다.(순수 jsp에서 사용)

 

 

- 이 DB 객체를 사용해서 sql문을 수행한다.

- execute SQL 메소드를 사용해서 실행할 sql 문자열과 저장할 Any 타입을 가지고 오는 것이다.

 

 

arrayOf<Any>()

- 바인딩할 내용을 배열Array에 담아서 전달해준다.(Any 타입을 담을 수 있는 array)

 

- Todo 할일(content) 의 내용이 이곳에 바인딩되어 들어간다.

 

- 만약 들어갈 ? 의 내용이 여러개라면 이 배열에 여러가지 정보를 담아서 각각의 ?에 바인딩해주면 된다

- 배열 args를 인자로 전달하기만 하면 순서대로 자동으로 바인딩해준다.

 

- java의 object 배열이 코틀린에서는 Array<Any> 라고 생각하면 된다.

 

- SQLite에는 날짜유형은 없지만 datetime() 이라는 함수를 통해서 현재 날짜를 집어넣어주면 된다.

- now, localtime을 인자로 넣어주면 된다.(세계시간 기준이 아니라 지역시간 기준이라는 의미로)

- 그러면 oracle의 sysdate와 같은 기능으로 사용할 수 있다.

 

- 할일 목록을 리턴해주려면 반복문을 돌면서 list에 할일 목록을 담아야 하기 때문에 mutableList<>, .add() 를 사용했다.

- 수정 가능한 todo타입을 담을 수 있는 리스트!

 

 

- rawQuery는 Cursor타입을 리턴한다.

- Cursor 타입은 jsp에서 사용하던 resultSet 역할이라고 보면 된다. select의 결과를 담아준다.

 

- Result는 Cursor 객체 타입이다. 타입 추론이 가능해서 생략한 것!

 

- 쿼리문을 수행해서 Cursor객체를 리턴해서 .moveToNext() 메소드로 커서가 위치한 곳의 결과를 얻어내는 것.

 

- 돌면서 출력해준다. 데이터를 빼낼때는 타입에 맞춰 getXX 메소드를 사용하면 된다.

- 칼럼명으로 출력하는 기능은 없다. 칼럼의 번호로 가지고 와야 한다.

- 일반적으로 getInt, getString 을 가장 많이 사용한다.

- getBlob() : 2진데이터를 불러낼때사용

 

 

- result의 0번째, 1번쨰, 2번째가 이것에 해당한다.

- 가져올 타입에 맞는 getter 메소드를 사용해주면 된다.

 


 

- 추가 버튼 클릭시 해야할 동작

 

- todo에는 지금 content만 담겨있다.

- Todo() 를 사용해서 담고 싶은데 현재 Todo에는 이런 디폴트 생성자가 없다.

 

- null은 넣을 수 없으므로, "" 이런식으로 넣어줄 수도 있다.

- content만 전달하고 나머지 num과 regdate에는 0과 빈 문자열을 전달하면 된다!

 

- onClick 메소드에서도 접근할 수 있게 하기위해 DBHelper를 나중에 값을 담을 필드로 만들어준다.

 

- 4개의 인자를 넣어서 DBHelper를 호출한다.

 

- 만약 DB내용을 갈아엎고 싶다면 마지막 인자 version에 2를 넣어주면 된다.

- DB내용이 초기화되면서 내용을 바꾸게 할 수 있다.

 

- 이 MainActivity는 자주 활성화된다. onCreate()가 호출될 일이 많다.

- 하지만 생성할때마다 DB를 새로 세팅하지는 않는다.(version 번호에 따라 새로 생성할지 여부가 달라진다)

 

- 입력한 할일이 이렇게 listView의 목록에 담긴다.

 

- 이 목록은 앱을 종료시켰다가 다시 실행해도 살아있다.

- 이 데이터는 일부러 지우지 않는 이상 영구 저장이다

 

- Device file explorer에서 보면 앱이 사용하는 고유한 sandbox가 있다. 이것은 앱의 패키지명으로 만들어진다.

- 여기가 앱의 내부(internal) 저장공간이다. 

 

- 이 내부 저장공간 안에 databases 폴더가 만들어져 있다.

  databases 폴더 안에 DBHelper에서 문자열로 전달했던 이름("MyDB.sqlite")으로 파일이 만들어져있다.

 

- 원한다면 이것을빼서 SQLite로 열 수 있는 프로그램으로 열어서 확인해 볼 수도 있다.

- 그러면 저 안에 저장된 테이블, 저장된 데이터 등등을 볼 수 있다.

 

- DB파일 자체는 앱에 저장되고, 

저 파일을 사용할 수 있는 기능은 안드로이드 기기에서 내장되어 가지고 있다.

 

- MainActiviy에서 인자로 전달하는 version의 숫자를 바꾸면?

- version up 하면 내용이 갈아 엎어진다. table의 내용이 깨끗하게 사라져 있다.

 

 

- 버전이 달라지면 onUpgrade() 가 호출되면서 테이블이 드랍된다.

- Drop table 하고 onCreate에서 테이블을 다시 만든 것이다.

 


 

 

- 지금 배우고 있는 것은 안드로이드 Native 앱 개발이다.

- 안드로이드의 고유한 ui를 사용 (버튼, textview, ...)

 

- 이 바탕으로 IOS Native App 개발은 할 수 없다.

- IOS만의 앱개발 UI가 따로 있기때문에. IOS 앱개발을 위해서는 swift를 배워야 한다.

 

- native를 바탕으로 만드는 것이 깔끔하고 빠르지만, 대부분의 앱들이 그렇게 빠른 속도를 요구하지는 않는다.

 (게임 등 특수한 경우가 아니라면)

- 웹브라우저의 기능을 앱으로 보여주는 정도라면 그렇게 엄청나게 빠르지는 않아도 된다.

- 고성능 앱을 요구하는 경우가 별로 없으므로..

→ 그러면 그런 앱을 꼭 안드로이드/IOS로 구분해야 할까? 하나를 만들어서 같이 사용할 방법은?

 

- 이렇게 안드로이드, IOS 겸용으로 앱개발을 하려면? 하이브리드 앱을 개발하면 된다.

- 네이티브 앱에 비해 성능은 조금 떨어지지만 비용절감 때문에...

 

 

- html, css, javascript 를 활용해서 만드는 것이 Hybrid app이다.

- 원래 웹브라우저가 해석해주는 것인데? 앱으로도 활용할 수 있다.

 

 

- html, css, javascript 가 해석할 수 있는 웹뷰를 만들어서 앱 위에 펼친다.

- 이런 형태로 앱을 개발하는 것이 hybrid app이다.

 

- 화면만 똑같이 나온다고 될까? 앱의 하드웨어를 사용해야 할 수도 있는데?

(연락처나 카메라 사용, 위치정보 접근, 갤러리 접근 및 이미지 사용, 흔들림/기울기 등 기기의 센서값, ...)

→ hybrid앱을 만들려면 하드웨어에 접근할 수 있는 코딩을 미리 해놓아야 한다.

  하드웨어에 접근하기 위한 코딩은 각각의 native 언어로 프로그래밍할 수밖에 없다.

 

- 하이브리드 앱을 개발할 수 있는 프레임워크가 있다.

 여기서 이런 코딩을 미리 해놓았다.(코틀린,swift로)

- 미리 만들어놓은 기능을 javascript로 call해서 사용할 수 있도록 만든다.

 

- 이런 프레임워크중 제일 많이 쓰이는것은 1) React Native, 2) Flutter 이다.

- 안드로이드 하드웨어, IOS 하드웨어를 사용할 코딩이 필요하면 이 프로그램 안에 미리 되어있는 코딩을 가져다 쓸 수 있다.

 

 

 

- Android 앱개발에 관심이있다면 java/kotlin 을 잘 배워두고 하이브리드 쪽으로 넘어가면 좋다.

 

- flutter는 언어가 다르다. dart 라는 언어를 사용한다.

 

- 이런 프로그램들을 익혀두면 안드로이드, ios앱을 비교적 쉽게 만들 수 있다.