λΆ„μ‚° μ‹œμŠ€ν…œμ˜ 컴파일 κ°€λŠ₯ν•œ ꡬ성

이 κ²Œμ‹œλ¬Όμ—μ„œ μš°λ¦¬λŠ” λΆ„μ‚° μ‹œμŠ€ν…œ ꡬ성을 μ²˜λ¦¬ν•˜λŠ” ν₯미둜운 방법을 κ³΅μœ ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.
ꡬ성은 μœ ν˜•μ΄ μ•ˆμ „ν•œ λ°©μ‹μœΌλ‘œ Scala μ–Έμ–΄λ‘œ 직접 ν‘œν˜„λ©λ‹ˆλ‹€. κ΅¬ν˜„ μ˜ˆκ°€ μžμ„Ένžˆ μ„€λͺ…λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 전체 개발 ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•œ 영ν–₯을 ν¬ν•¨ν•˜μ—¬ μ œμ•ˆμ˜ λ‹€μ–‘ν•œ 츑면이 λ…Όμ˜λ©λ‹ˆλ‹€.

λΆ„μ‚° μ‹œμŠ€ν…œμ˜ 컴파일 κ°€λŠ₯ν•œ ꡬ성

(λŸ¬μ‹œμ•„μ–΄λ‘œ)

κ°œμš”

κ°•λ ₯ν•œ λΆ„μ‚° μ‹œμŠ€ν…œμ„ κ΅¬μΆ•ν•˜λ €λ©΄ λͺ¨λ“  λ…Έλ“œμ—μ„œ μ •ν™•ν•˜κ³  μΌκ΄€λœ ꡬ성을 μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. 일반적인 μ†”λ£¨μ…˜μ€ ν…μŠ€νŠΈ 배포 μ„€λͺ…(terraform, ansible λ“±)κ³Ό μžλ™μœΌλ‘œ μƒμ„±λœ ꡬ성 파일(μ’…μ’… 각 λ…Έλ“œ/μ—­ν•  μ „μš©)을 μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. λ˜ν•œ 각 톡신 λ…Έλ“œμ—μ„œ λ™μΌν•œ λ²„μ „μ˜ λ™μΌν•œ ν”„λ‘œν† μ½œμ„ μ‚¬μš©ν•˜κ³  싢을 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€(그렇지 μ•ŠμœΌλ©΄ λΉ„ν˜Έν™˜μ„± λ¬Έμ œκ°€ λ°œμƒν•˜κ²Œ λ©λ‹ˆλ‹€). JVM μ„Έκ³„μ—μ„œ μ΄λŠ” μ΅œμ†Œν•œ λ©”μ‹œμ§• λΌμ΄λΈŒλŸ¬λ¦¬κ°€ λͺ¨λ“  톡신 λ…Έλ“œμ—μ„œ λ™μΌν•œ 버전이어야 함을 μ˜λ―Έν•©λ‹ˆλ‹€.

μ‹œμŠ€ν…œ ν…ŒμŠ€νŠΈλŠ” μ–΄λ–»μŠ΅λ‹ˆκΉŒ? λ¬Όλ‘  톡합 ν…ŒμŠ€νŠΈμ— μ•žμ„œ λͺ¨λ“  ꡬ성 μš”μ†Œμ— λŒ€ν•œ λ‹¨μœ„ ν…ŒμŠ€νŠΈλ₯Ό 거쳐야 ν•©λ‹ˆλ‹€. λŸ°νƒ€μž„ μ‹œ ν…ŒμŠ€νŠΈ κ²°κ³Όλ₯Ό μΆ”μ •ν•˜λ €λ©΄ λͺ¨λ“  라이브러리의 버전이 λŸ°νƒ€μž„κ³Ό ν…ŒμŠ€νŠΈ ν™˜κ²½ λͺ¨λ‘μ—μ„œ λ™μΌν•˜κ²Œ μœ μ§€λ˜λŠ”μ§€ 확인해야 ν•©λ‹ˆλ‹€.

톡합 ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•  λ•Œ λͺ¨λ“  λ…Έλ“œμ—μ„œ λ™μΌν•œ 클래슀 경둜λ₯Ό κ°–λŠ” 것이 훨씬 μ‰¬μš΄ κ²½μš°κ°€ λ§ŽμŠ΅λ‹ˆλ‹€. 배포 μ‹œ λ™μΌν•œ 클래슀 κ²½λ‘œκ°€ μ‚¬μš©λ˜λŠ”μ§€ ν™•μΈν•˜λ©΄ λ©λ‹ˆλ‹€. (λ‹€λ₯Έ λ…Έλ“œμ—μ„œ λ‹€λ₯Έ 클래슀 경둜λ₯Ό μ‚¬μš©ν•  수 μžˆμ§€λ§Œ 이 ꡬ성을 ν‘œν˜„ν•˜κ³  μ˜¬λ°”λ₯΄κ²Œ λ°°ν¬ν•˜λŠ” 것이 더 μ–΄λ ΅μŠ΅λ‹ˆλ‹€.) λ”°λΌμ„œ μž‘μ—…μ„ λ‹¨μˆœν•˜κ²Œ μœ μ§€ν•˜κΈ° μœ„ν•΄ λͺ¨λ“  λ…Έλ“œμ—μ„œ λ™μΌν•œ 클래슀 경둜만 κ³ λ €ν•©λ‹ˆλ‹€.

ꡬ성은 μ†Œν”„νŠΈμ›¨μ–΄μ™€ ν•¨κ»˜ λ°œμ „ν•˜λŠ” κ²½ν–₯이 μžˆμŠ΅λ‹ˆλ‹€. μš°λ¦¬λŠ” 일반적으둜 λ‹€μ–‘ν•œ 버전을 μ‹λ³„ν•˜κΈ° μœ„ν•΄ 버전을 μ‚¬μš©ν•©λ‹ˆλ‹€.
μ†Œν”„νŠΈμ›¨μ–΄ μ§„ν™”μ˜ 단계. 버전 κ΄€λ¦¬μ—μ„œ ꡬ성을 닀루고 일뢀 λ ˆμ΄λΈ”μ„ μ‚¬μš©ν•˜μ—¬ λ‹€μ–‘ν•œ ꡬ성을 μ‹λ³„ν•˜λŠ” 것이 ν•©λ¦¬μ μœΌλ‘œ λ³΄μž…λ‹ˆλ‹€. ν”„λ‘œλ•μ…˜μ— ꡬ성이 ν•˜λ‚˜λ§Œ μžˆλŠ” 경우 단일 버전을 μ‹λ³„μžλ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ•Œλ‘œλŠ” μ—¬λŸ¬ ν”„λ‘œλ•μ…˜ ν™˜κ²½μ΄ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. 그리고 각 ν™˜κ²½λ§ˆλ‹€ λ³„λ„μ˜ ꡬ성 λΆ„κΈ°κ°€ ν•„μš”ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ λ‹€μ–‘ν•œ ꡬ성을 κ³ μœ ν•˜κ²Œ μ‹λ³„ν•˜κΈ° μœ„ν•΄ ꡬ성에 λΆ„κΈ° 및 버전 λ ˆμ΄λΈ”μ΄ 지정될 수 μžˆμŠ΅λ‹ˆλ‹€. 각 λΆ„κΈ° λ ˆμ΄λΈ” 및 버전은 λΆ„μ‚° λ…Έλ“œ, 포트, μ™ΈλΆ€ λ¦¬μ†ŒμŠ€, 각 λ…Έλ“œμ˜ 클래슀 경둜 라이브러리 λ²„μ „μ˜ 단일 쑰합에 ν•΄λ‹Ήν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œλŠ” λ‹€λ₯Έ μ•„ν‹°νŒ©νŠΈμ™€ λ™μΌν•œ λ°©μ‹μœΌλ‘œ 단일 λΆ„κΈ°λ§Œ 닀루고 ꡬ성을 1.2.3개 ꡬ성 μš”μ†Œ XNUMXμ§„μˆ˜ 버전(XNUMX)으둜 μ‹λ³„ν•©λ‹ˆλ‹€.

μ΅œμ‹  ν™˜κ²½μ—μ„œλŠ” ꡬ성 파일이 더 이상 μˆ˜λ™μœΌλ‘œ μˆ˜μ •λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 일반적으둜 μš°λ¦¬λŠ”
배포 μ‹œ ꡬ성 파일 및 μ ˆλŒ€ λ§Œμ§€μ§€ λ§ˆμ„Έμš” λ‚˜μ€‘μ—. κ·Έλ ‡λ‹€λ©΄ ꡬ성 νŒŒμΌμ— μ™œ μ—¬μ „νžˆ ν…μŠ€νŠΈ ν˜•μ‹μ„ μ‚¬μš©ν•˜λŠ”μ§€ μ§ˆλ¬Έν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ‹€ν–‰ κ°€λŠ₯ν•œ μ˜΅μ…˜μ€ ꡬ성을 컴파일 λ‹¨μœ„ 내에 λ°°μΉ˜ν•˜κ³  컴파일 μ‹œκ°„ ꡬ성 μœ νš¨μ„± κ²€μ‚¬μ˜ 이점을 ν™œμš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

이번 ν¬μŠ€νŒ…μ—μ„œλŠ” 컴파일된 μ•„ν‹°νŒ©νŠΈμ— ꡬ성을 μœ μ§€ν•˜λŠ” 아이디어λ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

컴파일 κ°€λŠ₯ν•œ ꡬ성

이 μ„Ήμ…˜μ—μ„œλŠ” 정적 κ΅¬μ„±μ˜ 예λ₯Ό μ„€λͺ…ν•©λ‹ˆλ‹€. 두 가지 κ°„λ‹¨ν•œ μ„œλΉ„μŠ€μΈ 에코 μ„œλΉ„μŠ€μ™€ 에코 μ„œλΉ„μŠ€ ν΄λΌμ΄μ–ΈνŠΈκ°€ ꡬ성 및 κ΅¬ν˜„λ©λ‹ˆλ‹€. 그런 λ‹€μŒ 두 μ„œλΉ„μŠ€κ°€ λͺ¨λ‘ ν¬ν•¨λœ 두 개의 μ„œλ‘œ λ‹€λ₯Έ λΆ„μ‚° μ‹œμŠ€ν…œμ΄ μΈμŠ€ν„΄μŠ€ν™”λ©λ‹ˆλ‹€. ν•˜λ‚˜λŠ” 단일 λ…Έλ“œ κ΅¬μ„±μš©μ΄κ³  λ‹€λ₯Έ ν•˜λ‚˜λŠ” XNUMX개 λ…Έλ“œ κ΅¬μ„±μš©μž…λ‹ˆλ‹€.

