반응형

시스템에서 카산드라를 사용한지 3년이 넘어가면서 그 동안 도움을 받았거나 좋은 내용들의 글을 모아놨었는데 로컬에 남겨놓는건 찾기도 힘들고 언제 사라질지 모르니 포스팅으로 남겨본다.

1. How is data written?

https://docs.datastax.com/en/archived/cassandra/2.2/cassandra/dml/dmlHowDataWritten.html

 

How is data written?

Understand how Cassandra writes and stores data. Cassandra processes data at several stages on the write path, starting with the immediate logging of a write and ending in with a write of data to disk: Logging data in the commit log Writing data to the mem

docs.datastax.com

 

2. How is data read?

https://docs.datastax.com/en/archived/cassandra/3.0/cassandra/dml/dmlAboutReads.html

 

How is data read?

How Cassandra combines results from the active memtable and potentially multiple SSTables to satisfy a read. To satisfy a read, Cassandra must combine results from the active memtable and potentially multiple SSTables. Cassandra processes data at several s

docs.datastax.com

 

3. Materialized View Performance in Cassandra 3.x

https://www.datastax.com/dev/blog/materialized-view-performance-in-cassandra-3-x

 

Materialized View Performance in Cassandra 3.x | Datastax

DataStax, Titan, and TitanDB are registered trademarks of DataStax, Inc. and its subsidiaries in the United States and/or other countries. Apache, Apache Cassandra, Cassandra, Apache Tomcat, Tomcat, Apache Lucene, Lucene, Apache Solr, Apache Hadoop, Hadoop

www.datastax.com

 

4. Apache Cassandra Materialized View Design

https://docs.google.com/document/d/1sK96wsE3uwFqzrLQju_spya6rOTxojOKR9N7W-rPwdw/edit

 

Google 문서 - 온라인에서 문서를 작성하고 수정할 수 있으며 무료입니다.

하나의 계정으로 모든 Google 서비스를 문서로 이동하려면 로그인하세요.

accounts.google.com

 

5. Cassandra 3.0 Materialized Views Technical Deep Dive

http://www.doanduyhai.com/blog/?p=1930

 

Cassandra 3.0 Materialized Views Technical Deep Dive | DOAN DuyHai's blog

In this blog post, we’ll dig into the brand new materialized view feature of Cassandra 3.0. We’ll see how it is implemented internally, how you should use it to get the most of its performance and which caveats to avoid. For the remaining of this post Cass

www.doanduyhai.com

 

6. 카산드라 compaction관련 장애처리

http://knight76.tistory.com/entry/cassandra-compaction-%EA%B4%80%EB%A0%A8

 

cassandra gc 튜닝 - compaction과 full gc

cassandra를 운영하면서 CMS Full GC가 발생하면서 수십 초동안 stop the world (hang)이 발생했다. 이를 간단히 해결한 내용을 작성한다. Case #1 node repair를 하고 난 직후 바로 다른 table(colum family)에서..

knight76.tistory.com

 

7. Myths of Big Partitions

https://www.slideshare.net/DataStax/myths-of-big-partitions-robert-stupp-datastax-cassandra-summit-2016

 

Myths of Big Partitions (Robert Stupp, DataStax) | Cassandra Summit 2…

Large partitions shall no longer be a nightmare. That is the goal of CASSANDRA-11206. 100MB and 100,000 cells per partition is the recommended limit for a sing…

www.slideshare.net

 

8. Hinted Handoff: repair during write path

https://docs.datastax.com/en/cassandra/3.0/cassandra/operations/opsRepairNodesHintedHandoff.html

 

Hinted Handoff: repair during write path

Describes hinted handoff, repair during write path. On occasion, a node becomes unresponsive while data is being written. Reasons for unresponsiveness are hardware problems, network issues, or overloaded nodes that experience long garbage collection (GC) p

docs.datastax.com

 

9. Cassandra performance: the most comprehensive overview you’ll ever see

https://www.scnsoft.com/blog/cassandra-performance

 

Cassandra Performance: The Most Comprehensive Overview You’ll Ever See

