카테고리 보관물: 프로그래밍

Android ROOM 사용한 Master/Detail 관계 정의

개요

Android ROOM 은 Android Jetpack 에 포함된 컴포넌트 입니다. SQLite DB에 쉽게 접속하고 이용할 수 있게 해 주는 일종의 ORM(Object-relational mapping) 라이브러리 입니다. 이전에는 SQLite DB에 접속하려면 정형화된 별도의 클래스를 사용했습니다. 조금 지루한 작업이라고 할 수 있었습니다. 이것을 줄여주고 쉽게 SQLite DB 연동작업을 할 수 있도록 도와줍니다.

기초적인 연동방법은 좋은 글이 많으므로 그것을 참고하시면 됩니다. 이 글에서는 부모가 되는 테이블과 자식이 되는 테이블을 어떻게 정의하는지 살펴보도록 하겠습니다. 언어는 코틀린(Kotlin)을 기준으로 합니다.

Master/Detail 관계 정의

Master/Detail 관계는 기본적으로 1:N(일대다) 으로 이해하시면 됩니다. 하나의 부모에 자식이 여럿있는 개념입니다. 1:N(일대다) 관련 자료를 찾아보시면 더 자세한 내용을 보실 수 있습니다.

Android ROOM 에서는 클래스 파일에 테이블을 정의합니다. 코드는 다음과 같습니다.

@Entity(tableName = "test_parent")
class TestParent(@PrimaryKey @ColumnInfo(name = "parent_seq") var parentSeq: Int,
          @ColumnInfo(name = "parent_name") var parentName: String?,
.
.
.
)

@Entity(
    tableName = "test_detail",
    indices = [Index("parent_seq")],
    foreignKeys = [ForeignKey(entity = TestParent::class, parentColumns = ["parent_seq"], childColumns = ["parent_seq"], onDelete = ForeignKey.NO_ACTION)]
)

class TestDetail(@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "test_detail_seq") var testDetailSeq: Int,
                @ColumnInfo(name = "parent_seq") var parentSeq: Int,
.
.
.
)

12행이 핵심입니다. 부모 컬럼과 자식 컬럼이 지정된 것을 볼 수 있습니다. onDelete는 부모 테이블의 자료가 삭제되었을때의 동작입니다. 예제에서는 아무런 동작도 하지 않도록 했습니다. 각자의 상황에 맞는 값을 지정하면 됩니다. 사용할 수 있는 값과 의미는 다음의 주소에서 확인할 수 있습니다.

https://developer.android.com/reference/android/arch/persistence/room/ForeignKey.html#CASCADE

결과만 보면 간단한데 Master/Detail 관계를 정의한 예제를 거의 찾아볼 수 없었습니다. 코틀린(Kotlin)으로 된 예제는 없었습니다. 위 코드를 참조하셔서 필요한 부분에 적용하시면 됩니다.

필요한 필드만 업데이트

android ROOM을 이용해서 테이블을 갱신(update)해야 하는 경우가 있습니다. 기본적인 예제를 적용해보면 모든 필드가 갱신되는 것을 알 수 있습니다. 필요한 필드만 갱신하려면 Query 형태로 정의해야 합니다. Data Object Access(DAO) 클래스에 다음과 같이 정의합니다.


    @Query("update test_parent set parent_name = :parentName, photo = :parentPhoto, memo = :parentMemo where parent_seq = :parentSeq")
    fun updateParent(parentSeq:Int, parentName:String?, parentPhoto:String?, parentMemo:String?)

변수로 값을 전달해서 Query 내에 :변수명 형태로 대입해서 필요한 필드만 갱신 되도록 작업하시면 됩니다.

이상 Android ROOM 라이브러리를 사용한 Master/Detail 관계 정의에 대해서 알아보았습니다.

Visual Studio Git Branch 이용

개요

요즘 개발시에는 소스버전 관리는 필수입니다. 여러 버전관리 소프트웨어가 존재하지만 필자는 Git을 주로 사용합니다. 로컬에서 작업 후 저장소에 업데이트 하는 방식으로 사용됩니다. 작은 규모는 무료 호스팅도 이용이 가능합니다.

단순히 소스를 저장하고 변경된 내용을 보기위한 용도로도 이용할 수 있습니다. 프로젝트 성격에 따라 여러가지 방법으로 사용될 수 있습니다. 본인이 속한 회사나 팀의 상황에 맞게 사용하면 됩니다. 이 글에서는 단순히 소스를 백업하는 용도가 아닌 Branch를 이용해서 작업을 분리한 후 병합(merge)하는 과정을 알아보려고 합니다.

독자분들이 Git 자체과 Branch 개념을 알고 있다고 가정하고 진행합니다.

Visual Studio 와 Git 연동

Git 명령어를 입력하면서 사용해도 됩니다. 하지만 도움을 주는 프로그램을 설치하면 훨씬 효율이 좋습니다. 필자는 Git Extensions 와 Easy Git Integration Tools를 설치하고 Visual Studio와 연동했습니다. 검색해 보시면 좋은 글이 많으니 쉽게 연동하실 수 있습니다. 기본적인 연동 작업은 완료 되었다고 가정하겠습니다.