일반적인 λΆ„μ‚° μ‹œμŠ€ν…œμ€ λͺ‡ 개의 λ…Έλ“œλ‘œ κ΅¬μ„±λ©λ‹ˆλ‹€. λ…Έλ“œλŠ” λ‹€μŒκ³Ό 같은 μœ ν˜•μ„ μ‚¬μš©ν•˜μ—¬ 식별할 수 μžˆμŠ΅λ‹ˆλ‹€.

sealed trait NodeId
case object Backend extends NodeId
case object Frontend extends NodeId

λ˜λŠ”

case class NodeId(hostName: String)

심지어

object Singleton
type NodeId = Singleton.type

μ΄λŸ¬ν•œ λ…Έλ“œλŠ” λ‹€μ–‘ν•œ 역할을 μˆ˜ν–‰ν•˜κ³  일뢀 μ„œλΉ„μŠ€λ₯Ό μ‹€ν–‰ν•˜λ©° TCP/HTTP 연결을 톡해 λ‹€λ₯Έ λ…Έλ“œμ™€ 톡신할 수 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

TCP μ—°κ²°μ˜ 경우 μ΅œμ†Œν•œ 포트 λ²ˆν˜Έκ°€ ν•„μš”ν•©λ‹ˆλ‹€. λ˜ν•œ ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„κ°€ λ™μΌν•œ ν”„λ‘œν† μ½œμ„ μ‚¬μš©ν•˜λŠ”μ§€ ν™•μΈν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€. λ…Έλ“œ κ°„μ˜ 연결을 λͺ¨λΈλ§ν•˜κΈ° μœ„ν•΄ λ‹€μŒ 클래슀λ₯Ό μ„ μ–Έν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

case class TcpEndPoint[Protocol](node: NodeId, port: Port[Protocol])

어디에 Port κ·Έλƒ₯ Int ν—ˆμš©λœ λ²”μœ„ λ‚΄μ—μ„œ:

type PortNumber = Refined[Int, Closed[_0, W.`65535`.T]]

μ„Έλ ¨λœ μœ ν˜•

λ§Œλ‚˜λ‹€ μ„Έλ ¨λœ λ„μ„œκ΄€. 즉, λ‹€λ₯Έ μœ ν˜•μ— 컴파일 μ‹œκ°„ μ œμ•½ 쑰건을 μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 이 경우 Int 포트 번호λ₯Ό λ‚˜νƒ€λ‚Ό 수 μžˆλŠ” 16λΉ„νŠΈ κ°’λ§Œ ν—ˆμš©λ©λ‹ˆλ‹€. 이 ꡬ성 μ ‘κ·Ό λ°©μ‹μ—λŠ” 이 라이브러리λ₯Ό μ‚¬μš©ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. κ·Έλƒ₯ λ„ˆλ¬΄ 잘 μ–΄μšΈλ¦¬λŠ” 것 κ°™μ•„μš”.

HTTP(REST)의 경우 μ„œλΉ„μŠ€ κ²½λ‘œκ°€ ν•„μš”ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

type UrlPathPrefix = Refined[String, MatchesRegex[W.`"[a-zA-Z_0-9/]*"`.T]]
case class PortWithPrefix[Protocol](portNumber: PortNumber, pathPrefix: UrlPathPrefix)

νŒ¬ν…€ν˜•

컴파일 쀑에 ν”„λ‘œν† μ½œμ„ μ‹λ³„ν•˜κΈ° μœ„ν•΄ μš°λ¦¬λŠ” μœ ν˜• 인수λ₯Ό μ„ μ–Έν•˜λŠ” Scala κΈ°λŠ₯을 μ‚¬μš©ν•©λ‹ˆλ‹€. Protocol μˆ˜μ—…μ—μ„œλŠ” μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” κ²ƒμž…λ‹ˆλ‹€. μ†Œμœ„ λ§ν•˜λŠ”κ±°λ‹€ νŒ¬ν…€ μœ ν˜•. λŸ°νƒ€μž„μ—λŠ” ν”„λ‘œν† μ½œ μ‹λ³„μž μΈμŠ€ν„΄μŠ€κ°€ 거의 ν•„μš”ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ μ €μž₯ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ»΄νŒŒμΌν•˜λŠ” λ™μ•ˆ 이 νŒ¬ν…€ μœ ν˜•μ€ 좔가적인 μœ ν˜• μ•ˆμ „μ„±μ„ μ œκ³΅ν•©λ‹ˆλ‹€. 잘λͺ»λœ ν”„λ‘œν† μ½œλ‘œ 포트λ₯Ό 전달할 수 μ—†μŠ΅λ‹ˆλ‹€.

κ°€μž₯ 널리 μ‚¬μš©λ˜λŠ” ν”„λ‘œν† μ½œ 쀑 ν•˜λ‚˜λŠ” Json 직렬화λ₯Ό μ‚¬μš©ν•˜λŠ” REST APIμž…λ‹ˆλ‹€.

sealed trait JsonHttpRestProtocol[RequestMessage, ResponseMessage]

어디에 RequestMessage ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ²„μ— 보낼 수 μžˆλŠ” κΈ°λ³Έ λ©”μ‹œμ§€ μœ ν˜•μž…λ‹ˆλ‹€. ResponseMessage μ„œλ²„λ‘œλΆ€ν„°μ˜ 응닡 λ©”μ‹œμ§€μž…λ‹ˆλ‹€. λ¬Όλ‘  μ›ν•˜λŠ” μ •λ°€λ„λ‘œ 톡신 ν”„λ‘œν† μ½œμ„ μ§€μ •ν•˜λŠ” λ‹€λ₯Έ ν”„λ‘œν† μ½œ μ„€λͺ…을 λ§Œλ“€ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

이 κ²Œμ‹œλ¬Όμ˜ λͺ©μ μ„ μœ„ν•΄ μš°λ¦¬λŠ” ν”„λ‘œν† μ½œμ˜ 더 κ°„λ‹¨ν•œ 버전을 μ‚¬μš©ν•  κ²ƒμž…λ‹ˆλ‹€:

sealed trait SimpleHttpGetRest[RequestMessage, ResponseMessage]

이 ν”„λ‘œν† μ½œμ—μ„œλŠ” μš”μ²­ λ©”μ‹œμ§€κ°€ URL에 μΆ”κ°€λ˜κ³  응닡 λ©”μ‹œμ§€κ°€ 일반 λ¬Έμžμ—΄λ‘œ λ°˜ν™˜λ©λ‹ˆλ‹€.

μ„œλΉ„μŠ€ ꡬ성은 μ„œλΉ„μŠ€ 이름, 포트 λͺ¨μŒ 및 일뢀 μ’…μ†μ„±μœΌλ‘œ μ„€λͺ…될 수 μžˆμŠ΅λ‹ˆλ‹€. Scalaμ—μ„œ μ΄λŸ¬ν•œ λͺ¨λ“  μš”μ†Œλ₯Ό β€‹β€‹ν‘œν˜„ν•˜λŠ” λ°©λ²•μ—λŠ” λͺ‡ 가지 방법이 μžˆμŠ΅λ‹ˆλ‹€(예: HList, λŒ€μˆ˜ 데이터 μœ ν˜•). 이 κ²Œμ‹œλ¬Όμ˜ λͺ©μ μ„ μœ„ν•΄ μš°λ¦¬λŠ” 케이크 νŒ¨ν„΄μ„ μ‚¬μš©ν•˜κ³  κ²°ν•© κ°€λŠ₯ν•œ 쑰각(λͺ¨λ“ˆ)을 νŠΉμ„±μœΌλ‘œ λ‚˜νƒ€λ‚Ό κ²ƒμž…λ‹ˆλ‹€. (케이크 νŒ¨ν„΄μ€ 이 컴파일 κ°€λŠ₯ν•œ ꡬ성 μ ‘κ·Ό λ°©μ‹μ˜ μš”κ΅¬ 사항이 μ•„λ‹™λ‹ˆλ‹€. μ΄λŠ” μ•„μ΄λ””μ–΄μ˜ κ°€λŠ₯ν•œ κ΅¬ν˜„ 쀑 ν•˜λ‚˜μΌ λΏμž…λ‹ˆλ‹€.)

케이크 νŒ¨ν„΄μ„ λ‹€λ₯Έ λ…Έλ“œμ˜ 끝점으둜 μ‚¬μš©ν•˜μ—¬ 쒅속성을 ν‘œν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  type EchoProtocol[A] = SimpleHttpGetRest[A, A]

  trait EchoConfig[A] extends ServiceConfig {
    def portNumber: PortNumber = 8081
    def echoPort: PortWithPrefix[EchoProtocol[A]] = PortWithPrefix[EchoProtocol[A]](portNumber, "echo")
    def echoService: HttpSimpleGetEndPoint[NodeId, EchoProtocol[A]] = providedSimpleService(echoPort)
  }

에코 μ„œλΉ„μŠ€μ—λŠ” 포트만 κ΅¬μ„±ν•˜λ©΄ λ©λ‹ˆλ‹€. 그리고 이 ν¬νŠΈκ°€ 에코 ν”„λ‘œν† μ½œμ„ 지원함을 μ„ μ–Έν•©λ‹ˆλ‹€. νŠΉμ„±μ΄ 좔상 λ©”μ„œλ“œ 선언을 ν—ˆμš©ν•˜κΈ° λ•Œλ¬Έμ— μ§€κΈˆμ€ νŠΉμ • 포트λ₯Ό 지정할 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. 좔상 λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 경우 μ»΄νŒŒμΌλŸ¬λŠ” ꡬ성 μΈμŠ€ν„΄μŠ€μ—μ„œ κ΅¬ν˜„μ„ μš”κ΅¬ν•©λ‹ˆλ‹€. μ—¬κΈ°μ„œλŠ” κ΅¬ν˜„μ„ μ œκ³΅ν–ˆμŠ΅λ‹ˆλ‹€(8081) ꡬ체적인 κ΅¬μ„±μ—μ„œ κ±΄λ„ˆλ›°λ©΄ κΈ°λ³Έκ°’μœΌλ‘œ μ‚¬μš©λ©λ‹ˆλ‹€.

