컨테이너 번호 확인을 해야 하는데 찾아 나오는 C# 소스 코드가 에러가 있어서 수정해보았다. 방식은 다음(링크)을 참조했다.

 

        private bool Cntrnumb_Chk(string conNumber)
        {
        	//11자리 그대로 들어와야 한다.
            if (conNumber.Equals(""))
                return false;
            int nChk = 0;
            int nBcd = 0;
            int nHap = 0;
            string sChk = "";
            conNumber = conNumber.Trim();
            for (int i = 0; i < conNumber.Length - 1; i++)
            {
                nBcd *= 2;
                if (nBcd == 0)
                    nBcd = 1;
                sChk = conNumber.Substring(i, 1);
                switch (sChk)
                {
                    case "A": nChk = 10; break;
                    case "B": nChk = 12; break;
                    case "C": nChk = 13; break;
                    case "D": nChk = 14; break;
                    case "E": nChk = 15; break;
                    case "F": nChk = 16; break;
                    case "G": nChk = 17; break;
                    case "H": nChk = 18; break;
                    case "I": nChk = 19; break;
                    case "J": nChk = 20; break;
                    case "K": nChk = 21; break;
                    case "L": nChk = 23; break;
                    case "M": nChk = 24; break;
                    case "N": nChk = 25; break;
                    case "O": nChk = 26; break;
                    case "P": nChk = 27; break;
                    case "Q": nChk = 28; break;
                    case "R": nChk = 29; break;
                    case "S": nChk = 30; break;
                    case "T": nChk = 31; break;
                    case "U": nChk = 32; break;
                    case "V": nChk = 34; break;
                    case "W": nChk = 35; break;
                    case "X": nChk = 36; break;
                    case "Y": nChk = 37; break;
                    case "Z": nChk = 38; break;
                    case "1": nChk = 1; break;
                    case "2": nChk = 2; break;
                    case "3": nChk = 3; break;
                    case "4": nChk = 4; break;
                    case "5": nChk = 5; break;
                    case "6": nChk = 6; break;
                    case "7": nChk = 7; break;
                    case "8": nChk = 8; break;
                    case "9": nChk = 9; break;
                    default: nChk = 0; break;
                }
                nChk *= nBcd;
                nHap += nChk;
            }
            nChk = nHap / 11;
            nChk *= 11;
            nChk = nHap - nChk;
            if (nChk == 10)
                nChk = 0;
            if (Convert.ToInt16(conNumber.Substring(conNumber.Length - 1, 1)) == nChk)
                return true;
            else
                return false;
        }

'C#' 카테고리의 다른 글

DataTable을 Select하기.  (0) 2020.03.23

1. 시작하며

이전 글을 쓴 지 2주 남짓 지났다. 서비스를 운영한다는 건 문제와 해결이 꼬리에 꼬리를 물고 이어진다는 사실을 많이 느꼈다. 해결 하나는 또 다른 문제 하나를 물고 온다. 매일 밤 이용자들의 반응을 보다 보면 추가하고 싶거나 수정하고 싶은 것들이 떠오르기도 했다. 두서없이 개발하다 보니 이번에는 소재별로 글을 정리해 보았다. 

2. 몰려오는 트래픽 물결

개인적으로 이용자들의 정보 수집에 부정적인 관점을 가지고 있다. 장기적으로는 이용자들이 만들어낸 정보의 값어치에 적절한 보상이 필요하다고 생각한다. 하지만 서비스를 운영해보자, 정보를 수집하지 않는 한 물리적으로 관측이 어려운 웹 서비스가 어떤 방식으로 사용되고 있는지 파악할 길이 없었다. 노점상에서 붕어빵을 판다고 해도, 지나가는 손님들과 무엇을 사는지, 얼마나 사는지, 어떤 분들이 사는지를 모르려야 모를 수가 없는데, 구글 애널리틱스를 깔기 전까지는 오직 "꼬들"의 답안지가 어디에 얼마나 올라오는지 확인하는 정도뿐이었다.

 

게다가 트래픽 내역을 확인하자...

 

생각했던 것보다 엄청나게 많은 분들이 즐겨주셨다. 하지만 이 정도 트래픽량을 보니 Github blog의 트래픽 허용 용량이 얼마 정도 되는가 궁금해졌다. ( https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages ) 찾아보니

  • GitHub Pages sites have a soft bandwidth limit of 100GB per month.

라는 게 아닌가? 예전 소소한 설치형 블로그 운영할 때는 1GB/월로도 별 신경 안 써도 되었지만, 현재 이렇게 많은 분들이 하고 계신데 갑자기 트래픽 제한으로 연결이 끊긴다면? 하고 고민이 시작되었다. 그리고 GitHub에서는 현재 트래픽량이 얼마나 남았는지 등을 확인할 수 있는 영역도 없기 때문에, 이후 하루하루 실시간 이용자 수가 12시마다 쭉 올라갈 때마다 보이지 않는 시한폭탄의 심지가 바짝바짝 타들어가고 있는 기분이 들었다.

 