Branch 이용

프로젝트를 진행/관리하다 보면 실제로 작동되고 있는 소스를 유지하면서 작업해야 하는 경우가 많습니다. 작업 후 문제가 없으면 실제 서버에 올려서 반영하게 됩니다. 그런데 작업 중 발견하지 못한 다른 문제가 있어서 업데이트를 해야할 때 난감합니다. 원래소스로 복원한 후 문제가 된 부분을 고쳐야 하는데  수정된 부분이 많으면 까다롭습니다. 작업중인 소스를 백업하고 원래 소스로 복원 후 버그를 고치고 서버에 반영합니다. 그 다음 새롭게 작업된 소스를 다시 작업한 상태로 만들어야 합니다. 이런 과정을 수동으로 하다보면 시간이 많이 소요되고 실수할 확률도 높아지게 됩니다. 이럴 때 Branch 기능을 사용하면 편리하게 작업 할 수 있습니다. 간단한 예를 들어 알아보도록 하겠습니다.

ASP.NET 웹 응용 프로그램 프로젝트를 생성합니다. 다른 프로젝트로 원리는 같으니 원하시는 것으로 생성해도 됩니다.

index.aspx WebForm 을 추가하고 Business 클래스를 추가 합니다.

파일 추가 후 솔루션 탐색기 정보

파일 추가 후 솔루션 탐색기 정보

다음과 같이 샘플 코드를 입력 했습니다.

Business.cs
public class Business
{
public string GetCEOName()
{
var ceoName = "Toughman";
return ceoName;
}
}
index.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
var business = new Business();
var ceoName = business.GetCEOName();

Response.Write("CEO name : " + ceoName);
}

이 상태에서 로컬 저장소를 만들고 작업된 내용을 커밋합니다.

저장소 생성

저장소 생성

최초커밋

최초커밋

Git Extensions 를 클릭하여 확인하면 master 브랜치에 최초커밋이라고 나타납니다. 기준이 되는 줄기라고 생각하면 됩니다. 이 상태가 서버에 반영되어있고 추가 개발이 진행된다고 가정하겠습니다. 작업을 진행할 브랜치를 Commands > Create branch 메뉴를 선택합니다.

메뉴를 선택하면 다음과 같은 대화상자가 나타나는데 적절한 이름을 입력합니다. 필자는 dev로 입력했습니다.

Create branch 대화상자

Create branch 대화상자

브랜치를 생성하면 큰 줄기(master)와 가지(dev)가 내용이 같아 다음처럼 표시 됩니다.

dev 브랜치 생성

dev 브랜치 생성

dev 브랜치로 다음의 메뉴를 선택해서 전환합니다.

dev 브랜치로 전환

dev 브랜치로 전환

개발 진행에 따라 소스가 수정되었다고 가정해 보겠습니다. Business 클래스에 다음의 메소드를 추가합니다.

public string GetCTOName()
{
var ctoName = "CTO Name";
return ctoName;
}

이 상태에서 GetCEOName 메소드의 내용을 수정해서 서버에 반영해야 하는 상황이 되었습니다. 원래 master 브랜치의 Business.cs 파일을 가져와서 작업해야 합니다. 일단 작업 중인 사항을 커밋합니다. 위의 방법대로 다시 master 브랜치로 전환합니다. 그러면 Visual Studio 에서는 파일 변경되었다는 메시지가 나타나면서 다시 읽어들일 것인지 물어봅니다. 다시 읽어들이면 원래의 파일 내용으로 변경됩니다. GetCEOName 메소드의 내용을 수정합니다. 커밋하면 다음과 같은 상태가 됩니다.

master 브랜치 수정 후 상태

master 브랜치 수정 후 상태

상황이 종료되었으니 dev 브랜치로 전환하여 개발을 진행합니다. 개발이 완료되었고 문제가 없다는 것을 확인했으면 master 브랜치에 작업을 반영합니다. 병합(merge)을 다음과 같이 진행하면 됩니다.

master 브랜치로 전환 후 Commands > Merge branches 메뉴를 선택합니다. 병합할 브랜치(dev)를 선택합니다. 왼쪽 이미지 부분에 마우스 커서를 올려보면 fast forward 로 선택했을 때 어떻게 처리되는 지 알 수 있습니다. 이 글에서는 Always create a new merge commit 을 선택해서 병합한 내용이 커밋되도록 했습니다.

master 브랜치에 dev 브랜치 병합

master 브랜치에 dev 브랜치 병합

병합이 완료되면 다음과 같은 트리 모양이 됩니다.

병합 후 트리 모양

병합 후 트리 모양

단순한 예를 들어 설명했지만 소스 코드 수정 작업량의 차이만 있을 뿐 적용하는 방식은 동일합니다. branch 기능을 이용해서 효율적인 작업에 도움이 되었으면 합니다.