에코 μ„œλΉ„μŠ€ ν΄λΌμ΄μ–ΈνŠΈ κ΅¬μ„±μ—μ„œ 쒅속성을 μ„ μ–Έν•  수 μžˆμŠ΅λ‹ˆλ‹€.

  trait EchoClientConfig[A] {
    def testMessage: String = "test"
    def pollInterval: FiniteDuration
    def echoServiceDependency: HttpSimpleGetEndPoint[_, EchoProtocol[A]]
  }

쒅속성은 λ‹€μŒκ³Ό 같은 μœ ν˜•μ„ κ°€μ§‘λ‹ˆλ‹€. echoService. 특히 λ™μΌν•œ ν”„λ‘œν† μ½œμ΄ ν•„μš”ν•©λ‹ˆλ‹€. λ”°λΌμ„œ 이 두 가지 쒅속성을 μ—°κ²°ν•˜λ©΄ μ˜¬λ°”λ₯΄κ²Œ μž‘λ™ν•  것이라고 ν™•μ‹ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ„œλΉ„μŠ€ κ΅¬ν˜„

μ„œλΉ„μŠ€λ₯Ό μ‹œμž‘ν•˜κ³  μ •μƒμ μœΌλ‘œ μ’…λ£Œν•˜λ €λ©΄ κΈ°λŠ₯이 ν•„μš”ν•©λ‹ˆλ‹€. (μ„œλΉ„μŠ€λ₯Ό μ’…λ£Œν•˜λŠ” κΈ°λŠ₯은 ν…ŒμŠ€νŠΈμ— 맀우 μ€‘μš”ν•©λ‹ˆλ‹€.) λ˜ν•œ 주어진 ꡬ성에 λŒ€ν•΄ μ΄λŸ¬ν•œ κΈ°λŠ₯을 μ§€μ •ν•˜λŠ” λͺ‡ 가지 μ˜΅μ…˜μ΄ μžˆμŠ΅λ‹ˆλ‹€(예λ₯Ό λ“€μ–΄ μœ ν˜• 클래슀λ₯Ό μ‚¬μš©ν•  수 있음). 이 κ²Œμ‹œλ¬Όμ—μ„œλŠ” 케이크 νŒ¨ν„΄μ„ λ‹€μ‹œ μ‚¬μš©ν•˜κ² μŠ΅λ‹ˆλ‹€. λ‹€μŒμ„ μ‚¬μš©ν•˜μ—¬ μ„œλΉ„μŠ€λ₯Ό ν‘œν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. cats.Resource 이미 λΈŒλΌμΌ€νŒ… 및 λ¦¬μ†ŒμŠ€ 릴리슀λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€. λ¦¬μ†ŒμŠ€λ₯Ό μ–»μœΌλ €λ©΄ ꡬ성과 일뢀 λŸ°νƒ€μž„ μ»¨ν…μŠ€νŠΈλ₯Ό μ œκ³΅ν•΄μ•Ό ν•©λ‹ˆλ‹€. λ”°λΌμ„œ μ„œλΉ„μŠ€ μ‹œμž‘ κΈ°λŠ₯은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  type ResourceReader[F[_], Config, A] = Reader[Config, Resource[F, A]]

  trait ServiceImpl[F[_]] {
    type Config
    def resource(
      implicit
      resolver: AddressResolver[F],
      timer: Timer[F],
      contextShift: ContextShift[F],
      ec: ExecutionContext,
      applicative: Applicative[F]
    ): ResourceReader[F, Config, Unit]
  }

어디에

  • Config β€” 이 μ„œλΉ„μŠ€ μ‹œμž‘κΈ°μ— ν•„μš”ν•œ ꡬ성 μœ ν˜•
  • AddressResolver β€” λ‹€λ₯Έ λ…Έλ“œμ˜ μ‹€μ œ μ£Όμ†Œλ₯Ό 얻을 수 μžˆλŠ” κΈ°λŠ₯이 μžˆλŠ” λŸ°νƒ€μž„ 개체(μžμ„Έν•œ λ‚΄μš©μ€ 계속 μ½μœΌμ„Έμš”).

λ‹€λ₯Έ μœ ν˜•μ€ λ‹€μŒμ—μ„œ μœ λž˜ν•©λ‹ˆλ‹€. cats:

  • F[_] β€” 효과 μœ ν˜•(κ°€μž₯ κ°„λ‹¨ν•œ 경우 F[A] κ·Έλƒ₯ 될 μˆ˜μžˆλ‹€ () => A. 이 κ²Œμ‹œλ¬Όμ—μ„œ μš°λ¦¬λŠ” cats.IO.)
  • Reader[A,B] β€” ν•¨μˆ˜μ˜ λ™μ˜μ–΄μž…λ‹ˆλ‹€. A => B
  • cats.Resource β€” νšλ“ 및 ν•΄μ œ 방법이 μžˆμŠ΅λ‹ˆλ‹€.
  • Timer β€” 수면/μ‹œκ°„ μΈ‘μ • κ°€λŠ₯
  • ContextShift - μ•„λ‚ λ‘œκ·Έ ExecutionContext
  • Applicative β€” μ‹€μ œ ν•¨μˆ˜ 래퍼(거의 λͺ¨λ‚˜λ“œ)(κ²°κ΅­ λ‹€λ₯Έ κ²ƒμœΌλ‘œ λŒ€μ²΄ν•  수 있음)

이 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ λͺ‡ 가지 μ„œλΉ„μŠ€λ₯Ό κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 아무것도 ν•˜μ§€ μ•ŠλŠ” μ„œλΉ„μŠ€λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  trait ZeroServiceImpl[F[_]] extends ServiceImpl[F] {
    type Config <: Any
    def resource(...): ResourceReader[F, Config, Unit] =
      Reader(_ => Resource.pure[F, Unit](()))
  }

(μ°Έμ‘° μ†ŒμŠ€ μ½”λ“œ λ‹€λ₯Έ μ„œλΉ„μŠ€ κ΅¬ν˜„μ„ μœ„ν•œ β€” 에코 μ„œλΉ„μŠ€,
에코 ν΄λΌμ΄μ–ΈνŠΈ 및 수λͺ… 컨트둀러.)

λ…Έλ“œλŠ” λͺ‡ 가지 μ„œλΉ„μŠ€λ₯Ό μ‹€ν–‰ν•˜λŠ” 단일 κ°μ²΄μž…λ‹ˆλ‹€(λ¦¬μ†ŒμŠ€ 체인 μ‹œμž‘μ€ 케이크 νŒ¨ν„΄μ— μ˜ν•΄ ν™œμ„±ν™”λ©λ‹ˆλ‹€).

object SingleNodeImpl extends ZeroServiceImpl[IO]
  with EchoServiceService
  with EchoClientService
  with FiniteDurationLifecycleServiceImpl
{
  type Config = EchoConfig[String] with EchoClientConfig[String] with FiniteDurationLifecycleConfig
}

λ…Έλ“œμ—μ„œλŠ” 이 λ…Έλ“œμ— ν•„μš”ν•œ μ •ν™•ν•œ ꡬ성 μœ ν˜•μ„ μ§€μ •ν•©λ‹ˆλ‹€. μ»΄νŒŒμΌλŸ¬λŠ” μš°λ¦¬κ°€ λΆˆμΆ©λΆ„ν•œ μœ ν˜•μœΌλ‘œ 객체(케이크)λ₯Ό λ§Œλ“œλŠ” 것을 ν—ˆμš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. Config μœ ν˜•. λ˜ν•œ μ™„μ „ν•œ ꡬ성을 μ œκ³΅ν•˜μ§€ μ•ŠμœΌλ©΄ λ…Έλ“œλ₯Ό μ‹œμž‘ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

λ…Έλ“œ μ£Όμ†Œ 확인

연결을 μ„€μ •ν•˜λ €λ©΄ 각 λ…Έλ“œμ— λŒ€ν•œ μ‹€μ œ 호슀트 μ£Όμ†Œκ°€ ν•„μš”ν•©λ‹ˆλ‹€. κ΅¬μ„±μ˜ λ‹€λ₯Έ 뢀뢄보닀 λ‚˜μ€‘μ— μ•Œλ €μ§ˆ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ λ…Έλ“œ ID와 μ‹€μ œ μ£Όμ†Œ κ°„μ˜ 맀핑을 μ œκ³΅ν•˜λŠ” 방법이 ν•„μš”ν•©λ‹ˆλ‹€. 이 맀핑은 λ‹€μŒκ³Ό 같은 ν•¨μˆ˜μž…λ‹ˆλ‹€.

case class NodeAddress[NodeId](host: Uri.Host)
trait AddressResolver[F[_]] {
  def resolve[NodeId](nodeId: NodeId): F[NodeAddress[NodeId]]
}

μ΄λŸ¬ν•œ κΈ°λŠ₯을 κ΅¬ν˜„ν•˜λŠ” λ°©λ²•μ—λŠ” λͺ‡ 가지가 μžˆμŠ΅λ‹ˆλ‹€.

  1. 배포 전에 μ‹€μ œ μ£Όμ†Œλ₯Ό μ•Œκ³  있으면 λ…Έλ“œ 호슀트 μΈμŠ€ν„΄μŠ€ν™” 쀑에 μ‹€μ œ μ£Όμ†Œλ‘œ Scala μ½”λ“œλ₯Ό μƒμ„±ν•˜κ³  λ‚˜μ€‘μ— λΉŒλ“œλ₯Ό μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€(컴파일 μ‹œκ°„ 확인을 μˆ˜ν–‰ν•œ λ‹€μŒ 톡합 ν…ŒμŠ€νŠΈ 도ꡬ λͺ¨μŒ μ‹€ν–‰). 이 경우 맀핑 κΈ°λŠ₯은 μ •μ μœΌλ‘œ μ•Œλ €μ Έ 있으며 λ‹€μŒκ³Ό 같이 λ‹¨μˆœν™”λ  수 μžˆμŠ΅λ‹ˆλ‹€. Map[NodeId, NodeAddress].
  2. λ•Œλ‘œλŠ” λ…Έλ“œκ°€ μ‹€μ œλ‘œ μ‹œμž‘λ  λ•Œ λ‚˜μ€‘μ— μ‹€μ œ μ£Όμ†Œλ₯Ό μ–»κ±°λ‚˜ 아직 μ‹œμž‘λ˜μ§€ μ•Šμ€ λ…Έλ“œμ˜ μ£Όμ†Œκ°€ μ—†λŠ” κ²½μš°λ„ μžˆμŠ΅λ‹ˆλ‹€. 이 경우 λ‹€λ₯Έ λͺ¨λ“  λ…Έλ“œλ³΄λ‹€ λ¨Όμ € μ‹œμž‘λ˜λŠ” 검색 μ„œλΉ„μŠ€κ°€ μžˆμ„ 수 있으며 각 λ…Έλ“œλŠ” ν•΄λ‹Ή μ„œλΉ„μŠ€μ—μ„œ μžμ‹ μ˜ μ£Όμ†Œλ₯Ό μ•Œλ¦¬κ³  쒅속성을 ꡬ독할 수 μžˆμŠ΅λ‹ˆλ‹€.
  3. μˆ˜μ •ν•  수 μžˆλ‹€λ©΄ /etc/hosts, 사전 μ •μ˜λœ 호슀트 이름(예: my-project-main-node 및 echo-backend) 배포 μ‹œ 이 이름을 IP μ£Όμ†Œμ™€ μ—°κ²°ν•˜λ©΄ λ©λ‹ˆλ‹€.

