처음부터 그럴려고 한 것은 아니다...
그냥 아무 생각없이 한번 해본다는 것이 어쩌다가 여기까지 왔다.

워낙 게으른 탓에 쉽게 쉽게 하나 해볼려다가
제발등을 찍고 말았다.

블럭방을 운영하고 있었다.
엑셀로 짠 프로그램으로 그럭저럭 운영을 했다.
별 불편함을 못느꼈다.

그런데...
갑자기 한 어린친구가 엄마를 불러달랜다.
이런 전화번호가 없다.
그래서 열심히 회원리스트 장부를 뒤졌다..
없다....
그래서 가입신청서를 열심히 뒤져서 찾았다...

그런데 찾은 기쁨보다 "꼭 이렇게 어렵게 찾아야 하나...너무 힘들다"
이게 불행의 씨앗이다.

"그래 한번에 모든것을 해결할 방법을 찾자"

이렇게 시작된 것이 블럭방 관리 프로그램인 "블럭노리"다

처음 시작은 그랬다.

 


난 MFC개발자에서 출발해서 어렵다고 쉬운길로 가자고 웹개발자로 전환한 게으른 개발자였다.
그래서 처음엔 웹베이스로 한번 구상해보자 하고 시작했다.

난 MS를 욕하면서도 MS에 물들은 그런 개발자였나 보다.

먼저 복잡한것은 너무 싫었다.
쓰지도 않는 기능, 아주 가끔씩 쓰는 기능 그러나 없어도 별반 힘들지 않는 기능들은 만들지 말자 하면서 열심히 구상을 했다

가장 기본이 되는 기능만 만들자.
그럼 쉽게 만들겠지...
그런 생각으로 열심히 구상하고 프로그램 설계도 그리고 기능기획하고...

그러다 보니 궂이 이걸 웹으로 해야할까...
웹으로 하면 서버있어야 하는데..
DB도 돈주고 사던지 임대하던지 해야하는데...
호스팅 하면 매달 돈나가는데...

여기에 생각이 미치자 로컬로 만들어보자
그러면 웹으로 못하는데...

그래서 찾아봤다..

옛날 생각해서 VC++을 먼저 봤다
근데 난 6.0을 끝으로 손을 놨는데...없다....
이런 요즘은 대부분 Visual Studio 2005이상이다...
아니 Visual Studio 2008이나 Visual Studio 2010을 쓴다고 한다..

그래서 Visual Studio 2010을 설치했다...
너무 생소하고 이질적으로 느껴졌다...
이럴바에는 최신버전으로 한번 설치해보자
그래서 Visual Studio 2012를 설치했다...

DB는 무엇으로 할까...
로컬로 하자면....
MS ACCESS가 어떨까...
괜찮을것 같은데...
구글링을 했더니 2기가 이상이면 문제가 될 소지가 있단다...

쓸데없는 고민에 휩싸였다...
사실 DB로 2기가 안될것을 알면서 고민을 했다...
그래서 구글링을 했더니 SQLite를 쓰란다...
알았다...쓸께...

그런데 어떤 언어로 개발하지...
VC++은 너무 어려워....

그래서 VB.NET로 가서 해보기로 했다...
예전에 조금했으니깐...
근데 이것도 생소하다...
6.0이후로 너무 바뀌었다

그럼 옛날걸 설치하고 할까...
그래...
그래서 visual studio6.0을 구해 설치했다...
근데 또 마음이 바뀌었다...
델파이나 파워빌더가 낫지 않을까...
열심히 책을 찾아봤다
2005년 이후의 책이 없다...
이런...그럼 이제 델파이도 한물갔나...

그냥 Visual Studio 2012로 해보자
그럼 어떤 언어를 쓸까...
옆에서 C#으로 해보란다...
귀가 얇다...
그래서 C#으로 하기로 했다...

그래서 또 책을 찾았다...
다행히 회사에 책이 한권 굴러다닌다.
삼양미디어에서 나온 "C#.NET 프로그래밍"

