C#에서 PostgreSQL 사용하기

C# 언어에서 PostgreSQL 데이터베이스를 사용하기 위한 내용을 정리해 봅니다.

먼저 Visual Studio를 실행하고 C# 프로젝트를 생성합니다. 그리고 Package Manager를 실행하는데, 아래와 같은 메뉴를 통해 접근이 가능합니다.

Package Manager는 콘솔창과 비슷한 방식으로 명령을 실행할 수 있는데, .NET을 위한 PostgreSQL 라이브러리를 설치하기 위해 아래의 명령을 입력합니다.

Install-Package Npgsql -Version 4.0.4

현재 시점에서는 4.0.4가 최신버전이지만 이를 확인하기 위해 아래의 URL로 접속하기 바랍니다.

https://www.nuget.org/packages/Npgsql/

라이브러리의 설치가 성공적으로 마무리 되면 아래처럼 코드를 입력하여 PostgreSQL에 대한 조회가 가능합니다.

using (var conn = new NpgsqlConnection("host=localhost;username=postgres;password=__________;database=postgres"))
{
    try
    {
        conn.Open();
        using (var cmd = new NpgsqlCommand())
        {
            cmd.Connection = conn;

            cmd.CommandText = 
                "SELECT table_name " +
                "FROM information_schema.tables " + "" +
                "WHERE table_schema = 'public' AND table_type = 'BASE TABLE'";


            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    listBox1.Items.Add(reader.GetString(0));
                    //or listBox1.Items.Add(reader["table_name"].ToString());
                }
            }
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

Using 절에 추가해야 할 것은 다음과 같습니다.

using Npgsql;

끝으로 Npgsql은 하나의 Connection에 대해서 하나의 Command만을 실행할 수 있습니다. 확인한 날짜는 2019년 10월 2일자이며, 이 시점에서 최신 버전으로 테스트해 보았습니다.

[C#] 중복된 Key를 허용하며, Key로 정렬 된 해쉬맵(Dictionary)

C#의 자료구조 중 Key-Value 컨테이너는 Dictionary입니다. 경우에 따라 Key로 정렬된 Dictionary는 SortedDictionary 클래스로써 C#에서 기본적으로 제공하고 있습니다. 그런데, Dictionary이므로 Key가 중복될 수 없습니다. 중복된 값을 정렬해서 저장하기 위해서는 Set 자료 구조를 이용해야 합니다. 그런데, Set는 Key만을 저장할 수 있고 Value는 저장할 수 없습니다. 중복된 Key를 허용하면서, Key로 정렬된 컨테이너는 기본적으로 C#에서 제공하지 않습니다. 하지만 두개의 클래스를 조합하면 가능한데, SortedSet과 Tuple입니다. 이 두개의 클래스를 통해 중복된 Key를 허용하면서, Key로 정렬된 컨테이너에 대한 클래스는 아래와 같습니다.

public class SortedTupleBag<TKey, TValue> : SortedSet<Tuple<TKey, TValue>>
where TKey : IComparable
{
    private class TupleComparer : Comparer<Tuple<TKey, TValue>>
    {
        public override int Compare(Tuple<TKey, TValue> x, Tuple<TKey, TValue> y)
        {
            if (x == null || y == null) return 0;

            return x.Item1.Equals(y.Item1) ? 1 : Comparer<TKey>.Default.Compare(x.Item1, y.Item1);
        }
    }

    public SortedTupleBag() : base(new TupleComparer()) { }

    public void Add(TKey key, TValue value)
    {
        Add(new Tuple<TKey, TValue>(key, value));
    }
}

이 클래스의 활용 예는 아래의 코드와 같습니다.

var tuples = new SortedTupleBag<double, double>();

tuples.Add(10.0, 100.1);
tuples.Add(40.0, 100.4);
tuples.Add(10.0, 1000.1);
tuples.Add(80.0, 20.8);
tuples.Add(70.0, 2100.7);
tuples.Add(50.0, 200.5);

Add 함수의 첫번째는 Key이고 두번째는 Value입니다. Key의 순서대로 정렬되어 있는지 확인하기 위해 아래의 코드를 통해 살펴볼 수 있습니다.

Console.WriteLine("Sorted List");
foreach (var tuple in tuples)
{
    Console.WriteLine("{0} {1}", tuple.Item1, tuple.Item2);
}

Console.WriteLine("");

Console.WriteLine("Min: {0}, Max: {1}", tuples.Min, tuples.Max);

위 코드의 실행 결과는 아래와 같습니다.

Sorted List
10 100.1
10 1000.1
40 100.4
50 200.5
70 2100.7
80 20.8

Min: (10, 100.1), Max: (80, 20.8)

Android v6.0(API Level 23) 이상의 Permission 관련 API

Android 6.0에서는 이전 버전과 다르게 개발자가 지정한 Permission에 대해서 사용자가 다시 한번 허용할 것인지를 묻는 과정을 요구한다. 즉, 6.0 이전에서는 개발자가 지정한 퍼미션에 대해 설치시에 사용자에게 알리고 설치가 되면 사용자는 설치된 앱을 사용하게 되지만, 6.0 이상에서는 설치 뿐만 아니라 실제 실행시에 사용자의 퍼미션에 대한 허용 여부를 UI를 통해 명시적으로 지정해줘야 한다.

예를들어 아래처럼 안드로이드의 버전에 상관없이 퍼미션은 AndroidManifest.xml에 지정된다.


안드로이드 6.0 이전은 이게 전부였다. 그러나 6.0 이후부터는 위의 개발자가 지정한 퍼미션 뿐만 아니라 사용자도 퍼미션의 허용 여부를 지정해야 한다. 이를 위해 개발자는 추가적인 코드가 필요하다. 먼저 특정한 퍼미션을 필요로 하는 API를 호출하기 전에 해당 퍼미션을 사용자가 허용했는지의 여부를 확인해야 하며, 아래 코드와 같다.

if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
}

위의 코드 예는 READ_EXTERNAL_STORAGE라는 외장 메모리의 파일을 읽기 위한 퍼미션을 사용자가 허용했는지를 확인하고, 아직 사용자가 허용하지 않았다면 퍼미션 허용 대화상자를 아래처럼 표시한다는 것이다.

퍼미션 허용 대화상자가 표시되고 사용자가 해당 퍼미션에 대한 허용 여부는 아래와 같은 콜백함수에 의해 확인이 가능하다.

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if(requestCode == 100 && grantResults.length > 0) {
        if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 사용자가 퍼미션을 허용했으므로, 해당 퍼미션이 필요한 API 호출이 가능한 시점
            // ..
        }
    }
}