이 κ²Œμ‹œλ¬Όμ—μ„œλŠ” μ΄λŸ¬ν•œ 사둀λ₯Ό 더 μžμ„Ένžˆ 닀루지 μ•ŠμŠ΅λ‹ˆλ‹€. μ‹€μ œλ‘œ 우리의 μž₯λ‚œκ° μ˜ˆμ—μ„œλŠ” λͺ¨λ“  λ…Έλ“œκ°€ λ™μΌν•œ IP μ£Όμ†Œλ₯Ό κ°–μŠ΅λ‹ˆλ‹€. 127.0.0.1.

이 κ²Œμ‹œλ¬Όμ—μ„œλŠ” 두 가지 λΆ„μ‚° μ‹œμŠ€ν…œ λ ˆμ΄μ•„μ›ƒμ„ κ³ λ €ν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€.

  1. λͺ¨λ“  μ„œλΉ„μŠ€κ°€ 단일 λ…Έλ“œμ— λ°°μΉ˜λ˜λŠ” 단일 λ…Έλ“œ λ ˆμ΄μ•„μ›ƒ.
  2. μ„œλΉ„μŠ€μ™€ ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ‘œ λ‹€λ₯Έ λ…Έλ“œμ— μžˆλŠ” 두 개의 λ…Έλ“œ λ ˆμ΄μ•„μ›ƒ.

에 λŒ€ν•œ ꡬ성 단일 λ…Έλ“œ λ ˆμ΄μ•„μ›ƒμ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

단일 λ…Έλ“œ ꡬ성

object SingleNodeConfig extends EchoConfig[String] 
  with EchoClientConfig[String] with FiniteDurationLifecycleConfig
{
  case object Singleton // identifier of the single node 
  // configuration of server
  type NodeId = Singleton.type
  def nodeId = Singleton

  /** Type safe service port specification. */
  override def portNumber: PortNumber = 8088

  // configuration of client

  /** We'll use the service provided by the same host. */
  def echoServiceDependency = echoService

  override def testMessage: UrlPathElement = "hello"

  def pollInterval: FiniteDuration = 1.second

  // lifecycle controller configuration
  def lifetime: FiniteDuration = 10500.milliseconds // additional 0.5 seconds so that there are 10 requests, not 9.
}

μ—¬κΈ°μ„œλŠ” μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈ ꡬ성을 λͺ¨λ‘ ν™•μž₯ν•˜λŠ” 단일 ꡬ성을 λ§Œλ“­λ‹ˆλ‹€. λ˜ν•œ 일반적으둜 ν΄λΌμ΄μ–ΈνŠΈμ™€ μ„œλ²„λ₯Ό μ’…λ£Œν•˜λŠ” 라이프사이클 컨트둀러λ₯Ό κ΅¬μ„±ν•©λ‹ˆλ‹€. lifetime 간격이 μ§€λ‚˜κ°‘λ‹ˆλ‹€.

λ™μΌν•œ μ„œλΉ„μŠ€ κ΅¬ν˜„ 및 ꡬ성 μ„ΈνŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ 두 개의 κ°œλ³„ λ…Έλ“œκ°€ μžˆλŠ” μ‹œμŠ€ν…œ λ ˆμ΄μ•„μ›ƒμ„ 생성할 수 μžˆμŠ΅λ‹ˆλ‹€. μš°λ¦¬λŠ” 단지 μ°½μ‘°ν•˜κΈ°λ§Œ ν•˜λ©΄ λœλ‹€ 두 개의 별도 λ…Έλ“œ ꡬ성 μ μ ˆν•œ μ„œλΉ„μŠ€λ₯Ό 톡해:

XNUMX개 λ…Έλ“œ ꡬ성

  object NodeServerConfig extends EchoConfig[String] with SigTermLifecycleConfig
  {
    type NodeId = NodeIdImpl

    def nodeId = NodeServer

    override def portNumber: PortNumber = 8080
  }

  object NodeClientConfig extends EchoClientConfig[String] with FiniteDurationLifecycleConfig
  {
    // NB! dependency specification
    def echoServiceDependency = NodeServerConfig.echoService

    def pollInterval: FiniteDuration = 1.second

    def lifetime: FiniteDuration = 10500.milliseconds // additional 0.5 seconds so that there are 10 request, not 9.

    def testMessage: String = "dolly"
  }

쒅속성을 μ–΄λ–»κ²Œ μ§€μ •ν•˜λŠ”μ§€ μ‚΄νŽ΄λ³΄μ„Έμš”. ν˜„μž¬ λ…Έλ“œμ˜ μ’…μ†μ„±μœΌλ‘œ λ‹€λ₯Έ λ…Έλ“œκ°€ μ œκ³΅ν•˜λŠ” μ„œλΉ„μŠ€λ₯Ό μ–ΈκΈ‰ν•©λ‹ˆλ‹€. ν”„λ‘œν† μ½œμ„ μ„€λͺ…ν•˜λŠ” νŒ¬ν…€ μœ ν˜•μ΄ ν¬ν•¨λ˜μ–΄ μžˆμœΌλ―€λ‘œ 쒅속성 μœ ν˜•μ„ ν™•μΈν•©λ‹ˆλ‹€. 그리고 λŸ°νƒ€μž„μ—λŠ” μ˜¬λ°”λ₯Έ λ…Έλ“œ IDλ₯Ό κ°–κ²Œ λ©λ‹ˆλ‹€. μ΄λŠ” μ œμ•ˆλœ ꡬ성 μ ‘κ·Ό λ°©μ‹μ˜ μ€‘μš”ν•œ μΈ‘λ©΄ 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€. μ΄λŠ” 포트λ₯Ό ν•œ 번만 μ„€μ •ν•˜κ³  μ˜¬λ°”λ₯Έ 포트λ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλŠ”μ§€ ν™•μΈν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.

두 개의 λ…Έλ“œ κ΅¬ν˜„

이 κ΅¬μ„±μ—μ„œλŠ” μ •ν™•νžˆ λ™μΌν•œ μ„œλΉ„μŠ€ κ΅¬ν˜„μ„ μ‚¬μš©ν•©λ‹ˆλ‹€. μ „ν˜€ λ³€ν™”κ°€ μ—†μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μš°λ¦¬λŠ” μ„œλ‘œ λ‹€λ₯Έ μ„œλΉ„μŠ€ μ„ΈνŠΈλ₯Ό ν¬ν•¨ν•˜λŠ” 두 개의 μ„œλ‘œ λ‹€λ₯Έ λ…Έλ“œ κ΅¬ν˜„μ„ λ§Œλ“­λ‹ˆλ‹€.

  object TwoJvmNodeServerImpl extends ZeroServiceImpl[IO] with EchoServiceService with SigIntLifecycleServiceImpl {
    type Config = EchoConfig[String] with SigTermLifecycleConfig
  }

  object TwoJvmNodeClientImpl extends ZeroServiceImpl[IO] with EchoClientService with FiniteDurationLifecycleServiceImpl {
    type Config = EchoClientConfig[String] with FiniteDurationLifecycleConfig
  }

첫 번째 λ…Έλ“œλŠ” μ„œλ²„λ₯Ό κ΅¬ν˜„ν•˜λ©° μ„œλ²„ μΈ‘ κ΅¬μ„±λ§Œ ν•„μš”ν•©λ‹ˆλ‹€. 두 번째 λ…Έλ“œλŠ” ν΄λΌμ΄μ–ΈνŠΈλ₯Ό κ΅¬ν˜„ν•˜λ©° κ΅¬μ„±μ˜ 또 λ‹€λ₯Έ 뢀뢄이 ν•„μš”ν•©λ‹ˆλ‹€. 두 λ…Έλ“œ λͺ¨λ‘ 수λͺ… 사양이 ν•„μš”ν•©λ‹ˆλ‹€. 이 사후 μ„œλΉ„μŠ€ λ…Έλ“œμ˜ λͺ©μ μ„ μœ„ν•΄ λ‹€μŒμ„ μ‚¬μš©ν•˜μ—¬ μ’…λ£Œλ  수 μžˆλŠ” λ¬΄ν•œν•œ 수λͺ…을 κ°–μŠ΅λ‹ˆλ‹€. SIGTERM, 에코 ν΄λΌμ΄μ–ΈνŠΈλŠ” κ΅¬μ„±λœ μœ ν•œ κΈ°κ°„ 후에 μ’…λ£Œλ©λ‹ˆλ‹€. μ°Έμ‘° μŠ€νƒ€ν„° μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μžμ„Έν•œ λ‚΄μš©μ€.

μ „λ°˜μ μΈ 개발 κ³Όμ •

이 μ ‘κ·Ό 방식이 ꡬ성 μž‘μ—… 방식을 μ–΄λ–»κ²Œ λ³€κ²½ν•˜λŠ”μ§€ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

