Golang의 sort.Sort는 비교 정렬이자 불안정 정렬이다. (sort.Stable 안정 정렬을 지원한다.) 개발자는 두 데이터를 비교해 어느 데이터가 먼저 와야 하는지 알려주는 부분을 작성하면 된다. sort.Sort를 이용하기 위해서는 Len, Less, Swap 함수가 구조체 슬라이스에 정의돼야 한다. 물론 int, string, float64 슬라이스는 sort.Ints, sort.Strings, sort.Float64s 함수로 정렬한다.
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with index i
// must sort before the element with index j.
//
// If both Less(i, j) and Less(j, i) are false,
// then the elements at index i and j are considered equal.
// Sort may place equal elements in any order in the final result,
// while Stable preserves the original input order of equal elements.
//
// Less must describe a transitive ordering:
// - if both Less(i, j) and Less(j, k) are true, then Less(i, k) must be true as well.
// - if both Less(i, j) and Less(j, k) are false, then Less(i, k) must be false as well.
//
// Note that floating-point comparison (the < operator on float32 or float64 values)
// is not a transitive ordering when not-a-number (NaN) values are involved.
// See Float64Slice.Less for a correct implementation for floating-point values.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
func sort.Slice(slice interface{}, less func(i int, j int) bool)
sort.Slice 첫 번째 인수에 슬라이스, 두 번째 인수에 이전에 정의한 Less 함수를 넣으면 된다.
sort.Sort 특징
Golang에서 사용되는 정렬은 퀵 정렬을 사용합니다. 최악의 복잡도를 피하기 위해 피벗 3개 중 가운데를 선택하는 중위법을 사용합니다. 퀵 정렬의 깊이가 너무 깊어지면 힙 정렬을 사용하고 퀵 정렬 도중 데이터가 7개 이하가 되면 삽입 정렬을 사용합니다. 삽입 정렬은 데이터가 적으면 효과적입니다.
func quickSort(data Interface, a, b, maxDepth int) {
for b-a > 12 { // Use ShellSort for slices <= 12 elements
if maxDepth == 0 {
heapSort(data, a, b)
return
}
maxDepth--
mlo, mhi := doPivot(data, a, b)
// Avoiding recursion on the larger subproblem guarantees
// a stack depth of at most lg(b-a).
if mlo-a < b-mhi {
quickSort(data, a, mlo, maxDepth)
a = mhi // i.e., quickSort(data, mhi, b)
} else {
quickSort(data, mhi, b, maxDepth)
b = mlo // i.e., quickSort(data, a, mlo)
}
}
if b-a > 1 {
// Do ShellSort pass with gap 6
// It could be written in this simplified form cause b-a <= 12
for i := a + 6; i < b; i++ {
if data.Less(i, i-6) {
data.Swap(i, i-6)
}
}
insertionSort(data, a, b)
}
}
우크라이나 IT 기업들은 개발자 부족으로 손해를 보고 있다. IT 기업들이 빠르게 성장함에 따라 일 년에 약 개발자 5만여 명이 필요하지만, 매해 우크라이나 대학을 졸업하는 공학도들은 1만 6천 명 밖에 되지 않는다. 최근 조사에 따르면, 2024년까지 상황은 많이 변하지 않을 것으로 예측된다.
유럽연합이 후원하는 비정부기구인 BRDO(Better Regulation Delivery Office)는 2024년 우크라이나 연간 공과대학 졸업생이 23% 증가해 2만 명에 이를 것으로 본다. 그러나 2030년에 졸업생은 3만 8천 명이 되어 인력 상황이 좋아질 것으로 예측한다. BRDO 전문가 Ihor Samokhodsky는 우크라이나 기술 교육이 시대에 뒤떨어져 현지 시장의 요구를 충족시킬 수 없다고 판단한다. 하지만 높은 급여와 기술 산업이 제공하는 많은 일자리를 보고 젊은 우크라이나 청년들이 기술 분야를 공부한다고 말했다. 전문가들은 우크라이나에 기술 인력 충원을 긍정적으로 바라본다. 개발자 한 명이 매년 3만 5천 달러 어치를 수출하고 있고 기술 중심지라는 이미지를 홍보한다고 말했다.
Benefit
우크라이나 IT 산업은 매년 30%씩 성장하여 40억 달러 이상 수출을 하고 약 5억 9천만 달러를 세금으로 낸다. 약 18만 2천 명이 산업에 종사하고 있지만 인력이 부족한 상황이다. 현지 기술 기업 글로벌 로직은 지난 5년 동안 우크라이나 테크 기업의 인력 수요가 30% 가까이 증가하였다. 또한 파이썬, 자바스크립트, 자바, C++과 같은 프로그래밍 언어를 다루는 전문가들이 가장 수요가 많다고 했다. 키이브(키예프, 우크라이나 수도) 개발자들은 평균적으로 한 달에 2300달러를 버는 반면 우크라이나 평균 연봉은 440 달러이다.
BRDO는 우크라이나 개발자 85%가 키예프, 하르키프, 르비브, 드니프로, 오데사와 같은 대도시에서 지내고 그중 28%가 키이브에 거주한다고 말했다. 도네츠크 국립기술대학교, 키이브 국립대학교, 키이브 국립 기술 대학교 졸업생이 대부분을 차지한다. 하지만 낮은 집값, 편리한 교통, 깨끗한 환경을 요인으로 우크라이나 서부로 이동하고 있다. 우크라이나 온라인 테크 포털인 Dou.ua 설문조사에서 이바노-프랑킵스크, 르비브, 빈니쨔 같은 서부 도시들이 개발자들에게 가장 선호되고 있다.
Problems
이런 장점에도 불구하고 우크라이나 기술 산업은 교육 환경 부족, 인력 유출, 국내 기술 수요 부족이라는 문제가 있다. 많은 우크라이나 학생들은 대학교에 정보 기술을 공부할 노트북과 고속 인터넷 연결이 없다고 밝혔다. 또한, 대학교들이 최신 기술 발전을 따라가지 못하고 취업과 관련된 기술을 가르치지 않는다고 불평했다. 대학 교수들은 평균 1200달러 월급으로는 가르칠 이유가 없다고 불만을 나타내기도 했다.
우크라이나 정부는 낮은 세금과 높은 연봉으로 졸업생들을 국내에 유치하려고 하지만 외국 기업들은 더 좋은 조건을 제시한다. Dou.ua에 따르면, 우크라이나 개발자의 75%가 미국이나 서유럽으로 이주하려고 노력하는 반면 나머지 25%만 자국에 있고싶어 한다. 자국에 남은 개발자들조차도 해외에 서비스를 판매한다. 우크라이나는 아웃소싱 업체 수가 인도에 이어 세계 2위이다. 우크라이나 기업 21개가 세계 100대 아웃소싱 업체 중 하나이다. 스타트업을 창업한 개발자들도 해외로 진출하였다. Grammarly, People.ai, GitLab이 미국에 등록된 대표적인 우크라이나 스타트업이다.
Opportunity
BRDO는 국내 기술 산업 종사자 수를 증가시키는 두 방법을 제시한다. 첫 번째는 다른 산업 종사자에게 코딩을 교육하는 것이다. 이를 위해 현지 테크 기업과 비영리단체들이 무료 온라인 강좌로 웹 개발 기본과정 등을 제공하고 있다. 두 번째 방법은 해외 개발자를 국내에 유치하는 것이다. 많은 외국 개발자들에게 우크라이나는 부정부패, 관료주의 등으로 외면받는다. 하지만 전문가들은 우크라이나 IT는 앞으로 성장 가능성이 많다고 한다. 예를 들어 우크라이나는 기업인이 가장 낮은 세금(5%)을 내는 나라 중 하나이고 대부분 프로그래머가 개인 기업인으로 등록되어 있다고 한다.
2020년 10월 19일 ~ 2020년 12월 31일 와이즈넛, SK NUGU Interactive NLU DM DB 구축 규칙 생성
2021년 1월 우크라이나 학습 사이트 프로젝트 실패
2021년 2월 한국외대 우크라이나어과, 융복합 소프트웨어 전공으로 학과 수석 졸업
1. 우크라이나와 융복합소프트웨어 전공
왜 우크라이나어를 배우면서 융복합 소프트웨어를 전공하였을까?
한국외대 글로벌캠퍼스는 이중전공을 1학년 2학기 말에 선택한다. 당시 이중전공으로 고민했던 학과는 서울 캠퍼스 경제학과와 새로 신설된 융복합 소프트웨어학과였다. 경제학과는 다른 선배나 친구들이 이미 듣고 있었고 상경계열이라는 이점을 가지고 있던 반면 융복합 소프트웨어 학과는 첫 발을 딛고 있었다. 융복합 소프트웨어 전공 목표는 IT 소프트웨어 전문지식을 갖춘 지역 전문가이다. 현재까지도 우크라이나는 전 세계에서 소프트웨어 아웃소싱 20위 국가이고 IT 산업은 전체 수출비중에서 3위를 차지한다. 우크라이나 IT 전문가가 되기 위해 과에서 처음으로 융복합 소프트웨어를 이중전공으로 선택했다.
2. 우크라이나 전통 춤학회 "깔리나"
우크라이나어과는 전통 춤학회인 "깔리나"가 있다. 한국외대 세계민속문화축전이 9월 중순에 있으니 3월에 입학하자 마자 대회 준비를 시작한다. 세계민속문화축전 준비는 어려운 과정이다. 전체 안무 암기, 시간 부족, 반복 연습 그리고 가장 중요한 팀과의 호흡이다. 우크라이나 전통 춤이나 우크라이나에 관심이 없으면 목적성을 잃고 "왜 하는가?"에 대한 질문을 계속해서 하게 된다. 하지만 9월 공연에 서는 한 가지 목표를 향해 함께 서로 힘든 과정을 버티었다. 우크라이나 전통 춤학회가 단점이 명확한 반면에 인내심과 팀 협동심을 기른다는 장점이 있었다.
3. 한국외대 아너스 프로그램
아너스 프로그램은 전략지역전문가 양성을 목표로 한다. 6개월 어학연수, 4개월 인턴 활동으로 이루어진다. 우크라이나 르비브 국립 대학교에서 6개월간 예비학부에서 우크라이나어 기초, 회화, 문법 수업을 듣고 수료하였다. 그리고 르비브 지역 스타트업 지원 회사인 Startup Depot에서 인턴을 하였다. 코워킹 스페이스 IoT 서비스 지원 스타트업인 andcards에서 마케팅 홍보 지원으로 배정받아 일하였다. 예비학부를 다니고 있을 때, 인하대 지역 특화 청년 무역 전문가 양성 사업단인 gtep을 9월 20일 ~ 22일까지 도와 키이브 Intercharm Ucraine 2017을 성공적으로 마쳤다.
컴퓨터 관련 자격증은 정보처리기능사, SQL 개발자, 정보처리기사가 있다. 정보처리기능사는 학교 수업을 더 깊게 이해하고 기초 지식을 쌓기 위해 취득하였다. SQL 개발자는 멀티캠퍼스에서 빅데이터 활용을 위한 DB 관리를 수료하면서 데이터베이스를 더 공부하고자 취득하였고 다음 학기에 있던 데이터베이스 수업에서 A+를 맞았다. 정보처리기사는 기본 대학 교육 과정을 마무리하고 정리하기 위해 공부하였다.
5. 인공지능, 블록체인, 자연어 처리
대학 정규 과정을 마치고 생활코딩에서 머신러닝 야학 1기를 수료하였다. 이 과정은 처음에 파이썬으로만 진행되었다. 그래서 내가 사용하는 메인 언어인 javascript를 사용한 머신러닝 라이브러리 tensorflow.js를 사용해 내용을 옮겨 보기도 하였다. 한국외대 캠퍼스타운 취창업 연계 IT 교육 프로그램은 블록체인과 인공지능을 현재 분야 전문가분들에게서 수업을 듣는 과정이었다. 아이디어톤에서 "2030을 위한 블록체인 기반 여론조사 플랫폼"을 기획하였다.
와이즈넛 회사에서 SK NUGU Interactive NLU DM DB 구축 규칙 생성 아르바이트를 하였다. 자연어 처리에 대해서는 모르지만 NUGU와 같은 자연어 처리 인공지능이 문장 규칙, 단어와 동사 구분과 같이 많은 부분을 신경 써야 한다는 점을 알게 되었다. 리눅스를 기반으로 룰 규칙을 만들다 보니 리눅스에 익숙해지는 경험이었다.
6. 우크라이나 학습 사이트 프로젝트 실패
우크라이나 학습 사이트 개발 프로젝트를 1월에 시작하였고 결과적으로 실패하였다. 요구 분석, 모델링 작업, 디자인 패턴이 존재하지 않았고 그때그때 필요하면 고치는 막개발 수준이었다. 자세한 내용은 다른 블로그 글에 남기도록 한다.
7. 앞으로 계획
앞서 우크라이나 학습 사이트를 호기롭게 시작하였으나 모델링, 설계, 요구분석이 이루어지지 않고 실패하였다. 그래서 설계와 모델링 같은 소프트웨어 공학을 더 깊게 공부하기로 마음먹었다. 지금 블로그를 쓰는 시점에서 객체지향 프로그래밍(OOP), 도메인 주도 개발(DDD), 유비쿼터스 언어인 UML, 디자인 패턴 그리고 소프트웨어 공학 기초를 공부한다.
마이크로서비스 아키텍처(MSA)를 공부하면서 Docker, Kubernetes를 익히고 있다. 다음 프로젝트부터는 아마존 웹 서비스(AWS)를 적극 활용하도록 한다.
MongoDB 전문가가 되고자 한다. MongoDB는 국내 많은 기업에서 사용하고 있지 않지만 앞으로 사용하는 기업들이 늘어날 것이라고 생각된다. MongoDB 장점은 다른 블로그를 작성해야겠다.
메인 언어는 typescript와 golang이다. typescript를 활용한 Nestjs 서버 애플리케이션을 개발한다. golang은 아직 서툴지만 gRPC를 공부하면서 활용 방안을 생각해 본다.
코딩 테스트 준비는 메인 언어인 typescript, golang을 사용하여 풀이한다. 시간과 공간 복잡도에 무게감을 실어 효율적인 풀이를 하도록 한다.
BREAKING CHANGE: isolate scope bindings definition has changed and
the inject option for the directive controller injection was removed.
To migrate the code follow the example below:
Before:
scope: {
myAttr: 'attribute',
myBind: 'bind',
myExpression: 'expression',
myEval: 'evaluate',
myAccessor: 'accessor'
}
After:
scope: {
myAttr: '@',
myBind: '@',
myExpression: '&',
// myEval - usually not useful, but in cases where the expression is assignable, you can use '='
myAccessor: '=' // in directive's template change myAccessor() to myAccessor
}
The removed `inject` wasn't generaly useful for directives so there should be no code using it.
Closes #234
or
Closes #123, #245, #992
예시
feat($browser): onUrlChange event (popstate/hashchange/polling)
Added new event to $browser:
- forward popstate event if available
- forward hashchange event if popstate not available
- do polling when neither popstate nor hashchange available
Breaks $browser.onHashChange, which was removed (use onUrlChange instead)
fix($compile): couple of unit tests for IE9
Older IEs serialize html uppercased, but IE9 does not...
Would be better to expect case insensitive, unfortunately jasmine does
not allow to user regexps for throw expectations.
Closes #392
Breaks foo.bar api, foo.baz should be used instead