CI 소개

CI (Continuous Integration)는 애자일 개발 방법에 속한다. 통합 작업은 미루지 말고 개발 중에라도 꾸준히 해서 소프트웨어 복잡성을 제거하기 위해 사용한다.

애자일 프로젝트는 스프린트라는 짧은 주기로 설계, 개발, 테스트를 여러 번 실시한다. 스프린트 기간은 2주에서 1개월 정도이다. 스프린트 성과물이 요건을 만족하는지 확인된 프로그램이고 기간이 짧기 때문에 매일 개발, 통합, 테스트를 할 수 없다.

빌드와 테스트 자동화

CI는 빌드와 테스트 자동화에서 중요하다. 프로그램이 제대로 작동하고 있는지 피드백을 주는 통합 자동화 역할을 한다. 스프린트는 CI라는 짧고 빠른 피드백 주기로 구성되어 개발 속도와 품질을 높인다.

비용과 속도

CI는 비용과 시장 변화 속도에서 장점이 있다.

  • 비용

개발 속도가 느려지면 그만큼 비용이 발생한다. 버그 발생은 개발 속도를 굉장히 지연한다. 커밋 전이나 바로 후에 버그를 알아차리고 수정하면 다행이다. 하지만.. 일주일 뒤, 아니면 몇 달 뒤에 버그를 수정하려고 코드를 보면 막막해지고 수정이 정말 어렵다.

  • 속도

시장 변화 속도에 발맞출 수 있다는 것을 의미한다. 가독성, 유지 관리를 하면서 개발 주기가 짧아 시장에 민감하게 반응할 수 있다.

Reference

  • 성공으로 이끄는 팀 개발 실천 기술, 제이펍, 2016

'Docker, Kubernetes' 카테고리의 다른 글

쿠버네티스 deployment 업데이트 방법  (0) 2021.02.23
쿠버네티스 기본 명령어  (0) 2021.02.23
Docker 기본 명령어  (0) 2021.02.23
Commit Message 규칙  (0) 2020.12.27
브랜치 전략 패턴 git-flow, github-flow  (0) 2020.12.26

git-flow

중앙 repository에 메인 branch 2개(develop, master), 개발 멤버 리포지토리에 서포트 branch 3개(feature, release, hotfixes)가 있는 형태이다.

git-flow

  • 브랜치 설명
    • main branch
      1. master : 배포용 브랜치, 배포 시마다 태그 부여
      2. develop : 개발용 브랜치, 배포 전 최신 버전 유지
    • support branch
      1. feature : develop에서 생성, 기능 개발용
      2. release : develop에서 생성, 배포 준비용
      3. hotfix : 배포 제품에서 장애 발생 시 긴급 생성

git-flow 전략은 주기적인 배표 기간이 있는 대규모 프로젝트에 어울린다.


github-flow

  • git-flow 문제점
    • git 사용도 어려운데 브랜치 전략은 더 어렵다
    • GUI 도구를 사용할 때 git-flow 스크립트를 사용할 수 있어 브랜치 전략에 개발자가 익숙해야 한다
    • git-flow 스크립트와 브랜치 전략 모두 이해하기 어렵다

github-flow는 git-flow 보다 단순한 구조이다.

git-flow

  • master는 어떤 때에든 배포 가능하고 항상 최신 상태 유지
  • master에서 직접 브랜치 생성 (기능 추가, 버그 해결)
  • 생성된 브랜치와 커밋 메시지는 명확하게
  • 작성한 브랜치는 로컬 장치에서 커밋하고 원격 레포지토리에도 정기적으로 push 한다
  • 개발이 완료되면 master에 Pull Request 한다
  • Pull Request 검증하고 master에 merge 후 배포한다.

github-flow 주의점

  • master는 배포용이기 때문에 직접 수정하지 않는다
  • 작업 시작 시 브랜치를 생성한다
  • 작업 종료 후 master에 Pull Request 한다

github-flow 보다 좀 더 복잡하게

우크라이나 학습 사이트 개발 프로젝트는 github-flow에서 한 브랜치를 추가하려고 한다. git-flow 브랜치에서 main branch가 develop과 master로 나누어져 있다. develop는 개발/테스트 브랜치로 사용하고 master 브랜치는 배포할 때 사용한다. 그리고 master는 develop에서 머지할 때마다 태그를 바꾸는 식으로 하기로 한다.