μ½”λ“œλ‘œμ„œμ˜ ꡬ성이 μ»΄νŒŒμΌλ˜μ–΄ μ•„ν‹°νŒ©νŠΈλ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. ꡬ성 μ•„ν‹°νŒ©νŠΈλ₯Ό λ‹€λ₯Έ μ½”λ“œ μ•„ν‹°νŒ©νŠΈμ™€ λΆ„λ¦¬ν•˜λŠ” 것이 ν•©λ¦¬μ μœΌλ‘œ λ³΄μž…λ‹ˆλ‹€. λ™μΌν•œ μ½”λ“œ κΈ°λ°˜μ— λ‹€μ–‘ν•œ ꡬ성을 κ°€μ§ˆ 수 μžˆλŠ” κ²½μš°κ°€ λ§ŽμŠ΅λ‹ˆλ‹€. λ¬Όλ‘  λ‹€μ–‘ν•œ ꡬ성 λΆ„κΈ°μ˜ μ—¬λŸ¬ 버전이 μžˆμ„ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. κ΅¬μ„±μ—μ„œ νŠΉμ • λ²„μ „μ˜ 라이브러리λ₯Ό 선택할 수 있으며 μ΄λŠ” 이 ꡬ성을 배포할 λ•Œλ§ˆλ‹€ μΌμ •ν•˜κ²Œ μœ μ§€λ©λ‹ˆλ‹€.

ꡬ성 변경은 μ½”λ“œ 변경이 λ©λ‹ˆλ‹€. λ”°λΌμ„œ λ™μΌν•œ ν’ˆμ§ˆ 보증 ν”„λ‘œμ„ΈμŠ€κ°€ μ μš©λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

ν‹°μΌ“ -> 홍보 -> κ²€ν†  -> 병합 -> 지속적 톡합 -> 지속적 배포

μ ‘κ·Ό λ°©μ‹μ—λŠ” λ‹€μŒκ³Ό 같은 κ²°κ³Όκ°€ μžˆμŠ΅λ‹ˆλ‹€.

  1. ꡬ성은 νŠΉμ • μ‹œμŠ€ν…œμ˜ μΈμŠ€ν„΄μŠ€μ— λŒ€ν•΄ 일관성이 μžˆμŠ΅λ‹ˆλ‹€. λ…Έλ“œ κ°„ 연결이 잘λͺ»λ  수 μžˆλŠ” 방법은 μ—†λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.
  2. ν•˜λ‚˜μ˜ λ…Έλ“œμ—μ„œλ§Œ ꡬ성을 λ³€κ²½ν•˜λŠ” 것은 쉽지 μ•ŠμŠ΅λ‹ˆλ‹€. λ‘œκ·ΈμΈν•΄μ„œ 일뢀 ν…μŠ€νŠΈ νŒŒμΌμ„ λ³€κ²½ν•˜λŠ” 것은 무리인 것 κ°™μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ ꡬ성 λ“œλ¦¬ν”„νŠΈ κ°€λŠ₯성이 μ€„μ–΄λ“­λ‹ˆλ‹€.
  3. μž‘μ€ ꡬ성 변경은 쉽지 μ•ŠμŠ΅λ‹ˆλ‹€.
  4. λŒ€λΆ€λΆ„μ˜ ꡬ성 λ³€κ²½ 사항은 λ™μΌν•œ 개발 ν”„λ‘œμ„ΈμŠ€λ₯Ό λ”°λ₯΄λ©° 일뢀 κ²€ν† λ₯Ό ν†΅κ³Όν•©λ‹ˆλ‹€.

ν”„λ‘œλ•μ…˜ ꡬ성을 μœ„ν•΄ λ³„λ„μ˜ μ €μž₯μ†Œκ°€ ν•„μš”ν•©λ‹ˆκΉŒ? ν”„λ‘œλ•μ…˜ κ΅¬μ„±μ—λŠ” λ§Žμ€ μ‚¬λžŒμ˜ 손이 닿지 μ•ŠλŠ” 곳에 λ³΄κ΄€ν•˜κ³  싢은 λ―Όκ°ν•œ 정보가 포함될 수 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ ν”„λ‘œλ•μ…˜ ꡬ성을 ν¬ν•¨ν•˜κ³  μ•‘μ„ΈμŠ€κ°€ μ œν•œλœ λ³„λ„μ˜ μ €μž₯μ†Œλ₯Ό μœ μ§€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. ꡬ성을 두 λΆ€λΆ„μœΌλ‘œ λ‚˜λˆŒ 수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜λ‚˜λŠ” ν”„λ‘œλ•μ…˜μ˜ κ°€μž₯ 개방적인 λ§€κ°œλ³€μˆ˜λ₯Ό ν¬ν•¨ν•˜κ³  λ‹€λ₯Έ ν•˜λ‚˜λŠ” κ΅¬μ„±μ˜ λΉ„λ°€ 뢀뢄을 ν¬ν•¨ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 λŒ€λΆ€λΆ„μ˜ κ°œλ°œμžλŠ” 맀우 λ―Όκ°ν•œ ν•­λͺ©μ— λŒ€ν•œ μ•‘μ„ΈμŠ€λ₯Ό μ œν•œν•˜λ©΄μ„œ λŒ€λ‹€μˆ˜μ˜ λ§€κ°œλ³€μˆ˜μ— μ•‘μ„ΈμŠ€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κΈ°λ³Έ λ§€κ°œλ³€μˆ˜ 값이 μžˆλŠ” 쀑간 νŠΉμ„±μ„ μ‚¬μš©ν•˜λ©΄ 이λ₯Ό μ‰½κ²Œ μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ³€ν™”

λ‹€λ₯Έ ꡬ성 관리 기술과 λΉ„κ΅ν•˜μ—¬ μ œμ•ˆλœ μ ‘κ·Ό λ°©μ‹μ˜ μž₯단점을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

μš°μ„ , μ œμ•ˆλœ ꡬ성 처리 λ°©λ²•μ˜ λ‹€μ–‘ν•œ 츑면에 λŒ€ν•œ λͺ‡ 가지 λŒ€μ•ˆμ„ λ‚˜μ—΄ν•˜κ² μŠ΅λ‹ˆλ‹€.

  1. λŒ€μƒ μ»΄ν“¨ν„°μ˜ ν…μŠ€νŠΈ νŒŒμΌμž…λ‹ˆλ‹€.
  2. 쀑앙 집쀑식 ν‚€-κ°’ μ €μž₯μ†Œ(예: etcd/zookeeper).
  3. ν”„λ‘œμ„ΈμŠ€λ₯Ό λ‹€μ‹œ μ‹œμž‘ν•˜μ§€ μ•Šκ³ λ„ μž¬κ΅¬μ„±/λ‹€μ‹œ μ‹œμž‘ν•  수 μžˆλŠ” ν•˜μœ„ ν”„λ‘œμ„ΈμŠ€ ꡬ성 μš”μ†Œμž…λ‹ˆλ‹€.
  4. μ•„ν‹°νŒ©νŠΈ 및 버전 μ œμ–΄ μ™ΈλΆ€ κ΅¬μ„±μž…λ‹ˆλ‹€.

ν…μŠ€νŠΈ νŒŒμΌμ€ μž„μ‹œ μˆ˜μ • μΈ‘λ©΄μ—μ„œ μ–΄λŠ 정도 μœ μ—°μ„±μ„ μ œκ³΅ν•©λ‹ˆλ‹€. μ‹œμŠ€ν…œ κ΄€λ¦¬μžλŠ” λŒ€μƒ λ…Έλ“œμ— λ‘œκ·ΈμΈν•˜μ—¬ λ³€κ²½ν•œ ν›„ κ°„λ‹¨νžˆ μ„œλΉ„μŠ€λ₯Ό λ‹€μ‹œ μ‹œμž‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” 더 큰 μ‹œμŠ€ν…œμ—λŠ” 쒋지 μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. λ³€κ²½ 사항 뒀에 흔적이 남지 μ•ŠμŠ΅λ‹ˆλ‹€. λ³€κ²½ 사항은 λ‹€λ₯Έ μ‚¬λžŒμ˜ 눈으둜 κ²€ν† λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. λ³€ν™”μ˜ 원인이 무엇인지 μ•Œμ•„λ‚΄λŠ” 것은 μ–΄λ €μšΈ 수 μžˆμŠ΅λ‹ˆλ‹€. ν…ŒμŠ€νŠΈλ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. λΆ„μ‚° μ‹œμŠ€ν…œμ˜ κ΄€μ μ—μ„œ κ΄€λ¦¬μžλŠ” λ‹€λ₯Έ λ…Έλ“œ 쀑 ν•˜λ‚˜μ˜ ꡬ성을 μ—…λ°μ΄νŠΈν•˜λŠ” 것을 μžŠμ–΄λ²„λ¦΄ 수 μžˆμŠ΅λ‹ˆλ‹€.

(그런데 κ²°κ΅­ ν…μŠ€νŠΈ ꡬ성 νŒŒμΌμ„ μ‚¬μš©ν•˜κΈ° μ‹œμž‘ν•΄μ•Ό ν•œλ‹€λ©΄ λ™μΌν•œ κ²°κ³Όλ₯Ό 생성할 수 μžˆλŠ” νŒŒμ„œ + μœ νš¨μ„± κ²€μ‚¬κΈ°λ§Œ μΆ”κ°€ν•˜λ©΄ λ©λ‹ˆλ‹€. Config μœ ν˜•μ„ μž…λ ₯ν•˜λ©΄ ν…μŠ€νŠΈ ꡬ성을 μ‚¬μš©ν•˜κΈ°μ— μΆ©λΆ„ν•©λ‹ˆλ‹€. μ΄λŠ” λ˜ν•œ 컴파일 μ‹œκ°„ κ΅¬μ„±μ˜ λ³΅μž‘μ„±μ΄ ν…μŠ€νŠΈ 기반 κ΅¬μ„±μ˜ λ³΅μž‘μ„±λ³΄λ‹€ 쑰금 더 μž‘λ‹€λŠ” 것을 λ³΄μ—¬μ€λ‹ˆλ‹€. μ™œλƒν•˜λ©΄ ν…μŠ€νŠΈ 기반 λ²„μ „μ—μ„œλŠ” λͺ‡ 가지 μΆ”κ°€ μ½”λ“œκ°€ ν•„μš”ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.)