Javascript의 배열(Array)의 정렬(Sort)

사람이 처리할 수 있는 데이터의 양에는 한계가 있고, 컴퓨터는 이러한 한계를 가진 인간을 보조해주고 인간이 쉽고 빠르게 정보를 파악해 주는 기능을 제공합니다. 검색 결과 등과 같은 정보를 정렬하지 않고 사용자에게 제공할 경우 사용자는 자신이 찾고자 하는 데이터를 찾아 헤매게 됩니다. 하지만 정렬된 데이터라면 빠르게 데이터를 찾을 수 있습니다.

검색 결과를 담기에 적당한 자료 구조는 배열입니다. 특히 Javascript에서는요. 이러한 배열을 정렬하는 코드를 정리해 둡니다.

var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
    return a - b;
});

위의 코드는 배열에 담긴 요소들을 정렬한 결과로 원래의 배열을 변경합니다.

아래는 배열에 담긴 데이터가 Key-Value를 가지는 Object 항목으로 구성된 경우에 대한 정렬 예입니다.

var items = [
    { name: 'Edward', value: 21 },
    { name: 'Sharpe', value: 37 },
    { name: 'And', value: 45 },
    { name: 'The', value: -12 },
    { name: 'Magnetic' },
    { name: 'Zeros', value: 37 }
];

items.sort(function(a, b) {
    var nameA = a.name;
    var nameB = b.name;

    if (nameA < nameB) {
        return -1;
    }

    if (nameA > nameB) {
        return 1;
    }

    return 0;
});

정렬 못지 않게 중요한 것이 필터링(Filtering)입니다. 검색 결과 중 내가 보고자 하는 데이터만을 보고, 아닌 것은 보여주지 않는 것이죠. 정렬과 필터링 기능은 기본적인 기능이지만, 제법 많은 프로그램에서 놓치고 있는 기능이기도 합니다.

웹에서의 레이아웃을 위한 구세주, Flex

웹의 CSS를 이용해 가로에 대한 가운데 정렬은 그럭저럭 쉽게 지정할 수 있지만, 세로 정렬은 왠지 트릭같은 방식으로 지정하는 느낌을 받는다. 그렇다보니, 세로 정렬이 필요한 레이아웃을 구성할때마다 고충이 생기는데.. 이럴때 flex라는 비교적 최신의 CSS 방식을 활용해 이러한 고충을 제거하고자 이 글을 정리한다. 사실 flex 방식은 그 내용이 제법 방대하다. 하지만 체계적인지라 여러번 살펴보면 충분이 이해하고 실제 업무에 활용할 수 있다.

일단 앞서 언급한 가로와 세로에 대한 가운데 정렬을 위한 flex 방식을 이 글을 통해 간단이 언급해 둔다. 가운데 정렬이 필요할때마다 flex를 사용하다보면.. flex의 그밖의 요소들이 하나씩 접근하게 될 것이기 때문이다. 기술이란 그 필요에 의해 사용되고, 자연스럽게 사용되어질때 사용자가 보다 쉽게 이해할 수 있기 때문이다.

아래의 dom 구성에 대한 코드가 있다.

DIP2K
김형준

.container 안에 .item 항목을 가로와 세로로 가운데 정렬하고자 한다면 아래와 같은 스타일을 지정하면 된다.


실제 결과는 아래와 화면처럼 가로와 세로에 대해 가운데로 정렬된 것을 볼 수 있다.

[xyz-ihs snippet=”flex-layout-center-align”]

DIV 요소는 display가 block이다. 그러나 flex의 내부의 항목으로 들어가게 되면 inline-block으로 변경된다는 점을 알 수 있다. 끝으로 이 글을 작성하기 위해 읽었던 문서는 “flexbox의 기본 개념”이다.