어떻게 보면 gitlab-flow와 비슷하다

Reference

'Docker, Kubernetes' 카테고리의 다른 글

쿠버네티스 deployment 업데이트 방법  (0) 2021.02.23
쿠버네티스 기본 명령어  (0) 2021.02.23
Docker 기본 명령어  (0) 2021.02.23
Commit Message 규칙  (0) 2020.12.27
CI 지속적 통합  (0) 2020.12.27

익숙한 타입스크립트

한국외대 융복합소프트웨어를 전공하면서 다양한 프로그래밍 언어를 배웠다. 처음 배운 언어는 C 언어이다. 그리고 Python, Java 순으로 배웠다. 자료구조와 알고리즘을 C언어로 배운 만큼 타입을 정하는 게 익숙했다.

Javascript는 동아리 프로젝트를 하면서 처음 봤다. int, str 같은 타입 선언은 없고 var, let, const 가 전부인 언어였다. 처음에는 정말 당황스러웠지만 지금 거의 2년 넘게 써오면서 Javascript의 이런 황당한 타입 선언?은 오히려 편해졌다.

 

Express.js와 React.js를 작년부터 공부하고 있었다. Typescript는 웹 프로그래밍 강의로 유명한 노마드 코더의 유튜브 동영상인 '타입스크립트 + 리액트 조합이 꿀인 이유'를 보고 알게 되었다. Javascript와 비슷하지만, Typescript 타입 선언은 익숙하면서도 신선하게 느껴졌다. 바로 노마드 코더 니콜라스 선생님에게 'Typescript로 블록체인 만들기'를 수강하면서 관심을 키웠다.


타입스크립트가 그래서 뭔데?

타입스크립트 홈페이지는 타입 기능을 더한 자바스크립트로 타입스크립트를 소개한다.

TypeScript extends JavaScript by adding types

또 일반 자바스크립트로 컴파일되는 타입 기능이 있는 자바스크립트 상위 호환 언어로 보면 된다.

A typed superset of Javascript that compiles to plain Javascript

Typescript = Javascript + A type system 인 셈이다.

 

타입스크립트는 2012년 하반기 마이크로소프트에서 출시하고 지금까지 잘 관리하고 있는 언어이다.

Google에는 Golang이 있다

 

취준생 입장에서 보면 Java 공화국인 우리나라에서 Javascript는 웹 서비스에 국한되어 사용되고 있다. 서버 사이드에서 사용되는 Node.js는 애플리케이션 규모가 작은 경우나 스타트업에서 주로 사용된다. 자바스크립트의 동적타이핑과 약 타입(실행 도중 타입이 변하는 경우, weakly typed)은 프로젝트가 복잡해지거나 팀 규모가 커지면 문제가 발생한다. 작성자와 사용자 사이의 의사 소통 문제가 발생하기도 하고

"이거 타입이 문자열 아니었어?"

 

같은 이유로 유지보수 힘들어진다. 하지만 타입스크립트는 자바스크립트와 다르게 대규모 애플리케이션 개발을 위해 만들어지고 정적 타입 기능을 제공한다.


3 + [9] = "39" WTF!

자바스크립트에서 3 + [9] 는 문자열 '39' 다....

정말 말도 안 되는 상황이다.

타입스크립트는 타입 안정성(type safety)을 가지고 있다.

타입 안정성은 타입을 이용해 프로그램이 유효하지 않은 작업을 수행하지 않도록 방지한다.

  1. 1 + []
  2. '5' / 2

에서 자바스크립트는 "1", "2.5"로 계산한다.. 하지만 타입스크립트는 바로 에러가 발생했다고 에디터에서 빨간줄을 자비없이 그어버린다. 이런 에러 메시지는 확실하게 오류가 발생하는 경우를 줄여준다!

 

타입스크립트는 타입을 명시하거나 추론하는 방식을 선택해서 사용 할 수 있다!


/// 타입 명시
const add = (num1: number, num2: number): number => {
  const result: number = num1 + num2
  return result
}

/// 타입 추론
const add = (num1: number, num2: number) => {
  const result = num1 + num2
  return result
}

타입스크립트 VS 자바스크립트

  타입스크립트 자바스크립트