쀑앙 집쀑식 ν‚€-κ°’ μ €μž₯μ†ŒλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 메타 λ§€κ°œλ³€μˆ˜λ₯Ό λ°°ν¬ν•˜λŠ” 데 쒋은 λ©”μ»€λ‹ˆμ¦˜μž…λ‹ˆλ‹€. μ—¬κΈ°μ„œ μš°λ¦¬λŠ” ꡬ성 κ°’μœΌλ‘œ κ°„μ£Όν•˜λŠ” 것이 무엇인지, λ°μ΄ν„°λ§Œ 무엇인지 생각해 λ³Ό ν•„μš”κ°€ μžˆμŠ΅λ‹ˆλ‹€. 주어진 ν•¨μˆ˜ C => A => B μš°λ¦¬λŠ” 일반적으둜 거의 λ³€ν•˜μ§€ μ•ŠλŠ” 값을 ν˜ΈμΆœν•©λ‹ˆλ‹€. C "ꡬ성", 자주 λ³€κ²½λ˜λŠ” 데이터 A - 데이터λ₯Ό μž…λ ₯ν•˜λ©΄ λ©λ‹ˆλ‹€. ꡬ성은 데이터보닀 λ¨Όμ € κΈ°λŠ₯에 μ œκ³΅λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. A. 이 아이디어λ₯Ό κ³ λ €ν•˜λ©΄ ꡬ성 데이터와 λ‹¨μˆœν•œ 데이터λ₯Ό κ΅¬λ³„ν•˜λŠ” 데 μ‚¬μš©ν•  수 μžˆλŠ” λ³€κ²½ λΉˆλ„κ°€ μ˜ˆμƒλœλ‹€κ³  말할 수 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ λ°μ΄ν„°λŠ” 일반적으둜 ν•˜λ‚˜μ˜ μ†ŒμŠ€(μ‚¬μš©μž)μ—μ„œ κ°€μ Έμ˜€κ³  ꡬ성은 λ‹€λ₯Έ μ†ŒμŠ€(κ΄€λ¦¬μž)μ—μ„œ κ°€μ Έμ˜΅λ‹ˆλ‹€. μ΄ˆκΈ°ν™” κ³Όμ • 이후에 변경될 수 μžˆλŠ” λ§€κ°œλ³€μˆ˜λ₯Ό μ²˜λ¦¬ν•˜λŠ” 것은 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λ³΅μž‘μ„±μ„ μ¦κ°€μ‹œν‚΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ λ§€κ°œλ³€μˆ˜μ˜ 경우 전달 λ©”μ»€λ‹ˆμ¦˜, ꡬ문 뢄석 및 μœ νš¨μ„± 검사, 잘λͺ»λœ κ°’ 처리λ₯Ό μ²˜λ¦¬ν•΄μ•Ό ν•©λ‹ˆλ‹€. λ”°λΌμ„œ ν”„λ‘œκ·Έλž¨ λ³΅μž‘μ„±μ„ 쀄이렀면 λŸ°νƒ€μž„ μ‹œ 변경될 수 μžˆλŠ” λ§€κ°œλ³€μˆ˜ 수λ₯Ό μ€„μ΄λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€(λ˜λŠ” μ•„μ˜ˆ μ œκ±°ν•˜λŠ” 것도 μ’‹μŠ΅λ‹ˆλ‹€).

이 κ²Œμ‹œλ¬Όμ˜ κ΄€μ μ—μ„œ μš°λ¦¬λŠ” 정적 λ§€κ°œλ³€μˆ˜μ™€ 동적 λ§€κ°œλ³€μˆ˜λ₯Ό ꡬ별해야 ν•©λ‹ˆλ‹€. μ„œλΉ„μŠ€ 둜직이 λŸ°νƒ€μž„ μ‹œ 일뢀 λ§€κ°œλ³€μˆ˜λ₯Ό λ“œλ¬Όκ²Œ λ³€κ²½ν•΄μ•Ό ν•˜λŠ” 경우 이λ₯Ό 동적 λ§€κ°œλ³€μˆ˜λΌκ³  λΆ€λ₯Ό 수 μžˆμŠ΅λ‹ˆλ‹€. 그렇지 μ•ŠμœΌλ©΄ 정적이며 μ œμ•ˆλœ μ ‘κ·Ό 방식을 μ‚¬μš©ν•˜μ—¬ ꡬ성할 수 μžˆμŠ΅λ‹ˆλ‹€. 동적 μž¬κ΅¬μ„±μ„ μœ„ν•΄μ„œλŠ” λ‹€λ₯Έ μ ‘κ·Ό 방식이 ν•„μš”ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, λΆ„μ‚° μ‹œμŠ€ν…œμ˜ κ°œλ³„ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ‹€μ‹œ μ‹œμž‘ν•˜λŠ” 것과 μœ μ‚¬ν•œ λ°©μ‹μœΌλ‘œ μ‹œμŠ€ν…œμ˜ 일뢀가 μƒˆ ꡬ성 λ§€κ°œλ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ λ‹€μ‹œ μ‹œμž‘λ  수 μžˆμŠ΅λ‹ˆλ‹€.
(μ €μ˜ κ²Έμ†ν•œ μ˜κ²¬μ€ μ‹œμŠ€ν…œμ˜ λ³΅μž‘μ„±μ„ μ¦κ°€μ‹œν‚€κΈ° λ•Œλ¬Έμ— λŸ°νƒ€μž„ μž¬κ΅¬μ„±μ„ ν”Όν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.
ν”„λ‘œμ„ΈμŠ€ μž¬μ‹œμž‘μ— λŒ€ν•œ OS 지원에 μ˜μ‘΄ν•˜λŠ” 것이 더 간단할 수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ 항상 κ°€λŠ₯ν•˜μ§€λŠ” μ•Šμ„ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.)

λ•Œλ•Œλ‘œ μ‚¬λžŒλ“€μ΄ (λ‹€λ₯Έ 이유 없이) 동적 ꡬ성을 κ³ λ €ν•˜κ²Œ λ§Œλ“œλŠ” 정적 ꡬ성 μ‚¬μš©μ˜ μ€‘μš”ν•œ μΈ‘λ©΄ 쀑 ν•˜λ‚˜λŠ” ꡬ성 μ—…λ°μ΄νŠΈ 쀑 μ„œλΉ„μŠ€ 가동 쀑지 μ‹œκ°„μž…λ‹ˆλ‹€. μ‹€μ œλ‘œ 정적 ꡬ성을 λ³€κ²½ν•΄μ•Ό ν•˜λŠ” 경우 μƒˆ 값이 μ μš©λ˜λ„λ‘ μ‹œμŠ€ν…œμ„ λ‹€μ‹œ μ‹œμž‘ν•΄μ•Ό ν•©λ‹ˆλ‹€. 가동 쀑지 μ‹œκ°„μ— λŒ€ν•œ μš”κ΅¬ 사항은 μ‹œμŠ€ν…œλ§ˆλ‹€ λ‹€λ₯΄λ―€λ‘œ 그닀지 μ€‘μš”ν•˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μ€‘μš”ν•œ κ²½μš°μ—λŠ” μ‹œμŠ€ν…œμ„ λ‹€μ‹œ μ‹œμž‘ν•  수 μžˆλ„λ‘ 미리 κ³„νšμ„ μ„Έμ›Œμ•Ό ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ λ‹€μŒμ„ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€. AWS ELB μ—°κ²° λ“œλ ˆμ΄λ‹. 이 μ‹œλ‚˜λ¦¬μ˜€μ—μ„œλŠ” μ‹œμŠ€ν…œμ„ λ‹€μ‹œ μ‹œμž‘ν•΄μ•Ό ν•  λ•Œλ§ˆλ‹€ μ‹œμŠ€ν…œμ˜ μƒˆ μΈμŠ€ν„΄μŠ€λ₯Ό λ³‘λ ¬λ‘œ μ‹œμž‘ν•œ λ‹€μŒ ELBλ₯Ό ν•΄λ‹Ή μΈμŠ€ν„΄μŠ€λ‘œ μ „ν™˜ν•˜κ³  κΈ°μ‘΄ μ‹œμŠ€ν…œμ΄ κΈ°μ‘΄ μ—°κ²° μ„œλΉ„μŠ€λ₯Ό μ™„λ£Œν•˜λ„λ‘ ν•©λ‹ˆλ‹€.

버전이 μ§€μ •λœ μ•„ν‹°νŒ©νŠΈ λ‚΄λΆ€ λ˜λŠ” μ™ΈλΆ€μ—μ„œ ꡬ성을 μœ μ§€ν•˜λŠ” 것은 μ–΄λ–»μŠ΅λ‹ˆκΉŒ? μ•„ν‹°νŒ©νŠΈ 내뢀에 ꡬ성을 μœ μ§€ν•œλ‹€λŠ” 것은 λŒ€λΆ€λΆ„μ˜ 경우 이 ꡬ성이 λ‹€λ₯Έ μ•„ν‹°νŒ©νŠΈμ™€ λ™μΌν•œ ν’ˆμ§ˆ 보증 ν”„λ‘œμ„ΈμŠ€λ₯Ό ν†΅κ³Όν–ˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€. λ”°λΌμ„œ κ΅¬μ„±μ˜ ν’ˆμ§ˆμ΄ μ’‹κ³  μ‹ λ’°ν•  수 μžˆλ‹€κ³  ν™•μ‹ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ°˜λŒ€λ‘œ λ³„λ„μ˜ νŒŒμΌμ— κ΅¬μ„±ν•˜λ©΄ ν•΄λ‹Ή νŒŒμΌμ„ λ³€κ²½ν•œ μ‚¬λžŒκ³Ό μ΄μœ μ— λŒ€ν•œ 좔적이 μ—†μŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€. 이것이 μ€‘μš”ν•©λ‹ˆκΉŒ? μš°λ¦¬λŠ” λŒ€λΆ€λΆ„μ˜ 생산 μ‹œμŠ€ν…œμ—μ„œ μ•ˆμ •μ μ΄κ³  κ³ ν’ˆμ§ˆ ꡬ성을 κ°–λŠ” 것이 더 λ‚«λ‹€κ³  λ―ΏμŠ΅λ‹ˆλ‹€.

μ•„ν‹°νŒ©νŠΈ 버전을 톡해 생성 μ‹œκΈ°, ν¬ν•¨λœ κ°’, ν™œμ„±ν™”/λΉ„ν™œμ„±ν™”λ˜λŠ” κΈ°λŠ₯, κ΅¬μ„±μ˜ 각 변경을 λ‹΄λ‹Ήν•œ μ‚¬λžŒμ„ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. μ•„ν‹°νŒ©νŠΈ 내뢀에 ꡬ성을 μœ μ§€ν•˜λ €λ©΄ μ•½κ°„μ˜ λ…Έλ ₯이 ν•„μš”ν•  수 있으며 μ΄λŠ” λ””μžμΈ μ„ νƒμž…λ‹ˆλ‹€.

μž₯단점