Cassandra Performance: The Most Comprehensive Overview You’ll Ever See Head of Data Analytics Department, ScienceSoft Apache Cassandra obviously can’t tell the future. It can only enable you to organize data storage (or at least make it as organized as it

www.scnsoft.com

 

반응형
반응형

구글은 어떻게 일하는가의 shareSlide자료를 보고 와닿았던 문구들을 추려보았다.

 

1. 대부분의 회사들이 자유와 속도를 최대화하는게 아니라, 리스크를 최소하하려 한다.

먼저 요즘 IT회사들의 방향성에 대해 이야기하고 회사내에서도 보수적인 팀들의 성향을 잘 대변해주는 문구 인 것 같아 너무 와닿았다.

물론 관리자의 입장에서 리스크를 최소화하려고 노력하는 부분도 필요하다고 생각하지만 본인이 모르는 기술, 사용해보지 않은 것들에 대해 거부감을 가지고 있는 새로운 변화를 시도하지 않는다면 딱 그 자리 그 수준에서 밖에 머물 수 없다고 생각한다.

 

 

2. 1번과 같은 이유로 회사들은 변해가는 트렌드와 기술을 따라가기 힘들어지고 도태되고 만다.

 

 

 

3. 벤처회사의 기반을 계획에 두지마세요. 대신 전략적 토대에 기반을 두세요.

토이프로젝트를 동기 한 명과 진행하고 있는 요즘이라서 그런지 더욱 와닿았다. 내가 만들고 있는 서비스가 단순히 실력향상에만 초점이 맞추어져있다면 계획에 기반을 두고 진행되어도 괜찮겠지만 좀 더 큰 계획과 큰 꿈이 있기에 전략적 토대에 기반한 사고를 기르는데도 노력해야 할 것이다.

 

 

3. 양복쟁이들 말고, 연구쟁이들의 말에 귀를 귀울이세요.

실무를 하다보면 정말 100중에 10밖에 모르면서 90을 아는 것 처럼 말하는 분들을 접할 수 있다. 그렇게 생각하는 이유는 직접 그 시스템을 만들어보지 않았고 같은 상황을 겪어보지 않고 단순히 본인들의 생각과 주변에서 주워들은 이야기들을 빗대어 이야기 하기 떄문이다. 

개발자로 일하고 나서 부터는 백 마디 생각과 말보다 비슷한 프로토타입이라도 만들어보고 직접 경험한 내용에 기반한 이야기를 하는 것을 더 선호한다.

 

4. Ask yourself, what could be true in 5 years?

본인의 향후 5년 계획을 세워본 사람이 있는가? 살아지는 대로의 삶이 아닌 정말 본인이 추구하는 목표와 꿈이 있어 살아가는 사람이 있는가? 항상 나는 그런 삶을 살길 희망하고 노력한다. 그러기 위해서는 지금 당장의 행복도 중요하지만 미래를 위해 일정부분 감내해야 하는 용기와 마인드도 필요하다 생각한다. 5년 안에 나는 무엇이 될 수 있을까? 많은 생각을 해본다.

 

 

5. 상상할 수 없는 걸 상상하세요. 상상할 수 없는게 이미 많이 벌어지고 있으니까요.

너무 헛된 망상에 둘러쌓여 살진 말되, 너무 현실적인 생각만으로도 살진 말자.

 

 

잠깐 스쳐가나가다 시피 보게 된 내용이였는데 생각하게 만드는 좋은 문구들이 많아 이렇게 포스팅하게 되었다.

원문을 보고 싶은 분은 아래를 참고 바란다.

참조 : https://www.slideshare.net/alleciel/how-google-works-korean

반응형
반응형

브라우저에서 특정 사이트를 접속 할 때 브라우져는 어떻게 해당 도메인에 해당하는 IP를 어떤 순서로 찾을까????

 

1. 먼저 브라우저는 Local Cache를 검색한다.

 

2. 그리고 hosts 파일을 검색하여 찾는다. 

 

3. 위의 두 경우에 해당하는 도메인이 없는경우 그 때

DNS(Domanin Name Service)서버에 요청하여 해당 도메인의 IP주소를 받게된다.

 

그래서 보통 테스트 할 때

 

기존 naver.com DNS에 등록되어 있는 도메인의 ip가 323.5.2.1일지라도 

내 로컬 피시, 리눅스 환경에서 hosts파일에 naver.com 127.0.0.1로 등록해 놓게 되면

DNS에 가기전에 hosts파일을 먼저 뒤지기 때문에 127.0.0.1 IP로 요청이 가게 되는 것이다.

(보통 개발하다 보면 특정 도메인 테스트를 위해 이런 방법을 쓰곤 한다.)

반응형
반응형

Mac에서 인텔리제이(IntelliJ)를 사용하시는 분들이라면 무조건 겪어 보셨을거다..(분명해...)

Action검색 : Ctrl + Shift + a (execute maven, execute gradle 등등) 기본 액션을 편하게 해주는 단축키

 

근데 짜증나게도 여러번 단축키를 누르다 보면...

action창이 뜨지 않고 아래와 같은 이상한 노란 메모장같은 화면이 뜬다....(apropos exe - 80 x 48)

경험해보신분들 있죠???

 

해결책

해결법을 알려드리려 한다. MAC에서 제공하는 단축키와 겹치다 보니 아래와 같이 해당 서비스를 disable해주어야 한다.

시스템환경설정 -> 키보드 -> 단축키(탭) -> 서비스 -> 터미널 man페이지 인덱스 검색 => 비활성화(체크 해제)

터미널에서 man 페이지 인덱스 검색 체크를 해제해주어야 한다.

 

체크를 해제 해주게 되면 그 이후 부터는 노란 메모장을 더 이상 마주하지 않을 것이다^_^

반응형
반응형

기술블로그 혹은 그 이외의 좋은 글들을 나중에 쉽게 보기 위해 모아보려고 카테고리를 하나 더 만들었다.

 

 최근 너무나 좋은 글을 발견해 목록 리스트 통째로 남겨본다. 광고시스템(광고가 실시간 비딩(RTB)되는 과정, 크로스디바이스 방식)에 궁금한 분이나, 데이터사이언스에 대해 궁금하시다면 해당 포스팅들이 많은 도움이 될 거라 확신한다. 

프린터해서 몇 번씩 읽어봐야된다 진짜!

 

광고시스템에 대해 궁금하신 분이나 광고시스템을 운영하고 계시는 엔지니어 사이언스분들은
꼭 읽자, 아니 두 번 읽자 아니 최소 세번 읽자!!!

 

1. 빅 데이터, 머신러닝, 데이터 사이언스에 대한 오해

http://blog.ab180.co/data-science-with-r-1-misperception/

 

데이터 사이언스에 대한 오해

알파고로 인공지능의 가능성을 확인한 사람들이, 빅 데이터를 갖추고 있고, 머신러닝을 적용만하면 꿈같던 일들이 모두 현실화 될 것이라고 큰 기대를 품고 있는데, 데이터 사이언티스트 입장에서 대중의 기대에 일침을 놓는 글 시리즈를 드려볼까 한다.

blog.ab180.co

 

2. 최적화-CTR Optimizer

https://blog.ab180.co/data-science-with-r-3-optimization/

 

3. 최적화 (Collaborative vs. Contents-based)

필자가 구글 북 스토어에서 꾹꾹 눌러봤던 책들은 필자가 어떤 제목과 어떤 요약글에, 그리고 어떤 장르의 서적에 관심이 많은지를 잘 보여준다. 설문조사에는 로맨스 소설을 좋아한다고 “뻥”을 치더라도, 정작 구글 북 스토어 클릭 기록을 보면 SF 소설과 괴기 소설밖에 없다면 필자의 진정한 관심사는 무엇일까?

blog.ab180.co

 

3. 멀티 터치 어트리뷰션(Multi-Touch Attribution Model)

https://blog.ab180.co/data-science-with-r-4-multi-touch-attribution/

 

멀티 터치 어트리뷰션 (Multi-touch Attribution)

A가 B나 C와 결합되면 훨씬 더 많은 산출물을 냈으나, 정작 B와 C는 결합해서 별로 좋은 성과가 없다. 쉽게 이야기하면 A는 “버프”를 잘 시켜주는 일꾼인 것이다. 실제 광고에도, 다른 채널에서 전환이 잘 일어나도록 도움을 주는 채널도 있고, 반대로 다른 채널 광고 성과를 뺏

blog.ab180.co

 

4. 크로스 디바이스 매칭(Cross-Device Matching)

https://blog.ab180.co/data-science-with-r-5-cross-device-matching/

 

Cross device matching

필자가 사무실에서, 집에서, 통근길에 랩탑, 데스크탑, 모바일 기기로 검색했던 내용들을 3개의 기기로 나누어서 추적하는 것이 아니라, 1명의 유저가 한 행동으로 추적할 수 있다면 좀 더 정확하게 필자의 관심사를 파악할 수 있을 것이다.

blog.ab180.co

 

5. RTB란?

https://blog.ab180.co/data-science-with-r-6-rtb/

 

RTB란?

우선 RTB는 우리가 알고 있는 경매 방식대로 돌아가지 않는다. 제일 비싼 가격을 제시한 사람이 2등이 제시했던 가격으로 상품을 사간다. 2등 가격으로 팔면 파는 사람이 손해 아닌가? 먼저 결론만 말하면 “아니다”. 1등 가격으로 팔면 서로 눈치보기를 할 유인동기가 있지만...

blog.ab180.co

 

6. 사기 설치와 클릭(Fraud Installs & Clicks)

https://blog.ab180.co/data-science-with-r-10-fraud-installs-clicks/

 

 

반응형
반응형

2020년이 시작한 지도 벌써 한 달이 지나....벌써 2월 5일.......1월 한 달간 도움을 받은 기술포스팅들을 남겨본다. 내용이 좋아 추후 참고하고 싶은 글들을 모은 것이기도 하다.

 

1. 데이터 엔지니어링 관련 소프트웨어 장애 대응 사례

데이터 엔지니어로 일을 하고 있기도 하고 하둡 클러스터를 사용하면서 한 번 쯤을 겪게되는 (겪을 수 있는) 문제 들에 대해 잘 정리되어 진 글이다. 하둡 클러스터를 운영함에 어떤 이슈가 발생할 수 있고 하둡 이중화에 대해 관심이 있는 분들은 한 번 읽어보길 바란다.

https://engineering.linecorp.com/ko/blog/data-engineering-software-troubleshooting/

 

데이터 엔지니어링 관련 소프트웨어 장애 대응 사례 - LINE ENGINEERING

안녕하세요. LINE Data Labs에서 데이터 엔지니어로 일하고 있는 Keiji Yoshida입니다. 저는 이번 글에서 데이터 엔지니어링 관련 소프트웨어 장애 대응 사례를 몇 가지 소개하고자 합니다.

engineering.linecorp.com

 

2. 왜 굳이 도커(컨테이너)를 써야 하나요?

도커 관련 문서 중 가장 쉽고 친절하게 도커를 써야하는 이유와 필요성에 대해 잘 정리된 글이다.

도커가 궁금했던 분들이나 앞으로 도커를 사용할 계획이 있는 분들이 읽어 보면 좋을 듯 하다.

https://www.44bits.io/ko/post/why-should-i-use-docker-container

 

왜 굳이 도커(컨테이너)를 써야 하나요? - 컨테이너를 사용해야 하는 이유

컨테이너는 서버 애플리케이션을 배포하고 서버를 운영하는 표준적인 기술이 되어가고 있습니다. 하지만 처음 사용해본다면 그 장점이 잘 와닿지 않을 수도 있습니다. 왜 굳이 도커 컨테이너를 사용해야할까요? 이 글에서는 눈송이 서버를 넘어 컨테이너가 애플리케이션 배포와 운영에 있어 어떤 장점이 있는지 알아봅니다.

www.44bits.io

 

3. 스프링부트(SpringBoot)에서 Request 유효성 검사하는 방법

프론트도 그렇고 백엔드도 그렇고 기본적인 validation체크가 기본이 되는 요즘, 해당 포스팅에서 스프링부트에서 Validation을 처리하는 방식과 커스텀 어노테이션을 통해 입맞게 맞게 유효성을 체크하는 핵심 내용을 잘 정리해 주신 것 같다.

https://jeong-pro.tistory.com/203

 

스프링 부트에서 Request 유효성 검사하는 방법, 서버 개발한다면 꼭 해야하는 작업 Spring Validation

스프링부트에서 Request로 오는 객체(DTO)를 어떻게 검증하는가에 대한 이야기 데이터 검증(validation)은 여러 계층에 걸쳐서 발생하는 흔한 작업이다. 어떻게하면 깔끔하게 유효성 검사를 할 수 있을지 생각해보..

jeong-pro.tistory.com

 

4. AOP에 걸린 Method의 Parameter이름 가져오기

스프링에서 AOP를 사용할 때 AOP에 걸린 Method의 매개변수(Parameter)를 가져오는 방법에 대해 잘 정리된 포스팅

https://alwayspr.tistory.com/34

 

AOP에 걸린 Method의 Parameter 이름 가져오기

먼저, AOP가 뭔지에 대해 알아보자. Aspect-Oriented Programming 이란 프로그램 구조에 대해 또 다른 사고방식을 제공함으로써 Object-Oriented Programming을 보완한다. OOP 모듈성의 핵심 단위는 클래스인 반면..

alwayspr.tistory.com

 

 

 

5. 병아리 개발자의 걸음마 한 발짝

신입 개발자분이 입사 후 프로젝트를 하며 작성한 코드에 대해 시니어 개발자들로 부터 코드리뷰를 받고 성장해 나가는 내용으로 생생하게 포스팅을 남겨 주셨다. 글을 읽다보면 코드 리팩토링, 객체지향에 기반한 코드리뷰 내용 등 기본이 되는 내용들을 많이 수록하고 있어 다시 한 번 중요 내용들을 되짚어 보는 시간을 가질 수 있었던 것 같다.

http://woowabros.github.io/experience/2019/09/10/pilot-project.html

 

병아리 개발자의 걸음마 한 발짝 (feat. 파일럿 프로젝트) - 우아한형제들 기술 블로그

지원서에서 발췌한 내용 …나름대로 제일 좋은 방법이라고 생각했던 해결책이 경험 많은 개발자분들이 보시기에는 어떤지, 시니어 개발자분들은 문제가 생겼을 때 어떻게 접근하고 어떻게 해결하는지 등도 항상 궁금해 왔습니다. …

woowabros.github.io

 

6. 스프링부트(SpringBoot) 2.2변화에 대해

물론 스프링부트 다큐먼트를 읽어도 되지만 한국 말로 친절하게 잘 설명되어져 있는 글을 읽음으로써 어떠한 부분들이 변경이되었는지 시간 날 때 차분히 읽어보면 좋을 만한 글인 것 같아 남겨본다.

http://wonwoo.ml/index.php/post/category/web/spring-boot

 

spring-boot – 머루의개발블로그

오늘은 Spring의 WebClient의 사용법에 대해서 몇가지 알아보도록 하자. 사용 API만 살펴 볼 예정이므로 reactive streams(reactor..) 들의 개념과 사용법은 다른 블로그를 살펴보길 바란다. reactive streams 대한 내용을 알고 보면 좋지만 몰라도 코드를 보는데는 문제가 없을 듯 하다. WebClient는 Spring5 에 추가된 인터페이스다. spring5 이전에는 비동기 클라이언트로 AsyncRestTemplat

wonwoo.ml

 

 

 

반응형
반응형

scala 패턴매칭 관련해서 이전 문서 보다가 스터디하면서 정리했던 내용이 있길래 블로그로 무브

 

패턴 매칭

단순 매치

val bools = Seq(true, false)

for (bool <- bools) {
  bool match {
    case true => println("Got heads")
    case false => println("Got tails")
  }
}

컴파일러는 시퀀스의 타입으로부터 그 원소에 true와 false라는 두가지 경우가 있음을 안다.
따라서 매치가 완전하지 않을 경우 경고를 표시한다.
또한 일치하는 case 절이 없는 경우 MatchError가 발생한다.


매치 내의 값, 변수, 타입

특정 값이나 특정 타입의 모든 값과 매치시킬 수 있다.

{code:scala}

for {
  x <- Seq(1, 2, 2.7, "one", "two", 'four)                           // <1>
} {
  val str = x match {                                                // <2>
    case 1          => "int 1"                                       // <3>
    case i: Int     => "other int: "+i                               // <4>
    case d: Double  => "a double: "+x                                // <5>
    case "one"      => "string one"                                  // <6>
    case s: String  => "other string: "+s                            // <7>
    case unexpected => "unexpected value: " + unexpected             // <8>
  }
  println(str)                                                       // <9>
}

{code}

결과
int 1
  other int: 2
  a double: 2.7
  string one
  string: two
  unexpected value: 'four

- 매치는 앞에서부터 차례대로 처리된다.
- 구체적인 절이 앞으로 나와야 한다.
- 덜 구체적인 절은 뒤로 가야 한다.
- 기본절은 가장 마지막에 와야한다.

 

{code:scala}

def checkY(y: Int) = {
  for {
    x <- Seq(99, 100, 101)
  } {
    val str = x match {
      case y => "found y!" //  `y`(역 작은 따옴표)
      case i: Int => "int: "+i
    }
    println(str)
  }
}
checkY(100)

{code}

결과
int:99
found y!
int: 101
--------'y'일 경우--------
found y!
found y!
found y!

 

- case 절에서 소문자로 시작하는 이름은 뽑아낸 값을 저장할 새로운 변수 이름으로 간주한다
- 정의한 값을 참조하고 싶을 경우 역작은따옴표로 둘러싸야 한다.
- 대문자로 시작하는 이름은 타입 이름으로 간주된다.
- '\|'를 사용해서 *case \: Int \| \:Double => "Int or Double?"* 과 같이도 사용가능하다.

 

시퀀스에 일치시키기


Seq 는 정해진 순서대로 원소를 순회할 수 있는 List나 Vector 등의 모든 구체적인 컬렉션 타입의 부모 타입이다.
(Seq는 시퀀스('sequence 순서가 정해진 열')이라는 뜻에서 온 말이다)

{code:scala}
val nonEmptySeq    = Seq(1, 2, 3, 4, 5)                              // <1>
val emptySeq       = Seq.empty[Int]
val nonEmptyList   = List(1, 2, 3, 4, 5)                             // <2>
val emptyList      = Nil
val nonEmptyVector = Vector(1, 2, 3, 4, 5)                           // <3>
val emptyVector    = Vector.empty[Int]
val nonEmptyMap    = Map("one" -> 1, "two" -> 2, "three" -> 3)       // <4>
val emptyMap       = Map.empty[String,Int]

def seqToString[T](seq: Seq[T]): String = seq match {                // <5>
  case head +: tail => s"$head +: " + seqToString(tail)              // <6>
  case Nil => "Nil"                                                  // <7>
}

for (seq <- Seq(                                                     // <8>
    nonEmptySeq, emptySeq, nonEmptyList, emptyList,
    nonEmptyVector, emptyVector, nonEmptyMap.toSeq, emptyMap.toSeq)) {
  println(seqToString(seq))
}

- Nil : 비어있는 List를 표현하는 객체, 이 객체는 모든 빈 시퀀스와 일치한다 (List가 아닌 컬렉션에도 Nil을 사용할 수 있다)
- tail : Seq에서 머리를 제외한 나머지 부분

결과
1 +: 2 +: 3 +: 4 +: 5 +: Nil
Nil
1 +: 2 +: 3 +: 4 +: 5 +: Nil
Nil
1 +: 2 +: 3 +: 4 +: 5 +: Nil
Nil
(one,1) +: (two,2) +: (three,3) +: Nil
Nil


- Map은 순회 시 특별한 순서를 보장하지 않기 때문에 Seq의 서브타입이 아님 (따라서 Map.toSeq를 호출해 키-값 튜플의 시퀀스 만들어 주어야함)
- 연산자 +: 는 시퀀스의 '콘즈' 연산자다. 메서드 이름이 콜론(:)으로 끝나면 오른쪽으로 결합되어 Seq의 꼬리에 대한 호출이 됨을 기억 (List :: 연산자와 비슷)

 

h3. 4.4 튜플에 일치시키기

{code:scala}
val langs = Seq(
  ("Scala",   "Martin", "Odersky"),
  ("Clojure", "Rich",   "Hickey"),
  ("Lisp",    "John",   "McCarthy"))

for (tuple <- langs) {
  tuple match {
    case ("Scala", _, _) => println("Found Scala")                   // <1>
    case (lang, first, last) =>                                      // <2>
      println(s"Found other language: $lang ($first, $last)")
  }
}
{code}

결과
Found Scala
Found other language: Clojure (Rich, Hickey)
Found other language: Lisp (John, McCarthy)

 

케이스 클래스에 일치시키기

{code:scala}
case class Address(street: String, city: String, country: String)
case class Person(name: String, age: Int, address: Address)

val alice   = Person("Alice",   25, Address("1 Scala Lane", "Chicago", "USA"))
val bob     = Person("Bob",     29, Address("2 Java Ave.",  "Miami",   "USA"))
val charlie = Person("Charlie", 32, Address("3 Python Ct.", "Boston",  "USA"))

for (person <- Seq(alice, bob, charlie)) {
  person match {
    case Person("Alice", 25, Address(_, "Chicago", _)) => println("Hi Alice!")
    case Person("Bob", 29, Address("2 Java Ave.", "Miami", "USA")) =>
      println("Hi Bob!")
    case Person(name, age, _) =>
      println(s"Who are you, $age year-old person named $name?")
  }
}
{code}

결과
Hi Alice!
Hi Bob!
Who are you, 32 year-old person named Charlie?

 

-zipWithIndex : 튜플을 번호와 함께 출력하고 싶을 경우 사용

{code:scala}
val itemsCosts = Seq(("Pencil", 0.52), ("Paper", 1.35), ("Notebook", 2.43))
val itemsCostsIndices = itemsCosts.zipWithIndex
for (itemCostIndex <- itemsCostsIndices) {
  itemCostIndex match {
    case ((item, cost), index) => println(s"$index: $item costs $cost each")
  }
}
{code}

결과
itemsCostsIndices  : Seq[((String, Double), Int)] = List(((Pencil,0.52),0), ((Paper,1.35),1), ((Notebook,2.43),2))
0: Pencil costs 0.52 each
1: Paper costs 1.35 each
2: Notebook costs 2.43 each

 

apply, unapply 메서드

- 케이스 클래스의 특징 중 하나는 컴파일러가 모든 케이스 클래스에  대해 각 클래스와 이름이 같은 싱글턴 객체인 *동반 객체*를 자동으로 만들어 낸다.
(동반 객체는 직접 정의도 가능하다.)
* Companion Class (동반 클래스) : (객체 관점) 클래스의 이름이 싱글톤 객체의 이름과 같다.

* Companion Object (동반 객체) :  (클래스 관점) 싱글톤 객체의 이름이 클래스의 이름과 같다.

{code:scala}

case class Point(x: Double = 0.0, y: Double = 0.0)

> 만들어지는 동반 객체
object Point {   def apply(x: Double = 0.0, y: Double = 0.0) = new Point(x,y)}

> 동반 객체에는 자동으로 apply라는 메서드가 추가되고 동반 클래스의 생성자와 같은 인자를 받는다.
> 객체 뒤에 인자 목록을 덧붙이면 스칼라는 그 객체의 apply를 호출하기 위해 찾는다.
val p1 = Point.apply(1.0, 2.0)val p2 = Point(1.0, 2.0)둘은 동등한 식이라고 볼 수 있다.
Point.apply 메서드는 사실상 Point를 만드는 팩토리로 단지 동작은 new 키워드 없이 생성자를 호출하는 것과 같다.

{code}

unapply

{code:scala}

object patternMatching2 {
  object Test {
    def unapply(a: Int): Boolean = {
        if (a < 10) { true }
        else { false }
    }
}

object Test2 {
    def unapply(a: Int): Option[(Int, String)] = {
        if (a > 30) { Some(a/10, "from Test2") }
        else { None }
    }
}

class Example {
    def method(target: Int) {
        target match {
            case Test() => println("matched to Test")
            case Test2(n @ Test(), m) => println("result: " + n + " " + m)
            case 120 => println("match to 120")
            case 11 => println("noneMatching")
        }
    }
}

val t = new Example                               //> t  : patternMatching2.Example = patternMatching2$Example@593634ad
t.method(11)                                      //> matched to Test
t.method(40)                                      //> result: 4 from Test2
t.method(120)                                     //> match to 120
}

{code}

- n, m은 Test2로부터 리턴받을 아큐먼트
- 돌려받는 아규먼트에 다른 extractor를 @로 연결하면 해당 값에 대한 패턴매칭을 추가로 적용할 수 있다.

 

케이스 절의 변수 바인딩에 대해 더 살펴보기

객체 자체에도 변수를 대입하고 싶은 경우
p @ ...문법은 전체 Person 인스턴스를 p에 대입하며, a @ ...부분도 비슷하게 Address 객체를 대입한다.

{code:scala}

case class Address(street: String, city: String, country: String)
case class Person(name: String, age: Int, address: Address)

val alice   = Person("Alice",   25, Address("1 Scala Lane", "Chicago", "USA"))
val bob     = Person("Bob",     29, Address("2 Java Ave.",  "Miami",   "USA"))
val charlie = Person("Charlie", 32, Address("3 Python Ct.", "Boston",  "USA"))

for (person <- Seq(alice, bob, charlie)) {
  person match {
    case p @ Person("Alice", 25, address) => println(s"Hi Alice! $p")
    case p @ Person("Bob", 29, a @ Address(street, city, country)) =>
      println(s"Hi ${p.name}! age ${p.age}, in ${a.city}")
    case p @ Person(name, age, _) =>
      println(s"Who are you, $age year-old person named $name? $p")
  }
}
{code}

결과
Hi Alice! Person(Alice,25,Address(1 Scala Lane,Chicago,USA))
Hi Bob! age 29, in Miami
Who are you, 32 year-old person named Charlie? Person(Charlie,32,Address(3 Python Ct.,Boston,USA))

 

패턴 매칭의 다른 사용법

if 식에서도 패턴 매칭을 사용할 수 있다.
{code:scala}
val p = Person("Alice",   25, Address("1 Scala Lane", "Chicago", "USA"))

if ( alice == Person("Alice", 25, Address("1 Scala Lane", "Chicago", "USA")))
     "yes" 
else "no"

 

결과
res0: String = yes

위치지정자 _는 여기서 사용할 수 없다.
== 검사에 사용할 $eq$eq라는 내부 함수가 있다.
JVM 명세에서는 식별자에 알파벳, 숫자, _, $만 사용할 수 있기 때문에, 스칼라는 그 외의 문자를 JVM이 받아들일 수 있는 문자열로 조작한다.
그래서 =은 $eq가 된다.

 

마치며


- 정보를 정제된 방식으로 추출해야 하는 경우 패턴 매칭을 고려하라.
- for 내장과 함께 패턴 매칭은 자주 사용하는 스칼라 코드를 간결하면서 강력하게 만들어준다.
- 스칼라 프로그래머가 1/10 정도의 줄 수로 자바로 만든 프로그램과 비슷한 기능을 작성하는 경우도 드물지 않다.
- 패턴 매칭은 여러 함수형 언어의 보증서로 데이터 구조로부터 데이터를 뽑아내는 유연하고 간결한 기법이다.

반응형
반응형

설치환경 : 리눅스 centos7버전 때

 

기본 환경설정(git)

추후 superset git repository clone을 위해 필요

sudo yum install git

docker 설치 centos7

참고문서 : https://linuxize.com/post/how-to-install-and-use-docker-on-centos-7/

1. Start by updating your system packages and install the required dependencies:

sudo yum update
sudo yum install yum-utils device-mapper-persistent-data lvm2


2. Next, run the following command which will add the Docker stable repository to your system:

sudo yum-config-manager --add-repohttps://download.docker.com/linux/centos/docker-ce.repo


3. Now that the Docker repository is enabled, install the latest version of Docker CE (Community Edition) using yum by typing:

sudo yum install docker-ce


4. Once the Docker package is installed, start the Docker daemon and enable it to automatically start at boot time:

sudo systemctl start docker sudo systemctl enable docker

5. To verify that the Docker service is running type:

sudo systemctl status docker

 

Executing the Docker Command Without Sudo #

By default managing, Docker requires administrator privileges. If you want to run Docker commands as a non-root user without prepending sudo you need to add your user to the docker group which is created during the installation of the Docker CE package. You can do that by typing:

 

sudo usermod -aG docker ${USER}

$USER is an environment variable that holds your username.

 

Docker Compose 설명 및 설치


1. docker-compose download

sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose


2. APPLY EXECUTABLE PERMISSION TO THE BINARY
sudo chmod +x /usr/local/bin/docker-compose

 

3. alias setting

sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

docker, docker-compose 설치 이후 compose실행시 에러가 난다면 해당 세션창을 나갔다가 다시 접속해야한다.

superset source code clone & install

1. clone superset source codegit clone https://github.com/apache/incubator-superset/

 

2. dockerfile 수정

# First, we just wanna install requirements, which will allow us to utilize the cache

# in order to only build if and only if requirements change

COPY ./requirements.txt /app/ RUN cd /app \         && pip install --no-cache -r requirements.txt

해당 부분에 pip로 사용할 라이브러리들 추가

COPY ./requirements.txt /app/

RUN cd /app \        

      pip install --upgrade pip \        

      && pip install --no-cache -r requirements.txt \        

      && pip install mysqlclient \        

      && pip install impyla \        

      && pip install redis==3.2.1 \        

      && pip install gevent==1.2.2 \        

      && rm -rf /root/.cache/pip

 

 

3. docker-compose.yml 파일 수정

version: "3.7" => version: "3.4"
  superset:
    ports:
      - 8088:8088  => -8089:8088     (8088포트로 띄울 경우 정상적으로 동작안함)

4. docker-compose up

docker-compose up 명령어로 dockerfile의 이미지를 읽어가며 설치

docker-compose up

기존 리서치 superset에서 발생했던 이슈

1. 다운로드한 CSV가 엑셀로 열 경우 한글이 깨지는 문제 수정

2. sql tab이 한글명일 경우 정상적으로 csv다운로드 안되는 이슈 처리

vi /home1/irteam/incubator-superset/superset/views/core.py

 

docker기반 superset 설치시 발생했던 이슈 정리

1.설치는 되었는데 default id/pw가 생성이 안되어 있을 경우 =>  docker-init을 통하여 계정 설정


docker-init

## Initializing Database To initialize the database with a user and example charts, dashboards and datasets run:

```bash

docker-compose run -e SUPERSET_LOAD_EXAMPLES=yes --rm superset ./docker-init.sh

 

2. docker-compose.yml 내부의 버전과 docker-compose 버전이 맞지 않는 경우

[incubator-superset]$ docker-compose up



ERROR: In file './docker-compose.yml' service 'version' doesn't have any configuration options. All top level keys in your docker-compose.yml must map to a dictionary of configuration options.

해결책 docker-compose version 3.7 -> 2버전대로 낮추거나 docker-compose 버전을 높여주어야 한다.
참고 : https://github.com/docker/compose/issues/3331

 

3. 알파환경에서는 문제가 없었는데 리얼환경에서 클러스터 OS Partition 차이로 인한 이슈

-> docker-compose up 명령어 실행시 발생

ERROR: Service 'superset' failed to build: OCI runtime create failed: /var/lib/docker/overlay2/17f563586397ce35fab5733d85b37fc68073a42eb4a5044025e68fd89e87b573/merged is not an absolute path or is a symlink

해결책

# 실행되고 있는 docker stop
$ sudo systemctl stop docker

# 잘죽었는지 확인
$ sudo systemctl status docker

# 원하는 디렉터리 이동을 위한 디렉터리 생성
$ sudo mkdir /mnt/extra

# 기존 문제 발생했던 디렉터리의 내용들을 새로 만든 디렉터리로 이동
$ sudo mv /var/lib/docker /mnt/extra

# 링크생성
$ sudo ln -s /mnt/extra/docker /var/lib/docker

# docker 시작
$ sudo systemctl start docker

# docker 잘올라왔는지 상태 확인
$ sudo systemctl status docker

# 재설치 (iteam) $ docker-compose up

 

반응형
반응형

토이프로젝트를 하던 중 쿠키에 특정 값을 만들어 굽는 작업이 필요했다.

따라서 HttpServletResponse에 addCookie를 하여 쿠키를 구워줬지만 브라우저 개발자도구에서 눈을 씻고 찾아봐도 보이지가 않았다...

 

문제는 Cookie의 path를 설정해주지 않아서였다...

 

쿠키의 path를 설정해주지 않으면 현재 경로에서만 only valid하도록 처리되기 때문에

리다이렉트 되면서 유효하지 않기에 사라져 버리는 것이다.

 

[ 문제코드 ]

쿠키에 setPath를 지정해주지 않음...

 

[ 문제 해결 ] 

setPath를 루트로 지정

 

ref : https://stackoverflow.com/questions/35828087/setting-cookie-not-working-in-spring-web-mvc-4

반응형

+ Recent posts