한번 볼까...
이런 기초내용부터 너무 지루하다
언제 이 책한권을 다 읽지...
난감하다...

그래
그냥 만들어보자

그래서 구글링을 했다..
소스를 무지 구했다
약 200메가 정도 구했다

열심히 분석했다...

그리고 바로 Visual Studio 2012를 열고 개발을 시작했다...
무모했다...
바로 벽에 부딪히고 말았다...
그게 벌써 한달전이다...
우여곡절끝에 다 만들었다...

그리고 깨달은점...

책은 팔아먹을려고 쓸데없는 사설을 너무 많이 적어서 처음부터 질리게 한다.
둘째 무식하면 안된다...계획도 엉망이 되고
몸은 축난다..
셋째 게으르면 안된다...
쉽게 갈려다가 결구 200메가나 되는 소스를 전부 분석해버렸다...

다 만들고 났더니...
이런 이번엔 셋업을 해야 한단다...
그냥 Visual Studio 2012에서 제공하는 배포프로그램을 사용할까...

안된단다..저작권땜시

그래서 찾은게 NSIS...

이런!!! 스크립트가 너무 어렵다...
결국 개고생하면서 겨우 만들었다...

다음엔 만들지 말아야지...
그러면서 벌써
다음에 뭘 만들지 고민하기 시작했다...

난 안되나 보다...

top


블럭방 관리프로그램의 마지막 내용인 관리자 관리에 대한 내용과 엑셀 다운로드 기능에 대해서 살펴보기로 하자

또다른 기능인 SMS발송에 대한것은 업그레이드 중이라 작업이 완료된 이후에 다시 정리를 할 예정이다.

 

SMS를 뺀 나머지 기능들은 모두가 완성되어 1차 알파버전은 완성이 되었다.

이 프로그램은 현재 자유블럭방에서 사용되고 있으며 충분한 테스트가 진행중이다.

사소한 버그가 있긴 했지만 현재는 문제가 될만한 것은 거의 수정이 된 상태이다.

물론 실 운영을 하면서 테스트가 된 상태이기 때문에 현재 버전 그대로 사용한다고 해도 큰 무리는 없을듯하다.

 

- 관리자 등록(최고 관리자만이 관리자를 등록할 수 있다)

 

 

관리자 등록은 단순히 아이디와 비밀번호 이름, 연락처, 이메일, 메모 등으로 구성되어 있으며 필수항목은 아이디와 비밀번호, 이름, 연락처가 등록이 되면 된다.

수정과 차이점은 아이디 중복체크가 존재한다는 것이다

 

- 관리자 수정

 

 

관리자 등록과 모든 내용이 같지만 단 하나 아이디 수정이 안된다는 것이 다를 뿐이다

 

- 관리자 관리목록

 

 

관리자 목록은 최고권한 관리자에게만 제공이 되며 관리자로 등록된 모든 사람의 정보를 목록으로 보여준다.

리스트항목이라 별다른 특이 사항은 없다

 

그럼 마지막으로 엑셀 다운로드에 대해서 알아보자

 

- 엑셀 다운로드

 

 

기본적으로 엑셀은 설치프로그램 하단에 excel이란 디렉토리가 있다

거기에 목록에 보이는 모든 항목이 정리가 되어 엑셀파일로 저장이 된다.

각 저장 항목의 제목과 날짜로 파일명이 지정된다.

엑셀은 블럭방 관리프로그램에서 리스트가 있는 부분에서는 모두 저장이 가능하도록 구성되어 있다.

 

이것으로 블럭방 관리프로그램에 대한 기능 소개를 마무리를 할 예정이다.

 