μ—¬κΈ°μ„œ μš°λ¦¬λŠ” μ œμ•ˆλœ μ ‘κ·Ό λ°©μ‹μ˜ λͺ‡ 가지 μž₯점을 κ°•μ‘°ν•˜κ³  λͺ‡ 가지 단점을 λ…Όμ˜ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

μž₯점

μ™„μ „ν•œ λΆ„μ‚° μ‹œμŠ€ν…œμ˜ 컴파일 κ°€λŠ₯ν•œ ꡬ성 κΈ°λŠ₯:

  1. κ΅¬μ„±μ˜ 정적 확인. μ΄λŠ” μœ ν˜• μ œμ•½ 쑰건에 따라 ꡬ성이 μ •ν™•ν•˜λ‹€λŠ” 높은 μˆ˜μ€€μ˜ 확신을 μ œκ³΅ν•©λ‹ˆλ‹€.
  2. ν’λΆ€ν•œ ꡬ성 μ–Έμ–΄. 일반적으둜 λ‹€λ₯Έ ꡬ성 μ ‘κ·Ό 방식은 μ΅œλŒ€ λ³€μˆ˜ λŒ€μ²΄μœΌλ‘œ μ œν•œλ©λ‹ˆλ‹€.
    Scalaλ₯Ό μ‚¬μš©ν•˜λ©΄ κ΄‘λ²”μœ„ν•œ μ–Έμ–΄ κΈ°λŠ₯을 μ‚¬μš©ν•˜μ—¬ ꡬ성을 더 μ’‹κ²Œ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ νŠΉμ„±μ„ μ‚¬μš©ν•˜μ—¬ 기본값을 μ œκ³΅ν•˜κ³  개체λ₯Ό μ‚¬μš©ν•˜μ—¬ λ‹€λ₯Έ λ²”μœ„λ₯Ό μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€. valsλŠ” μ™ΈλΆ€ λ²”μœ„(DRY)μ—μ„œ ν•œ 번만 μ •μ˜λ©λ‹ˆλ‹€. λ¦¬ν„°λŸ΄ μ‹œν€€μŠ€λ‚˜ νŠΉμ • 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 κ°€λŠ₯ν•©λ‹ˆλ‹€(Seq, Mapλ“±).
  3. DSL. ScalaλŠ” DSL μž‘μ„±μžλ₯Ό μ μ ˆν•˜κ²Œ μ§€μ›ν•©λ‹ˆλ‹€. μ΄λŸ¬ν•œ κΈ°λŠ₯을 μ‚¬μš©ν•˜λ©΄ 보닀 νŽΈλ¦¬ν•˜κ³  μ΅œμ’… μ‚¬μš©μžμ—κ²Œ μΉœμˆ™ν•œ ꡬ성 μ–Έμ–΄λ₯Ό μ„€μ •ν•  수 μžˆμœΌλ―€λ‘œ μ΅œμ†Œν•œ 도메인 μ‚¬μš©μžλŠ” μ΅œμ’… ꡬ성을 읽을 수 μžˆμŠ΅λ‹ˆλ‹€.
  4. λ…Έλ“œ μ „μ²΄μ˜ 무결성과 일관성. 전체 λΆ„μ‚° μ‹œμŠ€ν…œμ„ ν•œ κ³³μ—μ„œ ꡬ성할 λ•Œμ˜ 이점 쀑 ν•˜λ‚˜λŠ” λͺ¨λ“  값이 μ—„κ²©ν•˜κ²Œ ν•œ 번 μ •μ˜λœ λ‹€μŒ ν•„μš”ν•œ λͺ¨λ“  κ³³μ—μ„œ μž¬μ‚¬μš©λœλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€. λ˜ν•œ μ•ˆμ „ν•œ 포트 선언을 μž…λ ₯ν•˜λ©΄ κ°€λŠ₯ν•œ λͺ¨λ“  μ˜¬λ°”λ₯Έ κ΅¬μ„±μ—μ„œ μ‹œμŠ€ν…œ λ…Έλ“œκ°€ λ™μΌν•œ μ–Έμ–΄λ₯Ό μ‚¬μš©ν•˜λ„λ‘ ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ…Έλ“œ κ°„μ—λŠ” λͺ…μ‹œμ μΈ 쒅속성이 μžˆμœΌλ―€λ‘œ 일뢀 μ„œλΉ„μŠ€λ₯Ό μ œκ³΅ν•˜λŠ” 것을 잊기 μ–΄λ ΅μŠ΅λ‹ˆλ‹€.
  5. 높은 ν’ˆμ§ˆμ˜ λ³€κ²½. 일반적인 PR ν”„λ‘œμ„ΈμŠ€λ₯Ό 톡해 ꡬ성 λ³€κ²½ 사항을 μ „λ‹¬ν•˜λŠ” μ „λ°˜μ μΈ μ ‘κ·Ό 방식은 κ΅¬μ„±μ—μ„œλ„ 높은 ν’ˆμ§ˆ ν‘œμ€€μ„ μ„€μ •ν•©λ‹ˆλ‹€.
  6. λ™μ‹œ ꡬ성 λ³€κ²½. ꡬ성 μžλ™ 배포λ₯Ό λ³€κ²½ν•  λ•Œλ§ˆλ‹€ λͺ¨λ“  λ…Έλ“œκ°€ μ—…λ°μ΄νŠΈλ˜λ„λ‘ ν•©λ‹ˆλ‹€.
  7. μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ‹¨μˆœν™”. μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ€ ꡬ성을 ꡬ문 뢄석 및 κ²€μ¦ν•˜κ³  잘λͺ»λœ ꡬ성 값을 μ²˜λ¦¬ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. μ΄λŠ” 전체 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ‹¨μˆœν™”ν•©λ‹ˆλ‹€. (ꡬ성 μžμ²΄μ— μ•½κ°„μ˜ λ³΅μž‘μ„± 증가가 μžˆμ§€λ§Œ μ΄λŠ” μ•ˆμ „μ— λŒ€ν•œ μ˜μ‹μ μΈ μ ˆμΆ©μž…λ‹ˆλ‹€.) 일반적인 κ΅¬μ„±μœΌλ‘œ λŒμ•„κ°€λŠ” 것은 맀우 κ°„λ‹¨ν•©λ‹ˆλ‹€. λˆ„λ½λœ 뢀뢄을 μΆ”κ°€ν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€. 컴파일된 κ΅¬μ„±μœΌλ‘œ μ‹œμž‘ν•˜κ³  μΆ”κ°€ λΆ€λΆ„μ˜ κ΅¬ν˜„μ„ λ‚˜μ€‘μ— μ—°κΈ°ν•˜λŠ” 것이 더 μ‰½μŠ΅λ‹ˆλ‹€.
  8. 버전이 μ§€μ •λœ ꡬ성. ꡬ성 변경이 λ™μΌν•œ 개발 ν”„λ‘œμ„ΈμŠ€λ₯Ό λ”°λ₯΄κΈ° λ•Œλ¬Έμ— 결과적으둜 κ³ μœ ν•œ λ²„μ „μ˜ μ•„ν‹°νŒ©νŠΈλ₯Ό μ–»κ²Œ λ©λ‹ˆλ‹€. ν•„μš”ν•œ 경우 ꡬ성을 λ‹€μ‹œ μ „ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. XNUMXλ…„ 전에 μ‚¬μš©ν–ˆλ˜ ꡬ성을 배포할 μˆ˜λ„ 있으며 μ΄λŠ” μ •ν™•νžˆ λ™μΌν•œ λ°©μ‹μœΌλ‘œ μž‘λ™ν•©λ‹ˆλ‹€. μ•ˆμ •μ μΈ ꡬ성은 λΆ„μ‚° μ‹œμŠ€ν…œμ˜ 예츑 κ°€λŠ₯μ„±κ³Ό 신뒰성을 ν–₯μƒμ‹œν‚΅λ‹ˆλ‹€. ꡬ성은 컴파일 νƒ€μž„μ— μˆ˜μ •λ˜λ©° ν”„λ‘œλ•μ…˜ μ‹œμŠ€ν…œμ—μ„œλŠ” μ‰½κ²Œ 변쑰될 수 μ—†μŠ΅λ‹ˆλ‹€.
  9. λͺ¨λ“ˆμ„±. μ œμ•ˆλœ ν”„λ ˆμž„μ›Œν¬λŠ” λͺ¨λ“ˆμ‹μ΄λ©° λͺ¨λ“ˆμ€ λ‹€μ–‘ν•œ λ°©μ‹μœΌλ‘œ 결합될 수 μžˆμŠ΅λ‹ˆλ‹€.
    λ‹€μ–‘ν•œ ꡬ성(μ„€μ •/λ ˆμ΄μ•„μ›ƒ)을 μ§€μ›ν•©λ‹ˆλ‹€. 특히 μ†Œκ·œλͺ¨ 단일 λ…Έλ“œ λ ˆμ΄μ•„μ›ƒκ³Ό λŒ€κ·œλͺ¨ 닀쀑 λ…Έλ“œ 섀정이 κ°€λŠ₯ν•©λ‹ˆλ‹€. μ—¬λŸ¬ 생산 λ ˆμ΄μ•„μ›ƒμ„ κ°–λŠ” 것이 ν•©λ¦¬μ μž…λ‹ˆλ‹€.
  10. ν…ŒμŠ€νŠΈ. ν…ŒμŠ€νŠΈ λͺ©μ μœΌλ‘œ λͺ¨μ˜ μ„œλΉ„μŠ€λ₯Ό κ΅¬ν˜„ν•˜κ³  이λ₯Ό μœ ν˜• μ•ˆμ „ λ°©μ‹μ˜ μ’…μ†μ„±μœΌλ‘œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λͺ¨μ˜ν’ˆμœΌλ‘œ ꡐ체된 λ‹€μ–‘ν•œ λΆ€ν’ˆμ„ κ°–μΆ˜ λͺ‡ 가지 λ‹€λ₯Έ ν…ŒμŠ€νŠΈ λ ˆμ΄μ•„μ›ƒμ„ λ™μ‹œμ— μœ μ§€ 관리할 수 μžˆμŠ΅λ‹ˆλ‹€.
  11. 톡합 ν…ŒμŠ€νŠΈ. λ•Œλ•Œλ‘œ λΆ„μ‚° μ‹œμŠ€ν…œμ—μ„œλŠ” 톡합 ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•˜κΈ°κ°€ μ–΄λ ΅μŠ΅λ‹ˆλ‹€. 전체 λΆ„μ‚° μ‹œμŠ€ν…œμ˜ μ•ˆμ „ν•œ ꡬ성을 μž…λ ₯ν•˜κΈ° μœ„ν•΄ μ„€λͺ…λœ μ ‘κ·Ό 방식을 μ‚¬μš©ν•˜λ©΄ 단일 μ„œλ²„μ—μ„œ λͺ¨λ“  λΆ„μ‚° 뢀뢄을 μ œμ–΄ κ°€λŠ₯ν•œ λ°©μ‹μœΌλ‘œ μ‹€ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 상황을 ν‰λ‚΄λ‚΄λŠ” 것은 μ‰½μŠ΅λ‹ˆλ‹€
    μ„œλΉ„μŠ€ 쀑 ν•˜λ‚˜λ₯Ό μ‚¬μš©ν•  수 μ—†κ²Œ 된 경우.