타입 정적 동적
자동 변환 O X
타입 확인 시기 실행 중 컴파일 중
에러 검출 시기 실행 중 컴파일 중

Typescript는 서버에서 어떻게 사용될까?

NestJS

A progressive Node.js framework for building efficient, reliable and scalable server-side applications.

Deno.js

Deno is a simple, modern and secure runtime for JavaScript and Typescript that use V8 and is built in Rust.


Reference

leetcode.com/problems/number-of-good-pairs/

 

Number of Good Pairs - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

javascript

/**
 * @param {number[]} nums
 * @return {number} 
 */
const numIdenticalPairs = (nums) => {
  const pairs = {}
  for (let i = 0; i < nums.length; i++) {
    pairs[nums[i]] ? pairs[nums[i]] += 1 : pairs[nums[i]] = 1
  }
  let numGoodPairs = 0
  const pairNums = Object.values(pairs)
  for (let i = 0; i < pairNums.length; i++) {
    numGoodPairs += (pairNums[i] * (pairNums[i] - 1)) / 2
  }
  return numGoodPairs
}

typescript

interface Pairs {
  [key: string]: number
}

const numIdenticalPairsTS = (nums: number[]): number => {
  const pairs: Pairs = {}
  for (let i = 0; i < nums.length; i++) {
    pairs[nums[i]] ? pairs[nums[i]] += 1 : pairs[nums[i]] = 1
  }
  let numGoodPairs: number = 0
  const pairNums = Object.keys(pairs)
  for (let i = 0; i < pairNums.length; i++) {
    numGoodPairs += (pairs[pairNums[i]] * (pairs[pairNums[i]] - 1)) / 2
  }
  return numGoodPairs
}

golang

func numIdenticalPairs(nums []int) int {
	goodPairs := 0
	pairs := make([]int, 101)
	for _, num := range nums {
		pairs[num]++
	}
	for _, pairsNum := range pairs {
		if pairsNum > 1 {
			goodPairs += pairsNum * (pairsNum - 1) / 2
		}
	}
	return goodPairs
}

'코딩 테스트 > LeetCode' 카테고리의 다른 글

Easy) 1108. Defanging an IP Address  (0) 2020.09.15
Easy) 771. Jewels and Stones  (0) 2020.09.15
Easy) Shuffle the Array  (0) 2020.09.13
Easy) Kids With the Greatest Number of Candies  (0) 2020.09.13
Easy. Running Sum of 1d Array  (0) 2020.07.02

 

leetcode.com/problems/defanging-an-ip-address/

 

Defanging an IP Address - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

javascript

/**
 * @param {string} address
 * @return {string}
 */
const defangIPaddr = (address) => {
  return address.replace(/\./g, '[.]')
  // address.split('.').join('[.]')
};

typescript

const defangIPaddrTS = (address: string): string => {
  return address.replace(/\./g, '[.]')
  // address.split('.').join('[.]')
};

golang

func defangIPaddr(address string) string {
	return strings.Replace(address, ".", "[.]", -1)
}

'코딩 테스트 > LeetCode' 카테고리의 다른 글

Easy) 1512. Number of Good Pairs  (0) 2020.09.15
Easy) 771. Jewels and Stones  (0) 2020.09.15
Easy) Shuffle the Array  (0) 2020.09.13
Easy) Kids With the Greatest Number of Candies  (0) 2020.09.13
Easy. Running Sum of 1d Array  (0) 2020.07.02

 

leetcode.com/problems/jewels-and-stones/

 

Jewels and Stones - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

javascript

/**
 * @param {string} J
 * @param {string} S
 * @return {number}
 */
const numJewelsInStones = function (J, S) {
  const stons = [...S]
  let numJewelsInStone = 0
  for (let i = 0; i < stons.length; i++) {
    if (J.includes(stons[i])) {
      numJewelsInStone++
    }
  }
  return numJewelsInStone
};

typescript

const numJewelsInStonesTS = function (J: string, S: string): number {
  const stons: string[] = [...S]
  let numJewelsInStone: number = 0
  for (let i = 0; i < stons.length; i++) {
    if (J.includes(stons[i])) {
      numJewelsInStone++
    }
  }
  return numJewelsInStone
};

golang