이젠 블럭방 프로그램을 만들면서 고려했던 각각의 특이한 소스(특이하다기 보다 그냥 C#을 공부하는데 도움이 될 만한 내용을 추려서 한번 더 포스트를 진행하고 그 다음은 솔루션 소개 자료와 셋업 프로그램에 대한 설명을 진행할 예정이다.

 

끝까지 관심을 부탁 ~~~

top


이번포스트에서는 회원유효기간 관리와 블럭제품관리에 대한 내용을 기술할려고 한다.

목록들은 대부분 대동소이하다.

각각의 특징에 따른 필드의 차이는 있지만 대부분 프로그램밍적으로는 비슷하다

 

- 회원유효기간관리 목록

 

 

 

제품유효기간은 타이틀별로 Sort가 필요해서 페이징을 없앴다.

리스트의 타이틀을 클릭하면 항목에 따라 정렬이 된다.

스트링으로 정리를 하는 형식이라 숫자에 대한 정렬리 문제가 있었으나

인터넷을 통해 그 문제도 해결하였다.

이부분이 참 잘 안풀리던차에 구한 소스다

 

소스를 보자면

        // 숫자의 정확한 sort를 위한 StringLogicalComparer 코드

        public class StringLogicalComparer
        {

            public static int Compare(string s1, string s2)
            {

                //get rid of special cases

                if ((s1 == null) && (s2 == null)) return 0;

                else if (s1 == null) return -1;

                else if (s2 == null) return 1;

 


                if ((s1.Equals(string.Empty) && (s2.Equals(string.Empty)))) return 0;

                else if (s1.Equals(string.Empty)) return -1;

                else if (s2.Equals(string.Empty)) return -1;

 


                //WE style, special case

                bool sp1 = Char.IsLetterOrDigit(s1, 0);

                bool sp2 = Char.IsLetterOrDigit(s2, 0);

                if (sp1 && !sp2) return 1;

                if (!sp1 && sp2) return -1;

 


                int i1 = 0, i2 = 0; //current index

                int r = 0; // temp result

                while (true)
                {

                    bool c1 = Char.IsDigit(s1, i1);

                    bool c2 = Char.IsDigit(s2, i2);

                    if (!c1 && !c2)
                    {

                        bool letter1 = Char.IsLetter(s1, i1);

                        bool letter2 = Char.IsLetter(s2, i2);

                        if ((letter1 && letter2) || (!letter1 && !letter2))
                        {

                            if (letter1 && letter2)
                            {

                                r = Char.ToLower(s1[i1]).CompareTo(Char.ToLower(s2[i2]));

                            }

                            else
                            {

                                r = s1[i1].CompareTo(s2[i2]);

                            }

                            if (r != 0) return r;

                        }

                        else if (!letter1 && letter2) return -1;

                        else if (letter1 && !letter2) return 1;

                    }

                    else if (c1 && c2)
                    {

                        r = CompareNum(s1, ref i1, s2, ref i2);

                        if (r != 0) return r;

                    }

                    else if (c1)
                    {

                        return -1;

                    }

                    else if (c2)
                    {

                        return 1;

                    }

                    i1++;

                    i2++;

                    if ((i1 >= s1.Length) && (i2 >= s2.Length))
                    {

                        return 0;

                    }

                    else if (i1 >= s1.Length)
                    {

                        return -1;

                    }

                    else if (i2 >= s2.Length)
                    {

                        return -1;

                    }

                }

            }

 


            private static int CompareNum(string s1, ref int i1, string s2, ref int i2)
            {

                int nzStart1 = i1, nzStart2 = i2; // nz = non zero

                int end1 = i1, end2 = i2;

 


                ScanNumEnd(s1, i1, ref end1, ref nzStart1);

                ScanNumEnd(s2, i2, ref end2, ref nzStart2);

                int start1 = i1;

                i1 = end1 - 1;

                int start2 = i2;

                i2 = end2 - 1;

 


                int nzLength1 = end1 - nzStart1;

                int nzLength2 = end2 - nzStart2;

 


                if (nzLength1 < nzLength2) return -1;

                else if (nzLength1 > nzLength2) return 1;

 


                for (int j1 = nzStart1, j2 = nzStart2; j1 <= i1; j1++, j2++)
                {

                    int r = s1[j1].CompareTo(s2[j2]);

                    if (r != 0) return r;

                }

                // the nz parts are equal

                int length1 = end1 - start1;

                int length2 = end2 - start2;

                if (length1 == length2) return 0;

                if (length1 > length2) return -1;

                return 1;

            }

 


            //lookahead

            private static void ScanNumEnd(string s, int start, ref int end, ref int nzStart)
            {

                nzStart = start;

                end = start;

                bool countZeros = true;

                while (Char.IsDigit(s, end))
                {

                    if (countZeros && s[end].Equals('0'))
                    {

                        nzStart++;

                    }

                    else countZeros = false;

                    end++;

                    if (end >= s.Length) break;

                }

            }

 


        }

 

위의 소스를 이용하여 sort문제를 해결하였다

 

- 회원유효기간 수정

 

 

 

회원유효기간 변경은 간단하다.

사용방법은 단지 유효기간을 늘려주거나 줄여주는것이외의 기능은 없다

회원들이 시간충전을 하고 유효기간내에 다 사용을 못한 경우 임의로 유효기간을 연장시켜줄수 있는 기능을 만들어준것이다

 

- 블럭방 이용관리

 

 

블럭방이용관리는 시간충전을 한 고객이 혹시 클레임이라도 제기하면 그 사람의 히스토리를 일목정연하게 보여주기 위해서 만들어졌다.

회원검색을 하면 그 사람이 사용한 시간에 대한 정리를 해준다.

이것으로 사용시간 패턴을 구할 수 있다.

그래프로 그려볼까 하다가 특별히 쓰일일이 없을것 같아 포기했다.

 

- 블럭제품관리

 

 

블럭제품관리는 목록보기는 대부분 같이 때문에 특별히 설명할 부분이 없다

단지 여기서는 현재 사용하고 있는 목록과 필요가 없거나 파손으로 폐기처분한 목록에 대한 리스트업을 할 수 있도록 기능을 추가하였다.

 

 

- 블럭제품 등록, 폐기, 수정, 삭제

 

 

 

마지막으로 블럭제품의 등록, 폐기, 수정, 삭제에 대한 기능을 삽입해줬다.

상기 화면에서 보면 블럭제품의 등록도 최소한의 정보만 등록하도록 만들었다.

원체 복잡한것을 싫어해서...그리고 현장에서도 복잡하게 등록할 일이 없는것 같아서 최소의 정보만을 입력토록했다.

이 부분에서 정산 부분을 연동시킬까도 생각했지만 정산까지 가면 너무 솔루션이 무거워지고 그러다 보면 아무나 가져다가 무료로 사용하게 하자는 정책에서 벗어날것 같아 제외하고 추후 필요하다면 정산 솔루션을 별도록 만들어서 무료배포를 해볼까 구상중이다.

 

다음 포스트에서는 관리자 등록과 엑셀 다운로드에 대해서 정리하고 나면 기능이나 화면설명은 끝이 난다.

 

참고로 이 프로그램은 종료와 동시에 한달동안의 DB는 자동으로 백업이 되도록 구성되어 있다.

한달이 지난 것은 순차적으로 지워지고 매일매일 종료시에 데이타베이스가 백업이 된다. 물론 로컬에 백업이 된다.

다음 포스트까지 기능 설명 후에 각각 기능에서 기억에 남는 소스를 추려서 다시 소스 공개를 하고 셋업을 위해 NSIS를 사용했는데 혹시나 시간이 되면 간단하게 NSIS에 대한 설명을 하고  마무리할려고 한다.

다음 포스트를 기대해주시고

 

내용을 다른 곳으로 많이 공유해주시면 고맙겠습니다....

추천도 팍팍...

좋아요도 팍팍...

광고도 팍팍....

top