일단은 마찬가지로 정적 홈페이지 트래픽을 무료로 월간 100GB를 지원하는 Vercel( https://vercel.com/ )과 Netifity( https://www.netlify.com/ )에 바로 가입하여, GitHub 내역을 Deploy 해 복제 정적 웹사이트들을 만들었다. ( 이렇게 간단하게 웹사이트 복제를 할 수 있다니! ) 어디 공지할 곳도 없으니, 트위터에 멘션으로 공지하였는데 아무래도 노출이 잘 될 것 같지 않았다. 또한 이렇게 만들어놨다 하더라도 원 GitHub Blog에 트래픽 제한이 걸리면 리디렉션 할 홈페이지조차 닫히게 된다는 아이러니가 실감 났다.

 

게다가 상술했듯, GitHub에서는 트래픽 사용량을 보여주지 않으니, 이 당시 달 초순에는 GitHub Blog , 중순에는 Vercel, 말에는 Netifty로 돌려가며 리디렉션을 할까 생각하고 있었다. ( 지금 생각해보면 그럴 때마다 게임 로컬 스토리지의 통계가 날아간다.... ) 소소하게 Vercel과 Netlify의 초기 주소를 다들 익숙하라고 원 주소를 살려 github-belorin-io로 서브도메인 이름을 지었다가 크롬에 차단되어 매우 놀라기도 했다. 주소 이름을 지을 때는 피싱사이트처럼 보이지 말자.

 

이 화면을 봤을 때 얼마나 놀랐는지.

3. 무한한 트래픽과 도메인 구매

당장 서버가 3개가 되자 먼저 생각나는 것은 도메인이었다. 세 개의 서버를 서로 리디렉션하며 갈아치우는 건 말도 안 되는 일이고, 세 개 다 닫혔을 때 어디론가 공지로 리디렉션 할 지점이 필요했다. 도메인을 고르는데도 생각했던 것보다 고민이 되었다. korld.le일지, kkordle일지, .net이나 .com일지. kordle.net도 고민해보았으나 battle.net과 어감이 비슷해서 이상한 기분이 들었다. 그러다 모양으로 보기엔 kordle.kr이 가장 예뻐 보여서 결정을 하고 GoDaddy( https://kr.godaddy.com/ )에서 구매를 하려고 하는데...

역순, 선순, 도로명 주소, 옛 주소 등등을 이것저것 입력해도 저 유효성 검사를 통과하지 못했다. 이걸 통과하려고 시도하느라 이틀이 걸렸으나 결국 다른 지인 분의 추천으로 호스팅케이알( https://www.hosting.kr/ )에서 쉽고 간단하게 구매하게 된다. 아무래도 .kr을 구매하려면 추가적인 검증이 필요한 상태여서 들어가는 정보인가 본데, 다른 분들은 어떻게 입력하고 구매했는지 궁금하다.

 

이 와중에 상황을 바꿀 트윗 하나가 와 있었는데...

Cloudfare Pages( https://www.cloudflare.com )를 추천해주는 @yechanism_님의 트윗이었다. 무제한 무료라는 말에 당장 가입하고 위의 두 사이트에서 익숙해진 Deploy를 구현하는데, 여기는 Create React App 등에 대해 자동 빌드 및 배포가 구성되어 있었다. 즉 빌드 이전의 코드를 올려두면 자동으로 알아서 빌드해준다! GitHub 원격 저장소에 Push만 하면 바로! ( 무엇을 선택할지 몰라서 Create React App을 선택했으나 React Static과 어떤 차이가 있는지 모르겠다. )

프레임 워크가 이렇게나 많다!

잘 올라가서 돌아가는지 확인한 후에, Kordle.Kr로 포워딩을 걸어주고는 한동안 지쳐서 쉬었다. ( 정적 포워딩을 걸자 아직 HTTPS가 아닌 주소라 바로 Clipboard API가 작동하지 않아 어쩔 수 없이 동적 포워딩으로 변경했다. 그렇게 해놓고 나니 이게 무슨 의미가 있나 싶고, 이용자들은 Pages의 주소를 복사해가기 시작했다. )

4. 어디에서 와서 어디로 가는가?

이렇게 되자 구글 애널리틱스의 리퍼러 대부분은 Kordle.Kr에서 들어오게 되었다. 그렇다면 Kordle.Kr로 들어오는 사람들은 어디에서 오는 건가? 마치 빌딩 로비에 앉아, 입구에서 들어오는 사람들을 보며 "다들 입구로 들어오는군"하는 꼴이었다. 게다가 문제점은 또 있다. 앞으로 개발하고 싶은 아이템은 주소로 쿼리 스트링을 통해서 정보를 받아야 하는데 이래서는 Cloudfare Pages의 주소로 리디렉션 되면서 쿼리 스트링이 날아가는 문제가 생겼다.

 

그래서 SSL을 설정하는데 지금까지 개념을 전혀 잘못 알고 있었다는 사실을 알게 된다. 암호 키나 비대칭키 개념은 알고 있었으나 정확히 인증서가 어디에 어떻게 작동하는지는 모르고 있었던 것이다. 지금까지는 특정 도메인 주소에 인증서가 삽입되고, 그 인증서가 삽입된 주소와 연결되는 서버 모두에게 효력이 발생되는지 알고 있었다. (... 웹 브라우저의 도메인 주소 옆에 자물쇠가 있으니까...)

 

https://www.whatsmydns.net/

하지만 알고 보니 도메인이라는 가면을 쓴 서버가 그 도메인의 서버가 맞는지 확인하는 용도의 인증서였고, 결국 인증서는 서버에 부착되어 도메인 주소의 DNS로 연결되는 것이었다. (아직도 개념을 명확히 이해한 것 같지 않다.) 어찌 되었든간, 또다시 Cloudflare의 도움을 받아 호스팅케이알의 DNS 주소를 Cloudflare 것으로 변경하고, 중간 인증서를 획득하여 이제 Kordle.Kr 옆에도 자물쇠가 달리게 되었다!  ( 네임서버 변경 과정에서 한국 네임서버 변경이 늦어 접속 장애가 발생했다. Dns propagation을 확인할 수 있는 몇 사이트에서 확인해 보았다. )

 

이렇게 같은 주소로 같은 서비스를 제공하고자 하는 과정에서 주소를 기반으로 구성된 로컬 스토리지가 몇 번이나 리셋되었다. 어떻게 손을 쓸 수 없는 상황에서 반복되다 보니 안타까움과 아쉬움이 남는다. 그리고 결과지에 주소를 남길지 말지도 매 번 고민이 돼서 이렇게도 저렇게도 해보았다. 개인적으로는 주소를 어디엔가 붙어 포스팅할 때 자동으로 섬네일이 구성되는 게 지저분하다 느끼는 편인데, 주소를 빼보았더니 일부러 찾아 붙이는 분들도 있어 그렇게도 받아들일 수 있구나 싶었다. 현재로서는 결과 복사 버튼을 링크 있는 버전과 없는 버전 2개로 늘릴지 고민 중이다.

5. 문제를 누구나 출제하도록 해보자!

주소도 고정되었으니, 맘 놓고 주소로 정보를 받을 수 있게 되어 추가 개발을 해보았다. 일단 정보는 간단하게 Base64로 변환하여 주고받고 기본 컴포넌트와 함수들을 이용하여 구성하였다. 생각했던 것보다 빠르게 만들고 배포할 수 있었다. 어느 정도 React의 구성이나 Typesrcipt의 운용을 이해하게 되었다. ( 역시 그냥 해 보는 게 좋다. )

 

개발 중간중간과 SSL 수정, DNS 변경 등 여러 부분에서 S의 도움을 많이 받았다. 특히 문제 출제 폼 구성과 도메인 서버 인증서 획득은 S에게 큰 도움을 받았다. 서로 번갈아 코딩 짜는 걸 공유하며 진행해보니 여러모로 재미가 있었다.

6. 나가며

이제는 가만히 놔두어도 2 ~ 3년 정도는 알아서 굴러갈 수 있는 서비스가 되어 마음은 편해졌다. 현재로서는 안정적으로 길게 군더더기 없는 깔끔함을 계속 유지하고 싶다. 앞으로 시간이 흘러 조금씩 찾아오는 사람이 줄어들다, 몇 명 들어오지 않아도 계속 그 자리에 꾸준히 기다리는 공간이 되고 싶다.

 

P. S.

사람들이 입력하지만 검증 단어에는 없는 단어들을 수집해서 검증 단어 풀을 늘려보려고 수집을 시작해보았는데,

 

뭐든 생각대로만은 되지 않는다. ( 48번째 정답, ㄱㅜㅇㅜㅓㄹ )

 

P. S. 2.

매일 밤 12시에 새로운 문제가 나오니, 12시 직전까지 새로운 기능을 넣어 매일매일 배포하게 되는 좋은 효과가 있는 반면, 다음날 아침에 봐도 무방한데도 새벽 한 시 두 시까지 잠 못 들고 사람들의 반응을 살피다 다음날 산 좀비로 회사 일을 하게 되는 악 효과도 있다.

'공개' 카테고리의 다른 글

"꼬들"을 만들기까지.  (12) 2022.02.05

1. 1월 26일 ~ 27일

아이디어는 기대치 않은 순간에 태어난다. 온라인 모임 단톡방에서 다양한 언어로 이뤄진 Wordle을 이야기하고 있었는데, 한국어 Wordle 이야기가 나왔고 누군가 "해볼까요?" 한 마디를 던졌다. 수동으로 세 판을 내리 해보며 사실상 "꼬들"의 기본적인 요소는 모두 구성되었다. (자세한 내역은 아래 접힌 카톡 대화에 담겨 있으며, 함께한 단톡방 친구분들께 감사의 말씀을 드린다.)

더보기

첫 번째 판

두 번째 판

3번째 판


수동으로 한국어 Wordle을 해보며 정리된 개념은 이렇게 많다.

  • 모음은 완전히 풀어쓰는 게 좋다.
  • 쌍자음과 겹받침도 풀어쓰는 게 좋다.
  • 음절 중간에 낀 자음은 앞에 붙을지 뒤에 붙을지 애매한 효과를 발생시킨다.
  • 여섯 칸이 적합하다. ( 다섯 칸은 2음절 강제, 풀어쓰기 상 겹모음과 겹자음이 최소화된다. )
  • 현 "꼬들"의 자판이 구성되었다.
  • 검증 단어의 범위가 중요하다.

그리고 무엇보다... 하나 만들어주세요, 하는 요청이 있었다.

2. 1월 28일

혹시 모를 마음으로 Github에서 Wordle을 검색해보았다. (현재 검색하면 훨씬 더 다양한 내역이 뜬다. ) 그러자 최상단에 당시 300여 개의 별이 찍힌 Wordle Clone이 나타났다. 현재는 뉴욕 타임스가 구매했기 때문인지 Word-Guessing-Game이라고 변경되었다. ( https://github.com/hannahcode/word-guessing-game/issues ) 나와있는 링크로 한 판 해보니 Wordle Clone은 매우 상세하게 구성되어 있었다. 하지만 GitHub에 올려져 있는 프로그램을 어떻게 진행해야 하는지 알 길이 없었다.

3. 1월 31일 오전

설 전날 집에서 S에게 넌지시 Wordle 이야기를 꺼내자 Fork을 살펴보자고 하였다. GitHub 페이지를 살펴보더니 S는 일단 우상단의 Fork를 눌러 그 목록을 살피기 시작했다. 쭉 내려가다 보니 포크의 포크가 아주 활발하게 구성된 "AnyLanguage-Wordle"이 있었고, ReadME에선 간결하고 쉽게 언어 변경을 간추린 내용이 있었다. ( https://github.com/roedoejet/AnyLanguage-Wordle )

이를 Git Clone을 이용하여 로컬의 적당한 장소에 옮겨놓고, (S의 Mac이었으며 이미 NPM이 구성되어 있었다.) NPM을 이용해 현 패키지의 라이브러리를 알아서 다 설치해주었다. 말하자면 안드로이드의 Grandle이 담당하는 영역과 흡사하다 하는데, 이렇게 일괄 관리를 할 수 있다는 것 자체가 충격이었다.

또한 NPM에서 배포판을 빌드하는 것까지는 그렇다 싶은데, run start를 이용해 서버를 바로 구성하여 웹브라우저로 띄우고, 코드를 수정하는 즉시 결과가 반영된다는 건 믿기지 않는 일이었다. 이 홈페이지를 보면 알겠지만, 보통 C#으로 exe 패키지를 배포하는 편이고 어쩌다 안드로이드 서버를 만들어야 할 때는 아파치 서버를 설치하고 일일이 Webapp 폴더에 올려 쿠키를 지워가며 디버그를 해왔던 입장에서는 인생을 잘못 살고 있는 게 아닐까 하는 생각마저 들었다.

이후 코드를 변경하는 일은 어디서나 비슷한 일이기 때문에 쉽사리 진행이 되었다. Wordle Clone은 Typescript라는 보통 프론트엔드에서 자주 사용하는 언어로 구성되어 있었고, AnyLanguage-Wordle은 사용자 편의를 위해 알파벳 형태일 경우 Constants에 몰아넣은 세팅부터 수정해주면 되었다.

어절의 길이도 간단히 config.ts의 wordLength를 수정하면 되었다. 다만 아직도 여섯 칸으로 결정을 내리지 못했는데, 어섯 칸이 될 경우 난도가 너무 상승하는 게 아닌가 고민되었기 때문이다. 그러나..

  B : 6칸이 되면 다양해져서 너무 어려워지지 않을까?
S : 어휘의 다양성에서는 그렇겠지만, 한 칸당 확인할 수 있는 범위도 같이 늘어나기 때문에 적절할 것 같아.
당장 두 칸짜리를 생각해봐. 그렇게 되면 몇 자 확인하지도 못하고 금방 끝나겠지.
B : ( 듣고 보니 논리적이군. 그리고 남을 설득할 때는 극단적인 반례를 드는게 좋겠군. )  

이 프로젝트를 진행하면서 Mac을 처음 써보았는데, 들었던 대로 마우스는 거의 이용하지 않고 단축키와 터치패드의 구성이 잘 되어 있어 훨씬 편하게 사용할 수 있었다. 특히 터치패드의 두 손가락, 세 손가락 제스처는 문화 컬처였다. 단축키도 Windows 기반과 꽤나 달라서 언어 모르는 다른 나라에 가 어린아이가 된 듯한 기분을 느꼈다.

AnyLanguage-Wordle은 두 가지 어휘목록을 가지고 있는데, 하나는 wordlist.ts로 문제 모음집이고, 다른 하나는 validGuesses로 검증 단어집이다. 처음에는 왜 분리되어 있는지 체감하지 못했지만 나중에 보니 당연히도 범용성 높은 단어만을 문제로, 최대한 넓은 범위의 단어를 검증으로 구성하여야 되었다. 온갖 단어가 다 들어가 있는 어휘집에서 문제를 추출할 경우 상상 이상의 난이도가 될 수밖에 없다.

국립국어원의 기본 어휘 중 명사만을 뽑아 ( 형용사, 동사, 수사 등등은 문제로 나올 경우 납득이 어려울 가능성이 높아 보였다 ) 초기 목표대로 자모를 분리하였다. Python의 h2j, j2hcj 라이브러리를 이용해 일단 분리하고, 이후 따로 만든 필터로 겹모음과 겹자음을 추가로 분리하였다. 그 후 6개로만 이루어진 목록을 정리했는데 여기서 S가 잠깐 목록을 보는데 'ㅈㅏㅎㅅㅏ'라는 단어를 발견했다. 내가 만든 추가 분리 코드에서 'ㅚ'를 뺴먹은 것이었다. 이 문제가 나왔다면 어떻게 되었을까..? ( 차후 1,000여 개의 문제 어휘 목록을 전부 읽어보며 확인하였다. 그러나 이제 와서 생각하니 '위집' 같은 단어는 제거해야겠다. )

말뭉치도 같은 단계로 진행하여 15,000 단어 정도로 검증 단어를 구성하였다. ( https://huggingface.co/klue/bert-base ) 이 정도면 충분하리라 생각했으나 이후 문제가 발생한다.

4. 1월 31일 오후

이쯤에 S가 한국어 워들이 이미 존재하고 있다는걸 발견하고 말해주었다. 개발하기 전에 구글 등에서 검색했을 때 나오지 않았지만 트위터에서 검색을 하니 26일에 이미 개발을 완료하여 올려놓으신 분이 있었다.

 

 

여기까지 굳이 진행을 할 필요가 있었나 하고 체념이 상당히 되었지만, 확인해본 바 칸 수도 입력 방식도 달랐고 완성해서 올렸을 때 사람들이 플레이할게 기대가 되어 마무리 지을 수 있었다.

한국어 자판을 구성하고 입력을 조율하는데, 받아오는 변수인 e.code가 잘 변환되지 않는 문제가 발생했었다. 이후에도 IME 문제가 발생하여 e.key를 직접 받아 한글이 일대일 대응되어 입력되도록 수정하였다. (한/영키 등을 누를 필요 없이 외국 자판을 사용하고 있더라도 위치에 맞춰 한글이 입력될 것으로 예상된다.)

NPM에서 빌드된 배포판을 확인해 본 이후, 적절한 정적 홈페이지를 올릴 사이트를 찾아보았고 Github의 개인 홈페이지도 그에 포함된다는 걸 확인하였다. 그러나 S의 PC에서 작성했기에 Git으로 업로드하기 애매한 상황이었다. 대부분 Github와는 풀과 푸시로 데이터를 주고받겠지만 이번에 Github에도 강제 파일 업로드가 있음을 확인할 수 있었다. 자정이 가까워져 가는 시간에 업로드하여 작동을 확인했고, 트위터에 게시하였다.

글 그대로 다들 재미있게 즐겨주었으며 하는 마음에 올렸는데 생각했던 것보다 더 많은 사람들이 참여하였고, 최대한 요건들을 개선하고 싶은 마음이 들었다. 일정도 설 연휴인지라 더 많은 사람들이 함께할 여유가 있었던 것으로 보인다.

5. 2월 1일 오전

트위터에서 트랜드에 올라가는 걸 확인하다 잠들었다. 다음 날 보니 이용자 분들이 단어가 너무 부족하다고 힘들어했다. "Word not found"가 싫다는 이야기 일색이었다. 그래서 DB를 찾아보는데도 그렇다 할 내역이 보이질 않았다. 부모님께도 한 판씩 하도록 해드렸는데 '가자미', '미나리', '다리미'를 입력하시는데 단어가 없어 한탄하셨다.

설 당일 바닷가가 보이는 전망대에서 휴대폰으로 열심히 검색을 해보니, K-ICT 빅데이터센터란 곳에서 NIADic을 Xlsx로 받을 수 있었다. ( https://kbig.kr/portal/kbig/datacube/niadict.page ) 집에 가자마자 열어 확인하는데 단어의 질이 그렇게까지 썩 좋지는 않았다. 품사 태그 표에서 명사 종류는 n으로 시작하는데, 모든 명사 종류를 ncn 하나로 통일시켜놓아서 따로 더 거를 수도 없었다. ( 네이버에서 우리말샘이 국어사전 지분을 늘려가는 것을 지적하는 경우가 많은데, 이 데이터에는 우리말샘의 단어들이 들어가 있는 것으로 보인다. )

더 시간을 허비할 수는 없고, 적당히나마 ㄹ로 시작하는 단어들을 거르고 - 북한어가 상당히 많이 들어있었다 - 이전과 같은 처리를 거쳐 자모를 분리해 검증 어휘 목록에 추가하였다. 이 와중에 CSV로 변환한 데이터를 Python이 약 170만 건 이상이라고 에러를 내뱉어서 시스템 한계를 해제하는 무식한 방식으로 넘겼다. 다들 '솜털', '나루터', '감줄', '긍휼', '힐난', '고라니', '두더지' 등의 단어가 없다고 아우성 중이었기 때문에 최대한 빨리 올리고 싶었다.

그런데 당장 올리려고 보니 정말 말도 안되는 단어들도 있는데 괜찮은가 싶었다. 사실상 사전에도 없는 단어들이 많은데 (사투리, 입말 등). 하지만 어떻게 생각하면 칠 수 있는 단어들이 늘면 역설적으로 단어를 많이 아는 사람들의 난도가 자동으로 상승한다. 그리고 이상한 단어가 통과되는 것이, 단어가 없다고 나오는 것보다 이용자에게 피로도를 덜 준다. 그런 면에서 업로드를 진행했다. ( 이후 검증 단어 목록은 약 55,000 단어가 되었다. )

하는 김에 지문 대부분을 한국어로 수정하였다. 이 업로드 이후 다들 만족하는 분위기라 기분이 좋았다.

6. 2월 1일 오후

구글 애널리틱스의 추적 ID를 추가하는 부분이 Config.ts에 있기에 추가해보았으나 하루를 작동하지 않고 있었다. 알고 보니 ID 번호의 시작이 G-로 시작하면 안 되고 UA-로 만들어야 작동한다. 다음날에 수정하여 올리니 정상적으로 연결이 되었고 이때부터 이용자 정보를 확인해볼 수 있었다. 만드는 와중에 고급 설정에서 선택해주어야 한다. 다음 포스트의 도움을 받았다. ( https://devsungyeon.github.io/github%20blog/Google-analytics/ )

7. 2월 2일

S와 함께 집에 돌아와 내 컴퓨터에 개발 환경을 구성하기 시작했다. Windows에서도 Node.js를 설치하고 intelliJ 커뮤니티 판은 Typescript 개발 지원이 안 된다고 하여 Vs Code를 준비하였다. Node.js가 잘 설치되고 나자, NPM도 잘 작동하였고 크게 다르지 않게 가상 서버가 구성되고 수정된 코드가 바로 웹 테스트에 반영되었다.

그 사이 설명을 꾸준히 바꿔왔는데 겹자음과 겹모음을 자연스럽게 읽고 무의식 속에 어휘 풀어쓰기를 받아들일 수 있도록 배치하려고 노력하였다. 최대한 자모가 겹치지 않도록 했는데 자연스럽게 읽히는지 궁금하다. 하는 김에 소소하게 파비콘도 변경하고, 손톱 밑 가시 같던 키보드 배치도 변경하였다. 혹시나 아직도 단어가 없다는 알림창이 영어로 나온다던가, 키보드 형태가 실제 키보드와 상이하다던가, 파비콘이 원자로 보일 경우 F5를 한 번 눌러주시길 바란다.

8. 차후

새로운 사전 데이터를 추천받았는데 예상되는데 앞으로 어떻게 진행할지 고민이 된다. 다음과 같이 세 가지 방법이 있을 것이다.

  1. 유지 - 우리말샘과 입말이 검증 어휘 목록에 포함되어, 어휘 검증이 질적으로 떨어지나 익숙함을 유지할 수 있다.
  2. 추가 - 분량이 너무 많아지므로 무거워질 수 있고, 단어 풀이 너무 넓어져 단어 필터링의 질이 낮아진다.
  3. 교체 - 갑작스레 사전 단어로만 빡빡하게 변경되어 이용자들이 낯선 상태에 돌입하게 된다.

좀 더 생각해보니, 일단 기초대사전의 단어들을 받아, 현 목록과 얼마나 겹치는지 등을 비교하여 분량을 생각해서 그때 결정하면 되겠다.

꾸준히 지적된 결과 복사 버튼 수정도 우선순위에 있다. 초기 우선순위에서는 잠시 검색해봐도 다양한 환경에서 각기 다른 결과가 펼쳐져 피드백이 매우 복잡해질 수 있어 뒤로 밀어놓았는데, 편안한 공유를 위해 이제 언어도 찬찬히 알아보면서 수정이 필요할 듯싶다. 마지막으로...


>>> 귀엽고 단순한 게 최고다. <<<


P. S
한글의 특성 때문에 다양한 방식의 풀이법이 존재하며, 각각 좋은 디자인으로 구성되어 있다면 놀이 방법은 큰 문제가 아니라고 생각한다. 개인적으로 3자 우리말 워들( https://plan9.kr/wordle/ )을 적정한 난이도 때문에 재미있게 하고 있으며, 심지어는 5자 음절 워들( https://site.thekipa.com/korsylwordle/ )도 몇 개 풀어보았다.

P. S. 2.
개발자 판에는 Shuffle 모드가 존재한다. 원한다면 시간제한 없이 무한으로 즐길 수 있다. ( 그러나 안 쓴다... )

P. S. 3.
현재 "꼬들"의 결과를 공유할 때 앞에 31 ~ 35라고 붙어 있다. 1 ~ 30은 어디로 갔는가 하면, 애초에 이 패키지가 2022년 1월 1일 배포할 것으로 예정되었을 때의 디폴트 값이 들어있었는데, 그걸 수정하지 않고 배포해버려서 문제 어휘 목록 중 앞 30개를 넘기고 시작해 버렸다.

P. S. 4.
현재 "꼬들"의 문제 어휘 목록의 차례는 완전히 임의적이다. 어떠한 의도도 담겨있지 않는데 신기하게도 맥락을 느낀다.

'공개' 카테고리의 다른 글

"꼬들"을 운영하면서.  (12) 2022.02.20

안드로이드로 앱 개발을 진행 중인데 PC에서는 C#로 구성된 프로그램에서 DB에 접근한다.

PC에서 이미지 파일을 MS SQL Sever에 binary로 변환하여 업로드하는데, 그걸 안드로이드 앱에서 받아 이미지를 구현하는데 많은 애를 먹어서 작성해본다.

 

이전에 존재했던 DB - APP 정보 송수신은 다음과 같았다.

 

1. Ms SQL Server에 Apache Http Server 설치 ( 고정 IP 설정 )

2. SQL Server와 Apache Http Server간은 JDBC로 통신

3. Apache http Server는 JSP를 통해 XML 서식으로 송신

4. App에서는 XMLparser와 POST 방식을 이용하여 수신

 

일단 문제를 일으키던 XML 형태를 JSON 형태로 바꿔 개발하기 시작했다. 데이터를 잘 받아오던 와중에 binary(max)로 변환된 이미지를 JSON이 제대로 가져오지 못하면서 문제가 생기기 시작했다. 이유인즉슨 binary 값을 받아오기 위해서는 byte[] 형태로 가져와야 하나, JSP에서 출력할 때 이미 toString()으로 변환되어버리기 때문이었다.

 

이미 변환된 String을 byte[]로 바꾸기 위해 App에서 여러가지 시도를 했으나 전부 실패했고, JSP 상에서 Base64를 이용하여 encode하려던 것도 Import를 못 잡아서 시행하지 못했다. 한참 헤매던 끝에, SQL Server에서 query를 작성했을 때, Select 되는 결과를 Base64로 변환하여 올라오도록 수정하였다.

 

SELECT CAST(N'' AS XML).value('xs:base64Binary(xs:hexBinary(sql:column(\"컬럼이름\")))', 'VARCHAR(MAX)') 컬럼이름 FROM 테이블이름

 

그리고 난 후 App 상에서 Base64 변환을 거쳐 ImageView에 setImageBetmap()을 하니 잘 올라갔다. 도식은 다음과 같다.

 

  String checkImage = array.getJSONObject(i).getString("컬럼이름"); //받아온 String 데이터
  byte[] encodeByte = Base64.decode(checkImage, Base64.DEFAULT);
  Bitmap bitmap = BitmapFactory.decodeByteArray(encodeByte, 0, encodeByte.length);
  bitmap = Bitmap.createScaledBitmap(bitmap,  600 ,600, true); // 크기변환
  imageView.setImageBitmap(bitmap);

 

아마 JSP에서 base64를 이용하여 JSON에 변환된 결과값을 담는 방법도 있을 것이다. JSP에 익숙하지 않아도 Server단에서 base64로 변환하는 방법도 있다는걸 정리하고 싶었다.

DevExpress에서는 열별 Summary를 GroupFooter를 통해 자동 생성을 지원하고 있습니다.

GroupField와 xrTableCell별 DataBinding을 이용하면 쉽게 소계와 합계를 낼 수 있습니다.

 

다만 다음과 같은 상황을 생각해봅시다.

 

[QUNT] [COST] [TLAM]

 

수량[QUNT]과 단가[COST]를 곱해서 결과[TLAM]를 내야 하는데, Detail이나 GroupFooter인 경우, xrTableCell을 기준으로 접근할 수가 없습니다.

왜냐하면, Detail과 GroupFooter는 테이블의 상태에 따라 자동으로 갯수가 변화하게 되는데, 객체 자체는 하나로 계속 유지되기 때문입니다.

그런고로 Event를 잡아서 xrTableCell.Text를 꺼내봐도 아무것도 없으며, String을 넣는다 하더라도 Report에 반영되지 않습니다.

 

먼저는 자동 생성하는 셀 객체를 찾아야 합니다. 그러기 위해서는 먼저 찾고자 하는 셀의 'BeforePrint' Event 메소드를 생성합니다. (속성에서 생성가능)

생성하고 나면 매개변수는 다음과 같습니다.

 

private void xrTableCell_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e)

 

sender 오브젝트를 XRTableCell으로 캐스팅하면 라인이 추가로 생성될 때마다 생성되는 Cell을 가져올 수 있습니다.

그래서 예를 들어 다음과 같이 하면 생성될 때마다 Cell에 값을 찍을 수 있습니다.

 

XRTableCell cell = (XRTableCell) sender;

cell.Text = "SomeThing";

 

특정한 값을 가져오기 위해서는 조금 복잡합니다. cell의 Text값은 Print 되기 전에는 빈 값입니다.

그리고 XRTableCell의 내부 변수에는 Value 값이 없습니다. Report에서 보이는 단일 사각형과 관련된 정보(디자인적 요소)만 있다고 생각하시면 됩니다.

그리하여 다음과 같이 돌아가야 특정한 값을 가져올 수 있습니다.

 

XRTableCell cell = (XRTableCell) sender;

XtraReport report = cell.RootReport;

object Value = report.GetCurrentColumnValue("QUNT");

 

위와 같은 상황에서 저 행이 Detail이라면 다음과 같이 매 번 Detail이 생성될 때마다 거기에 현재 찍힐 수량[QUNT] 값을 가져올 수 있습니다.

다만 이의 경우 Summary 등으로 구성된 이름 없는 변수값을 가져올 수가 없습니다.

 

GroupFooter에서 자동으로 Summary된 값을 가져오려면 다음과 같이, cell에 넣어놓은 Summary 메소드를 실행하면 됩니다.

 

XRTableCell cell = (XRTableCell) sender;

object value = cell.Summary.GetResult();

 

다만 이렇게 코딩할 경우, Summary는 구성되어 있지만 값이 없어서 GetResult 결과가 null로 나올 경우, NullPointException 에러가 Print 창에서 발생합니다. 

"개체 참조가 개체의 인스턴스로 설정되지 않았습니다."라고 하며, Debug에서도 잡히지 않습니다.

그런고로 저는 다음과 같이 처리하였습니다.

 

XRTableCell cell = (XRTableCell) sender;

if (cell.Summary.GetResult() == null)

return "SomeErrorThing";

else

return cell.Summary.GetResult();

 

이렇게 구성하시면, 전역변수를 통해 메소드간 데이터를 주고 받고, 행간 수식을 구성하실 수 있습니다.

 

P.S. Summary를 사용하지 않는 행의 경우, RootReport를 통해 아예 현재의 Row을 가져오는 방법도 있습니다. (GroupFooter이기 때문에 이렇게 복잡합니다.)

다음과 같이 짜면, Row를 바로 가져와 내부 행들을 쓸 수 있습니다. (Detail의 경우)

 

XRTableCell cell = (XRTableCell) sender;

XtraReport report = cell.RootReport;

DataRowView currentRow = (DataRowView) report.GetCurrentRow();

object[] rowItem = currentRow.Row.ItemArray;

 

//cell.text = (decimal) rowItem[1] * (decimal) rowItem[2]

C#에서는 강력한 DB 라이브러리를 제공하고 있음에도 제대로 이용하고 있지 못하다. (특히 Linq)

대부분 하드 쿼리를 이용해서 필요한 정보들을 요청하고 정리하는데, 프로그램 상에서 수정할 수 있는 것을 도전해보고 있다.

 

쿼리를 통해 받은 DataTable 객체를 이용하고자 하려니 여러 문제가 생긴다.

가장 간단하게 DataTable에서 Select하고 내용을 쓰려고 하니, Select을 DataRow[]를 반환하는 것이다.

이걸 foreach 혹은 for 문을 돌려 새로운 DataTable 객체에 넣으려니 분통이 터진다.

알고보니 그렇게 할 필요가 없다.

DataTable Table = SomeTable.Select("SomeThing = '100'").CopyToDataTable();

위와 같이 하면, 데이터 테이블을 반환한다.

다만 이렇게 할 경우, Select 이후 DataRow가 0일 경우 에러가 발생한다.

DataRows[] dataRows = SomeTable.Select("SomeThing = '100'")
if(dataRows == null || dataRows.Length == 0)
	return;
DataTable Table = dataRows.CopyToDataTable();

그렇기 때문에 위와 같이 에러 처리를 해주는 것이 좋다.

'C#' 카테고리의 다른 글

[C#] 컨테이너 번호 에러 체크 container number digit check  (1) 2022.09.22

- 두 개의 프로젝트를 Commit하고 가지고 있는 모든 프로젝트를 Git으로 갈무리하려는 찰나,

- 그 프로젝트를 열 때마다 로딩이 엄청나게 지연되었다.

 

- 나중에 곰곰히 생각해보니, 첫 Commit을 할 때 이상한 에러가 발생하였고,

- 빨리 Commit을 하고 싶은 나머지 그 에러 대응을 검색해서 바로 처리해버렸다.

warning: CRLF will be replaced by LF in some/file.file.
The file will have its original line endings in your working directory.

- 위와 같은 에러이며, 간단히 말해 리눅스와 윈도우를 오갈 때 생기는 문제들이다.

- 나는 이 글을 참조하여 아무 생각 없이 자동변경을 켜버렸는데, 그래선 안 되었다.

- C#의 코드들은 메모장으로도 열 수 있는 TXT 형태로 되어 있는데 그게 변형되어 버린다.

 

- 지금까지는 아직 리눅스 사용자와 협업할 일이 없으므로, 자동변경을 꺼주도록 한다.

- 이걸 한다고 해서 로딩 지연이 해결될지는 모르겠다.

##설정
git config --global core.autocrlf false

##설정확인
git config --global --list|grep core.eol

-  자동변경을 끄고 나서 git status를 검색하자 다음과 같은 에러가 발생하였다.

- 또한 git config --list를 사용해도 core.autocrlf가 중복으로 들어 있는 등 다른 문제들이 발생했다.

git status

fatal: bad numeric config value 'auto' for 'core.autocrlf'

- 그래서 다음 글을 참조하여, 문제를 해결했다.

- 요약하자면 다음과 같다. AutoCRLF를 리셋시키고, 재설정한다.

git config --system --unset core.autocrlf
git config --global core.autocrlf false

 

Git을 실무 적용된 상태로 배울 수 없어서 당혹스러운 과정들을 거치고 있는데, 초보더라도 그 과정들을 기록해보자 한다.

 

- 일단 범용 컴퓨터라 Git GUI와 Git BASH가 설치되어 있었다. 

- 그런고로 저장소를 만들고 싶은 폴더에서 오른쪽 버튼을 누르면, 그 경로에서 GUI나 BASH(cmd)를 실행할 수 있었다.

 

- git은 저장소 폴더의 '.git' 폴더 내에 모든 정보가 담겨 있으므로 연습하다가 두려우면 그 폴더를 삭제하면 깔끔하게 제거된다.

- git을 그렇게 삭제하는 것 외에 제거하는 것은 상당히 어렵다고 한다. ( 잘 모름 )

- 폴더에서 '숨겨진 파일 표시'를 하면 콤마로 시작하는 파일들도 전부 보여 무언가 잘못 될 때의 두려움이 해소되었다.

 

- 다음에는 git을 구성할 때 들어가는 용량과 부하가 걱정되었다.

- 아무 생각 없이 변환된 모든 파일을 읽어들이고 기록한다면, 릴리즈, 디버그 빌드 dll 등 몽땅 기록될 것이다.

- 그래서 알아보니 git ignore라는 설정을 넣으면 특정 이름의 폴더나 특정 속성의 파일들을 기록하지 않는다.

- C# ignore라고 검색했을 때 나오는 것을 기준으로 작성하였다.

 

- 당황하지 말고, 다른 분들의 도움을 받아 만들자.

- 여기서 당황했던건 C# ignore의 내용을 붙여넣어야 하는데, Vim 화면에서 Ctrl-V가 안 된다.

- git BASH 상에서 오른쪽 클릭을 하여 PASTE로 붙여넣거나, Shift+Insert를 하면 붙여넣기가 가능하다.

 

- 또한 ignore 파일을 만든 즉시 다른 설정을 해줄 필요 없이 바로 적용된 상태가 된다. ( 이것도 당황 )

- 그럼 이제 Commit을 진행하면 걱정했던 것들은 제외하고 저장이 된다.

 

- 그리고 Git을 따로 공부할 때 개인적으로 가장 혼란스러웠던 것은 checkup등 master의 위치가 무엇을 의미하느냐였다.

- 처음부터 이해하기 전까지는 master가 일종의 포인터라고 생각했고, 지시 위치를 변경한다고 생각했다.

- 그렇기 때문에 먼저 포인터를 이동시키고, 다른 조작어를 통해 포인터가 지시하는 파일의 형태로 변경한다 착각했다.

- 그러나 포인터와 실제 파일이 일치하는 상태이며, 이동 즉시 현재 저장소의 파일들은 모두 변경된다.

- 이런 혼동이 정리된 이후는 좀 더 잘 파악할 수 있게 되었다. ( 레퍼런스 형태가 아니라니. )

평균보다는 늦은 나이에 프로그래머의 삶을 시작했기 때문에 장기적인 삶은 어떻게 살아야 하는가 확인하기 위해 이미 10년 전이지만 나이든 프로그래머들이 쓴 글을 살펴보았다.

 

대략적으로 당시의 선택지를 정리하자면 다음과 같다.

1. 정보처리 기술사, 감리사를 취득한다.

2. 관련 영역에 대한 책을 쓴다.

3. 온라인 / 오프라인 모임을 구성하고 주도한다.

4. 전직한다. ( 관리자, DBA, 컨설턴트 등 )

 

[정보처리 기술사, 감리사]

구체적이고 확실한 목표가 주어지지만 왜 해야하는 지는 명확하지 않고, 일종의 고시 차력처럼 느껴졌다. 이 책의 일부는 정보처리사를 따기 위한 메뉴얼로 이루어져 있다. 경력에 도움이 되고, 광범위한 IT 영역의 정보를 이 과정을 통해 타의적으로나마 정리할 수 있다는 장점이 있지만, 심적으로 꺼려진다. 그래도 한국의 경향성과 이 계통의 분류 방식을 참고하기 위해서라도 미리 미리 확인해볼 생각이다.

 

[서적 출판]

자발적으로 선택하여 생산적이고 맺음이 있는 일처럼 느껴졌다. 자기 분야에 충실한 결과물을 낼 수도 있고, 실무를 체계화시켜 정리하는 과정이 포함되기도 한다. 다른 무엇보다도 이걸 통과한 사람들이 느끼는 효능감은 위의 시험과는 다른 부분이 있다. 자격증의 경우 언젠가 해야 하는 것을 해내거나, 자존심의 일부를 지지하는 요소가 되었다면, 서적은 하면 고생이나 계속 해보고 싶다, 1년에 한 권씩 내고 싶다고 이야기 한다. 책을 쓸만큼 체계적으로 정보들을 이해해나가는게 좋겠다.


2011년도에 나온 책이라 현재 시점에서 어디서 무엇을 하고 있는지 확인하고 싶었다.

 

임백준 - 이후 [나는 프로그래머다]라는 책도 읽었다. 위키 페이지에 등록되어 있으며, 2017년 삼성전자의 상무로 근무중으로 나온다. ( 데이타 인텔리전스랩 상무 )

 

오병곤  - 터닝포인트 경영연구소 대표로 있다. 글쓰기를 지도하고 있는듯 하다.

 

이춘식 - (주)씨에스리(DB 전문)의 대표이사로 있으며, 아이리포라는 기술사 등 IT 교육산업에 종사 중이다.

 

이주연 - 은퇴한 것인지 알 수가 없다.

 

박재성 - 브런치의 설명에 의하면 프로그래머 교육 서비스인 넥스트스텝을 운영하고 있으며, 우아한형제들에서 우아한테크코스 교육 과정을 만들어 가고 있다.

 

신재용 - 데이터뱅크시스템즈의 이사로 있으며, 브레인 코딩에 관련된 글을 쓴다.

 

대부분 IT 교육 사업에 매진하고 있다. 이게 적당한 방향인지는 모르겠다.

'프로그래밍 서적 읽기' 카테고리의 다른 글

2019년 마지막 주기 반납 결산.  (0) 2019.12.28

  새로운 영역에서 일하게 되면 언제나 관련된 책들을 찾아보게 된다. 도서관에서 책들을 열람하다보면, 그 주제를 출판 영역에서 어떻게 다루고 있고, 서지학에서는 어떻게 분류하고 있는지 알게 된다. 이런 총체적 스케치가 안심을 이끈다. 프로그래밍 계통도 이와 마찬가지로 접근 중이며, 정리를 해보려 한다.

 

 = A대 도서관

- 대학 도서관이므로 관련 책들의 볼륨이 가장 넓고 깊다. 다양한 책들을 빌리는 중. ( 대출 기간 : 2주 + 4주 )

 

 [도메인 주도 설계] | Evans, Eric

 

  절반 정도 읽고 반납. UML도 디자인 패턴도 모르는 상태로 읽기 시작하였다. 전혀 모르는 영역에 대해서도 무작정 읽으며 나름대로의 구성을 정리해나가는데, 이 책을 통해서는 프로그래밍 설계 철학의 패러다임 변천을 감각하게 되었다. 대부분의 개설서를 읽기 시작할 때 OOP를 PP와 비교하며 시작하게 되는데, 사실상 맥락을 모르는 상태에서는 쌩뚱맞게 느껴진다. 이 분야도 DDD라고 불리는데, TDD와 비견될 어떤 '프로그래밍 설계' 개념이라고 생각하지 않으면 맥을 못 추게 된다. 프로그래밍 전반을 구성하는 영역의 구조단을 어렴풋이 분류할 수 있었다.

 

   개념들이 매우 추상화되어 있는 상태에서, 어떠한 패턴들을 이해한다손 치더라도 실무에서 적용이 가능할까 하는 의문이 들고, 일단 디자인 패턴의 구체를 이해한 후에 다시 접근해보기로 하였다. 각각의 개념에 대한 자세하고 긴 서술은 이 책의 특점이다.

 

[디자인 패턴 재사용성을 지닌 객체지향 소프트웨어의 핵심요소] | Gamma, Erich

 

  23개의 디자인 패턴을 처음으로 주창한 책. 맥락만 살펴보고 반납하게 되었다. 오래된 책은 읽기가 힘들다. 일단 언어가 낯설수 밖에 없으며, 실무 구성에 가상으로 적용하는 상상을 해야하는데 그게 쉽지가 않다.

 

[객체 지향과 디자인 패턴] | 최범균

 

  한국인이 쓴데다 익숙한 Java로 설명했다고 하여 빌렸는데, 거의 못 읽고 반납. 나중에 다시 한 번 빌려보고 싶다. 종이 책으로 코딩을 익숙하게 읽을 수 있을까. 이 두 권의 책을 훑어본 후, 디자인 패턴을 미약하게 이해하게 되었다. 객체를 어떤 방식으로 배치하고 재배치 / 수정하는 방식으로 상황을 쉽게 개선하고 변경할 지, 그리고 그런 명칭들에 이름 붙여 서로 대화할 때 더 잘 대화하기 위해서.

 

[프랙티컬 C#] | 이데이 히데유키

 

  현재 사용하고 있는 언어를 다룬 책을 한 권은 빌리고 싶어서 고른 책. 원하던 형태로 구성되어 있었고, 기회가 되면 구매하겠다고 생각했다. 낙서를 하고 꼼꼼하게 읽어보고 싶은 책.

 

 = 타 도서관

 

[꾸준히, 자유롭게, 즐겁게] |  송우일

 

  주변 도서관에서 우연히 발견해 단숨에 다 읽은 책. 현재 어떤 내용의 책을 읽고 싶은지 확연하게 자각했다. 이 계통에서 일을 늦게 시작하게 되기도 했고, 한국에서 다른 사람들이 어떤 방식으로 커리어를 쌓아 올려가고 있는지 매우 알고 싶었던 것이다. 나이가 더 들면 어떻게 될 지, 지금의 이 시간을 이렇게 쓰는게 맞는지, 앞으로 어떤 방식으로 살게 될 지 등등. 각자가 하는 분야의 디테일한 용어들을 몰라도 어떤 걸 어떻게 얼마나 진행하는 지를 들어보며 약간 안정되는 느낌이었다. 그래서 이 계통의 책을 몇 권 더 빌렸다.

 

  일단 얇고 넓게 어떤 테크트리가 펼쳐져 있는지 확인하고, 내가 뭘 하고 싶고 밖에서는 뭘 요구하는지를 찾아보는게 좋겠다. 보통 특정 프로젝트가 2~3년 가기도 하고.

+ Recent posts