func numJewelsInStones(J string, S string) int {
	jewels := make(map[rune]bool)
	for _, jewel := range J {
		jewels[jewel] = true
	}
	numJewelsInStone := 0
	for _, stone := range S {
		if jewels[stone] {
			numJewelsInStone++
		}
	}
	return numJewelsInStone
}

/*
func numJewelsInStones(J string, S string) int {
	num := 0
	for _, jewel := range J {
		for _, stone := range S {
			if jewel == stone {
				num++
			}
		}
	}
	return num
}
*/

 

'코딩 테스트 > LeetCode' 카테고리의 다른 글

Easy) 1512. Number of Good Pairs  (0) 2020.09.15
Easy) 1108. Defanging an IP Address  (0) 2020.09.15
Easy) Shuffle the Array  (0) 2020.09.13
Easy) Kids With the Greatest Number of Candies  (0) 2020.09.13
Easy. Running Sum of 1d Array  (0) 2020.07.02

leetcode.com/problems/shuffle-the-array/

 

Shuffle the Array - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

nums 배열이 [1, 2, 3, 1, 2, 3] 이고

n 이 3이면

결과값은 [1, 1, 2, 2, 3, 3] 이 되어야 합니다.

 

그래서 

먼저 중간 인덱스 값은 mid를 구합니다.

그리고 배열이 나누어져 있다고 생각하고 

[1, 2, 3] [1, 2, 3]

새로운 빈 배열에 하나씩 넣습니다.

 

javascript

/**
 * @param {number[]} nums
 * @param {number} n
 * @return {number[]}
 */
const shuffle = (nums, n) => {
  if (nums.length <= 2) return nums
  const shuffled = []
  const mid = Math.floor(nums.length / 2)
  for (let i = 0; i < mid; i++) {
    shuffled.push(nums[i])
    shuffled.push(nums[i + n])
  }
  return shuffled
};

typescript

function shuffleTS(nums: number[], n: number): number[] {
  if (nums.length <= 2) return nums
  const shuffled: number[] = []
  const mid: number = Math.floor(nums.length / 2)
  for (let i = 0; i < mid; i++) {
    shuffled.push(nums[i])
    shuffled.push(nums[i + n])
  }
  return shuffled
};

golang

func shuffle(nums []int, n int) []int {
	if len(nums) <= 2 {
		return nums
	}
	result := make([]int, len(nums))
	mid := int(len(nums) / 2)

	i := 0
	j := 0
	for i < mid {
		result[j] = nums[i]
		result[j+1] = nums[i+n]
		i++
		j += 2
	}
	return result
}

https://leetcode.com/problems/kids-with-the-greatest-number-of-candies/

 

Kids With the Greatest Number of Candies - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

candies 양의 정수 배열은 각 index 별로 아이들이 가지고 있는 캔디 수를 의미합니다.

아이에게 extraCandies를 주면 아이들 중에 가장 많은 캔디를 가질 수 있는지 없는지를 판별하여

boolean 배열을 반환합니다.

 

javascript

/**
 * @param {number[]} candies
 * @param {number} extraCandies
 * @return {boolean[]}
 */
const kidsWithCandies = (candies, extraCandies) => {
  const greatestNum = Math.max(...candies)
  const result = candies.map(kid => kid + extraCandies >= greatestNum)
  return result
}

typescript

const kidsWithCandiesTS = (candies: number[], extraCandies: number): boolean[] => {
  const greatestNum: number = Math.max(...candies)
  const result: boolean[] = candies.map(kid => kid + extraCandies >= greatestNum)
  return result
}

golang

func kidsWithCandies(candies []int, extraCandies int) []bool {
	var result = make([]bool, len(candies))
	var greatestNum int = candies[0]
	for i := 0; i < len(candies); i++ {
		if greatestNum < candies[i] {
			greatestNum = candies[i]
		}
	}
	for index, kid := range candies {
		if kid+extraCandies >= greatestNum {
			result[index] = true
		}
	}
	return result
}

'코딩 테스트 > LeetCode' 카테고리의 다른 글

Easy) 1512. Number of Good Pairs  (0) 2020.09.15
Easy) 1108. Defanging an IP Address  (0) 2020.09.15
Easy) 771. Jewels and Stones  (0) 2020.09.15
Easy) Shuffle the Array  (0) 2020.09.13
Easy. Running Sum of 1d Array  (0) 2020.07.02

+ Recent posts