단점

컴파일된 ꡬ성 μ ‘κ·Ό 방식은 "일반" ꡬ성과 λ‹€λ₯΄λ©° λͺ¨λ“  μš”κ΅¬ 사항에 μ ν•©ν•˜μ§€ μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. 컴파일된 κ΅¬μ„±μ˜ λͺ‡ 가지 단점은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  1. 정적 ꡬ성. λͺ¨λ“  μ‘μš© ν”„λ‘œκ·Έλž¨μ— μ ν•©ν•˜μ§€ μ•Šμ„ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μ–΄λ–€ κ²½μš°μ—λŠ” λͺ¨λ“  μ•ˆμ „ 쑰치λ₯Ό μš°νšŒν•˜μ—¬ 생산 μ‹œ ꡬ성을 μ‹ μ†ν•˜κ²Œ μˆ˜μ •ν•΄μ•Ό ν•  ν•„μš”κ°€ μžˆμŠ΅λ‹ˆλ‹€. 이 μ ‘κ·Ό 방식은 더 μ–΄λ ΅μŠ΅λ‹ˆλ‹€. ꡬ성을 λ³€κ²½ν•œ ν›„μ—λŠ” 컴파일 및 μž¬λ°°ν¬κ°€ ν•„μš”ν•©λ‹ˆλ‹€. 이것이 νŠΉμ§•μ΄κΈ°λ„ ν•˜κ³  뢀담이기도 ν•˜λ‹€.
  2. ꡬ성 생성. 일뢀 μžλ™ν™” λ„κ΅¬μ—μ„œ ꡬ성을 μƒμ„±ν•˜λŠ” 경우 이 μ ‘κ·Ό λ°©μ‹μ—λŠ” 후속 컴파일이 ν•„μš”ν•©λ‹ˆλ‹€(결과적으둜 μ‹€νŒ¨ν•  수 있음). 이 μΆ”κ°€ 단계λ₯Ό λΉŒλ“œ μ‹œμŠ€ν…œμ— ν†΅ν•©ν•˜λ €λ©΄ μΆ”κ°€ λ…Έλ ₯이 ν•„μš”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  3. μ•…κΈ°. μ˜€λŠ˜λ‚  ν…μŠ€νŠΈ 기반 ꡬ성에 μ˜μ‘΄ν•˜λŠ” 도ꡬ가 많이 μ‚¬μš©λ˜κ³  μžˆμŠ΅λ‹ˆλ‹€. κ·Έλ“€ 쀑 일뢀
    ꡬ성이 컴파일되면 μ μš©λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
  4. μ‚¬κ³ λ°©μ‹μ˜ μ „ν™˜μ΄ ν•„μš”ν•©λ‹ˆλ‹€. κ°œλ°œμžμ™€ DevOpsλŠ” ν…μŠ€νŠΈ ꡬ성 νŒŒμΌμ— μ΅μˆ™ν•©λ‹ˆλ‹€. ꡬ성을 μ»΄νŒŒμΌν•œλ‹€λŠ” 아이디어가 κ·Έλ“€μ—κ²ŒλŠ” μ΄μƒν•˜κ²Œ 보일 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.
  5. 컴파일 κ°€λŠ₯ν•œ ꡬ성을 λ„μž…ν•˜κΈ° 전에 κ³ ν’ˆμ§ˆ μ†Œν”„νŠΈμ›¨μ–΄ 개발 ν”„λ‘œμ„ΈμŠ€κ°€ ν•„μš”ν•©λ‹ˆλ‹€.

κ΅¬ν˜„λœ μ˜ˆμ œμ—λŠ” λͺ‡ 가지 μ œν•œ 사항이 μžˆμŠ΅λ‹ˆλ‹€.

  1. λ…Έλ“œ κ΅¬ν˜„μ—μ„œ μš”κ΅¬ν•˜μ§€ μ•ŠλŠ” μΆ”κ°€ ꡬ성을 μ œκ³΅ν•˜λŠ” 경우 μ»΄νŒŒμΌλŸ¬λŠ” λˆ„λ½λœ κ΅¬ν˜„μ„ κ°μ§€ν•˜λŠ” 데 도움이 λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 이 λ¬Έμ œλŠ” λ‹€μŒμ„ μ‚¬μš©ν•˜μ—¬ ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€. HList λ˜λŠ” νŠΉμ„± 및 케이크 νŒ¨ν„΄ λŒ€μ‹  λ…Έλ“œ ꡬ성을 μœ„ν•œ ADT(μΌ€μ΄μŠ€ 클래슀).
  2. ꡬ성 νŒŒμΌμ— λͺ‡ 가지 μƒμš©κ΅¬λ₯Ό μ œκ³΅ν•΄μ•Ό ν•©λ‹ˆλ‹€. (package, import, object μ„ μ–Έ;
    override def기본값이 μžˆλŠ” λ§€κ°œλ³€μˆ˜μ˜ 경우). 이 λ¬Έμ œλŠ” DSL을 μ‚¬μš©ν•˜μ—¬ λΆ€λΆ„μ μœΌλ‘œ 해결될 수 μžˆμŠ΅λ‹ˆλ‹€.
  3. 이 κ²Œμ‹œλ¬Όμ—μ„œλŠ” μœ μ‚¬ν•œ λ…Έλ“œ ν΄λŸ¬μŠ€ν„°μ˜ 동적 μž¬κ΅¬μ„±μ„ 닀루지 μ•ŠμŠ΅λ‹ˆλ‹€.

κ²°λ‘ 

이 κ²Œμ‹œλ¬Όμ—μ„œ μš°λ¦¬λŠ” μœ ν˜•μ΄ μ•ˆμ „ν•œ λ°©μ‹μœΌλ‘œ μ†ŒμŠ€ μ½”λ“œμ—μ„œ 직접 ꡬ성을 ν‘œν˜„ν•˜λŠ” 아이디어에 λŒ€ν•΄ λ…Όμ˜ν–ˆμŠ΅λ‹ˆλ‹€. 이 μ ‘κ·Ό 방식은 XML 및 기타 ν…μŠ€νŠΈ 기반 ꡬ성을 λŒ€μ²΄ν•˜μ—¬ λ§Žμ€ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€. 우리 μ˜ˆμ œκ°€ Scala둜 κ΅¬ν˜„λ˜μ—ˆμŒμ—λ„ λΆˆκ΅¬ν•˜κ³  λ‹€λ₯Έ 컴파일 κ°€λŠ₯ν•œ μ–Έμ–΄(Kotlin, C#, Swift λ“±)둜 λ²ˆμ—­λ  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μƒˆ ν”„λ‘œμ νŠΈμ—μ„œ 이 μ ‘κ·Ό 방식을 μ‹œλ„ν•΄ λ³Ό 수 있으며, 잘 λ§žμ§€ μ•ŠλŠ” 경우 κΈ°μ‘΄ λ°©μ‹μœΌλ‘œ μ „ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ¬Όλ‘  컴파일 κ°€λŠ₯ν•œ κ΅¬μ„±μ—λŠ” κ³ ν’ˆμ§ˆ 개발 ν”„λ‘œμ„ΈμŠ€κ°€ ν•„μš”ν•©λ‹ˆλ‹€. κ·Έ λŒ€κ°€λ‘œ κ³ ν’ˆμ§ˆμ˜ κ²¬κ³ ν•œ ꡬ성을 μ œκ³΅ν•  것을 μ•½μ†ν•©λ‹ˆλ‹€.

이 μ ‘κ·Ό 방식은 λ‹€μ–‘ν•œ λ°©μ‹μœΌλ‘œ ν™•μž₯될 수 μžˆμŠ΅λ‹ˆλ‹€.

  1. 맀크둜λ₯Ό μ‚¬μš©ν•˜μ—¬ ꡬ성 μœ νš¨μ„± 검사λ₯Ό μˆ˜ν–‰ν•˜κ³  λΉ„μ¦ˆλ‹ˆμŠ€ 논리 μ œμ•½ 쑰건이 μ‹€νŒ¨ν•˜λŠ” 경우 컴파일 νƒ€μž„μ— μ‹€νŒ¨ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  2. 도메인 μ‚¬μš©μž μΉœν™”μ μΈ λ°©μ‹μœΌλ‘œ ꡬ성을 λ‚˜νƒ€λ‚΄κΈ° μœ„ν•΄ DSL을 κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  3. μžλ™ ꡬ성 쑰정을 ν†΅ν•œ 동적 λ¦¬μ†ŒμŠ€ 관리. 예λ₯Ό λ“€μ–΄, ν΄λŸ¬μŠ€ν„° λ…Έλ“œ 수λ₯Ό μ‘°μ •ν•  λ•Œ (1) λ…Έλ“œκ°€ μ•½κ°„ μˆ˜μ •λœ ꡬ성을 얻도둝 ν•˜κ³ ; (2) ν΄λŸ¬μŠ€ν„° κ΄€λ¦¬μžλŠ” μƒˆ λ…Έλ“œ 정보λ₯Ό μˆ˜μ‹ ν•©λ‹ˆλ‹€.

감사

이 κ²Œμ‹œλ¬Όμ˜ μ΄ˆμ•ˆμ„ 보닀 λͺ…ν™•ν•˜κ²Œ λ§Œλ“œλŠ” 데 도움이 λ˜λŠ” μ˜κ°μ„ μ£ΌλŠ” ν”Όλ“œλ°±μ„ μ£Όμ‹  Andrey Saksonov, Pavel Popov, Anton Nehaevμ—κ²Œ κ°μ‚¬μ˜ 말씀을 μ „ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

좜처 : habr.com