반응형


회사에서 '광고에서 배운 창의력 세미나'주제로 세미나가 열렸다.

TBWA KOREA대표이시자 '여덟 단어', '책은 도끼다'의 저자인 

박웅현대표님(58세이심에도 크리에이터답게 패션센스가 ㅎㄷㄷ)이 오늘의 강연자!


말씀하셨던 내용중 핵심문구들만 쏙!쏙! 뽑아 포스팅~!!!



[ 강의 내용 ] 

-창의성은 문화이다. (젊은 사람들이 모이면 시끄러워야 한다. S기업 H기업의 군대문화에서는 창의성 발휘 힘들다 > 너무 뻔한말?!)
-옷만 캐주얼해지지 말자 생각도 같이 캐주얼해지자 (실제로 너무 캐주얼한 패션에 깜짝놀람...)
-광고는 제품의 문제점을 찾아내서 어떻게 문제를 풀어내는가가 중요하다. (알아도 매우 힘든...)

-뱀파이어 효과 : 광고에서 광고하려는 상품이나 브랜드를 광고에 나오는 연예인이 다 흡수해버리는 것을 말한다.  
-광고는 전능하지 않습니다. 그렇다고 무능하지도 않습니다. 
-광고의 힘은 점점 빠지고 있다. 예전에는 kbs, sbs, mbc광고 3번이면 전국민이 알정도였다. (지금은 유트브(1인 채널) 및 sns로 인한 채널 다양화)

-창의성은 '무엇을 하느냐 보다 어떻게 하느냐'에서 비롯된다. 
-다독에 대한 욕심을 버리고 그 책을 씹어먹어라. 밑줄치고, 타이핑하면 3번을 보는 효과 (저랑비슷ㅎㅎ)
-창의성은 삶의 태도와도 연관있다.(돈키호테력)
    -> 돈키호테력 원천 - 재미있는 일을 좇는 것, 사소한 것에 집중하는 것

-창의성과 발상은 같지 않다.(신선한 생각이 창의성은 아니다.) 발상을 실행할 수 있는 나머지가 훨씬 더 중요하다. 그 나머지는 바로 아래

-창의력은 과정관리, 실행력, 무모함, 대담함, 용기, 실패, 고집, 위험, 자기 확신, 끈기의 집합체이다.
-아이디어는 마치 씨앗과 같다. 물을 주고 영양분을 주면 점점 자라난다.

-말한 사람이 발견하지 못하는 가치를 발견해주는 사람이 되고 싶다.(58세 강사님의 앞으로의 목표...멋지심)
-Creativity의 반대말은 Safety이다.
-Idea에서 copy 한 줄이 나오기까지 보통 2달이 걸린다. 

(가끔 책을 읽다가 뭔가가 떠올라 생각을 정리하는데 너무 오래걸려 답답함을 느낀적이있었다. 

생각을 정리하는 시간을 아까워도 답답해하지도 말고 꼭 정리하는 시간을 가지자. 나보다 더 훌륭한 분들도 저렇게나 오래걸리는걸?! )

-말로해서는 안팔려서 영상을 만들었다. 백 날 말만해서는 상품을 팔 수 없다. 
-뿌리깊은 나무(잡지, 1976년 창간)은 대한민국 출판계의 '비틀즈'이다.
-창의성은 처음 충격에서 시작해 나중엔 상식이 된다.
-늘 하던대로 하면서 새로운 것을 기대하는 것은 Insane(미친)이다.


강의를 들으면서 느낀 생각
- 이 아저씨 나랑 비슷하다. 듣다보면 결국 자기자랑이다. 자기애가 매우 강할 것 같다.
- 아저씨가 말하는 창의력이 행동력이 중요한 것이라면 나는 충분히 창의적인 사람이다.
- 사람들을 생각하는 콘텐츠(영상)을 제작해보고 싶다.그것의 방향성에 대해서는 아직 잘 모르겠다.

오늘 내가 한 질문
Question :  광고업계에서 그 광고의 상품이나 브랜드보다 연예인만 기억이 남는 경우 '뱀파이어 효과'라고 한다고 하셨는데요.
오늘 강사님의 강의를 들으며 무척 재미있었지만 이 시간이 지난 이후에는 강사님의 바지만 기억에 남는 뱀파이어 효과를 경험할 것 같습니다.
저와 같은 청중이 있다는 걸 알았을 때 강사니므이 오늘 패션에 대한 스스로의 생각이 어떠신지 궁금합니다.

Answer 

그렇게 느끼셨다면 패션이 잘못됬네요~(중간 기억 안남)~패션도 signal이라고 생각합니다.(또 기억안남)ㅎㅎ사실 많은사람들앞인지라 질문끝나고 긴장이 풀려 잘 못들은듯...

하지만 생각보다 크리에이티브 내 만족도를 채워주는 답변은 아니였던듯


포스팅 끝~!

반응형
반응형

[ Javascript ] 자바스크립트 ajax 크로스도메인 이슈(CORS)

특정 서버의 API를 테스트해야하는 페이지를 작업중 크로스도메인 이슈에 맞닥뜨리게 되었다.
예전 고객센터시스템 개발할 때 자주접하던 이슈였기에 쉽게 해결할 수 있을 줄 알았으나....꽤나 삽질을 많이 했다.
그래서 겸사겸사 정리하며 다시 한 번 머리에 각인!

1. 크로스도메인이슈 (CORS, Cross Origin Resources Sharing)

jQuery 1.5.0이후 버전부터는 이러한 crossdomain을 원천 봉쇄해버렸다.
테스트페이지(웹) -> 쿠키매칭시스템API호출
 http://alpha-adserver.toast.com/ -> http://cm-exchange.toast.com

크로스 도메인은 서로 다른 도메인 간 호출로 위와 같이 호출하게되면 크로스도메인이슈가 발생하게 된다.
보통 서브도메인만 다른 경우의 사이트끼리의 정보 교환은 document.domain만 맞추어 주면 해결이 가능하다.
ex)
1. abc.toast.com
2. def.toast.com
사이트끼리의 정보 교환은 해당페이지 스크립트에 document.domain='toast.com' 설정시 해결가능

하지만 이번 경우에는 브라우져 -> 서버간의 호출로 다음과 같은 문제로 해결이 힘든 상황.
따라서 javascript, ajax로 요청시 다음과 같은 에러가 발생
스크린샷 2018-07-25 오후 5.16.21.png
이렇게 외부로 요청이 안되는 것은 자바스크립트 엔진 표준 스펙의 동일 출처 정책(SOP, Same-Origin Policy)이라는 보안 규칙이 있기 때문


2. 동일 출처 정책 (SOP, Same-Origin Policy)

웹어플리케이션 보안 모델에서 중요한 개념중 하나
해당 정책으로 인해 자바스크립트(XMLHttpRequest)로 다른 웹페이지 접근시 같은 출처(same origin)의 페이지에만 접근 가능하다.
같은 출처라는 것은 Protocol, Host명, Port가 같다는 것을 의미
쉽게 말해, 웹페이지의 스크립트는 그 페이지와 같은 서버에 있는 주소로만 ajax요청을 할 수 있다는 것이다.
스크린샷 2018-07-25 오후 5.19.29.png


3. CORS 작동 방식

스크린샷 2018-07-25 오후 5.21.56.png
Preflight request(사전요청) - 요청하려는 URL이 외부 도메인일 경우 웹 브라우저는 preflight요청을 먼저 날린다.
preflight요청은 실제로 요청하려는 경로와 같은 URL에 대해 OPTIONS 메서드로 요청을 미리 날려보고 요청 할 수 있는 권한이 있는지 확인한다.
CORS요청을 편법없이 처리하기 위해서는 클라이언트 처리만으로는 어렵고 서버측에서 preflight요청을 처리하는 기능이 필요하다.


4. CORS 해결할 수 있는 방법.

1) 웹 브라우저 실행옵션이나 플러그인인을 통한 동일출처 정책 회피(크롬 --disable-web-security옵션을 추가하여 실행)

-> 테스트하는 컴퓨터마다 설정해야하는 번거로움으로 X

2) jsonp(json with padding)를 통한 해결

JSONP는 HTML의 script 요소로부터 요청되는 호출에는 보안상 정책이 적용되지 않는다는 점을 이용한 우회 방법
다시 한번 확실히 하자면, script 요소는 src를 호출한 결과를 javascript를 불러와서 포함시키는 것이 아니고 실행시키는 태그입니다.

다음과 같이 dataType만 변경해서 보내면된다??? nono 서버에서 수정해줘야 함...(일반적인 웹사이트에서는 dataType만 jsonp로 고치면 된다는 식으로 말하고있음...)

$.ajax({
    type: 'GET',
    url: url,
    dataType: 'jsonp',   //cross-domain 이슈를 회피하기 위해 jsonp요청을 한다.
    success: callback    //callback이란 함수를 나의 success function에 매핑시켜 콜백요청을 처리할 것이다.
});

or

$.getJSON(url + "?callback=?", data, callback);</span>

RESPONSE의 경우
callback({'kingbbode', age:28})

이처럼 Callback 함수명으로 감싸져서 오는데 서버에서 위와같이 감싸진 형태의 Text로 내려주어야한다!!!!
Text로 내려진 데이터가 Javascript로 실행되는 과정을 Jquery에서 지원하여 Success 함수로 연결시켜 주는 것이다.

정확한 서버구현과 내용은 참고 : jsonp참고페이지

**-> 서버를 건드릴거면 Accss-Control-allow-origin만 설정해주는 것이 훨씬 간편... **

3) 중간에 proxy서버를 두는 방법

-> 배보다 배꼽이 더큰 상황...

4) jquery.ajaxPrefilter()

ajax요청전 내부적으로 $.ajaxPrefilter()를 거친다. 따라서 ajaxPrefilter()내부를 변조하면 cross-domain문제를 해결할 수 있다. 라는 느낌?
밑의 코드는 통신 자체를 'jsonp'로 속여 보내는 방식으로 처리가능하다고 하는데 나의 경우는 정상동작 안함...(http://igna.tistory.com/20?category=430584)

$.ajaxPrefilter('json', function(options, orig, jqXHR) {
    if (options.crossDomain && !$.support.cors) return 'jsonp'
});

$.ajax({
    type: 'GET',
    crossDomain: true,
    url: url,
    dataType: 'json',
    success: function(data, textStatus, xhr) {        $('#bidValue').val(JSON.stringify(data));
}});

5) 서버에서 Accss-Control-allow-origin 설정을 통한 요청 허용

API컨트롤러에 다음과 같은 애노테이션 선언
특정 도메인만 허용하고 싶은 경우에는 별도 config로 설정 후 사용
참고 : 스프링에서 cors설정

@CrossOrigin("*")

>> 결국에는 서버에 Accss-Control-allow-origin으로 특정 도메인을 풀어주는 것으로 해결

ref :  http://enterkey.tistory.com/409


반응형
반응형

[ jQquery ] jQuery(제이쿼리) 플러그인으로 쿠키 다루기


자바스크립트로도 쿠키를 control할 수 있으나~! jQuery Plugin을 이용하면 훨씬 더 직관적으로 쉽게


쿠키를 컨트롤 할 수 있다.


# 자바스크립트로 쿠키의 특정값을 가져오는 경우


# jQuery Plugin을 사용해서 쿠키 특정값을 가져오는 경우



위에서 보듯 자바스크립트를 이용할 때보다 jQyery를 이용하는 방법이 훨씬 직관적이면서 쉬운것을 볼 수 있다.



사용방법


* cdn으로 jquery.cookie.js를 import해준다. (당연히 jQuery는 import되어 있어야겠죠?) 소스코드를 받아 프로젝트에 내장하는걸 권장

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"></script>


위의 스크립트를 import해주면 플러그인의 기능을 손쉽게 사용할 수 있다.


[ 쿠키저장 ] - 쿠키는 브라우저가 열려 있는 동안만 유지

$.cookie('key', 'value');


[ 쿠키만료일 지정 ] 

$.cookie('key', 'value', {expires: 값});


[ 쿠키삭제 ] - 특정도메인이 있는 쿠키의 값인 경우 도메인을 명시해주지 않으면 제대로 삭제되지 않는다. 

* expires기간을 오늘 이전 날짜로 셋팅해주면 자동으로 지워진다.

* 쿠키 설정시 domain과 path를 설정했을 경우 삭제시에도 동일하게 옵션으로 전달해야 삭제가능

$.cookie('BID', '', {domain : "toast.com", expires: new Date(2016, 10, 29, 11, 00, 00)});

혹은 다음처롬도 삭제 가능하다.

$.removeCookie('BID', {path: '/',domain: 'toast.com'});


[ 특정시간만료시 삭제 & secure를 true로 설정시 https를 통해서만 쿠키값을 전송가능하다 ] 

$.cookie(visits, 10, {expires: new Date(2019, 10, 29, 11, 00, 00), secure: true});


자바스크립트를 사용하든 jQuery플러그인을 선택하든 선택은 자유:)

반응형
반응형

생각의 비밀 -김승호 지음-

간만에 전공서적 이외의 서적을 집어 들었다. 뻔한 스토리이지만 아무나 실천하지 못하는 내용들이 담긴 자기계발서적은 삶에 대한 열정이 식어가고 뚜렷한 목표가 희미해져가는 시점에 불을 지펴주는 역할을 한다. 

아래의 내용은 책을 읽으며 공감가거나 참신한 표현이라고 생각되는 부분들에 대한 정리이다.

  • 내 생각을 끊임없이 자극할 만한 환경만 만들어주면 무엇이든지 얻게 된다는 것이 내 경험의 소산이다
  • 배우려 하고 도전하려는 사람들에겐 조그만 틈새로도 빛이 들어오는 것이 보이고, 그 빛을 그냥 지나치지 않는 호기심과 열정이 있다. 이 열정이 성공의 문을 만드는 것이다.
  • 긍정적 마인드를 가진 사람을 이긴다는 것은 거의 불가능하다. 결국 작은 확률이라도 잡아내는 사람은 그 확률을 믿고 기다린 사람이기 때문이다.
  • 성공이란 오래된 습관의 결정체다. 그리고 이 습관이 만들어낸 판단 하나하나가 모여 실체를 이룬다.
  • 우리는 우리의 부모를 존중하는 법을 뒤늦게 배운 후 후회하는 일을 선사시대부터 계속해왔다.
    • (opinion) 역사에 대해 관심을 가지고 책으로부터 배운 지식들을 소중히 여기자. 직접경험해야만 경험할 수 있는 것은 아니다.
  • 역사는 반복되지만 역사를 통해 배우지 않는다는 것도 역시 반복된다는 것을 알 수 있다.
  • 장사란 본인이 모든 업무를 제일 잘 알아서 각 직원들에게 가르쳐주는 경우다. 그러나 직원들이 사장보다 각각의 업무를 더 잘할 때가 되면 진짜 사업이 시작된다.
  • 먼저 사실을 보고하고 의견을 나중에 말한다.
  • 불평을 하려면 대안도 함께 제시한다.
    • (opinion) 불평은 가급적 피하고 불가피한 상황이라면 대안을 함께 제시할 수 있는 사람이 되자.
  • 어떤 일이든 마감이 있고, 마감을 넘긴 일은 아무리 잘해도 칭찬이 없다.
    • 사과도 늦으면 아니한 것만 못하듯이 업무도 마감을 넘기면 아니한 것만도 못하다 생각한다.
      • (opinion) 항상 모든일에는 타이밍이라는 것이 있다. 그 타이밍을 알고 행동할 수 있는 사람이 되자.
  • 자신만 알고 있고 자신만 할 수 있는 일을 가지면 항상 그 일만 하거나 도태될 것이다.
    • (opinion) 내 지식을 전파하고 공유하면 더 많이 발전하고 새로운 것을 얻게 될 것이다. 
  • 문제가 있으면 언제나 답도 있다. 답이 없으면 문제를 바꿔라.
    • 문제란 풀기 위해 있는 것이고 문제를 해결함에 있어서 문제 자체를 없애는 정도까지의 수많은 해결책을 찾는 문화가 절실히 필요하다.
  • 단순함이란 자세함의 완성이다.
    • (opinion) 디테일의 힘에 대해 믿고 귀찮더라도 좀 더 디테일한 사람이 되도록 주위에 관심을 가지고 귀찮음을 이겨낼 줄 아는 사람이 되자.
  • 나라는 존재는 그동안 내가 생각해온 결과물이다. 지금 생각을 바꾸면 나도 바뀌고 미래도 바뀐다. 
    • 그 사람의 몸매란 그 사람의 생활습관의 결과물이다. 생활습관이 바뀌면 몸도 바뀐다. 
    • 좋은 몸매를 위해서는 다이어트가 아니라 생활습관을 바꾸면 된다. 
  • 실패해보지도 않은 사람이 어찌 도전해서 실패해본 사람에게 조언을 할 수 있다는 말인가. 실패하지 않았다 함은 도전해보지 않았다는 뜻이다.
    • (opinion) 내가 도전해보지 않은 분야의 실패한 사람에게 '왜그랬어'보다는 '큰 도전을 한 네가 대단하다'라는 말을 해줄수 있는 사람이되자.
  • 그 꿈이, 당신이 보기에 상상조차 못할 큰 꿈이라면, 상상도 못할 노력만 하면 된다. 상상도 못할 노력을 할 자신만 가지면 된다.
  • 당신이 미쳤다는 소리 한번 듣지 않고 살았다면 당신은 한번도 목숨 걸고 도전해본 적이 없다는 뜻이다.
    • (opinion) ㅎㅎ나 한번도 못들어본것 같은데...꼭 이번년도에는 미친듯 내 자신을 가꿔 내가 원하는 몸을 가지도록 해야겠다.
  • 나와 함께 웃을 수 있는 사람들이 내 주위에 항상 함께한다는 것을 느낄 때 삶에서의 성공을 실감한다.
    • (opinion) 성공을 실감하게 해주는 주위사람들에게 더 잘해야겠다.
  • 전문적인 역사 공부가 아니더라도 세게사 연표만 조금씩 이해하고 있다면 우리의 사고나 판단은 놀랍도록 달라진다.
  • 역사와 지리를 공부하지 않고서는 절대로 냉철한 판단을 할 수 없다. 일반적 판단을 따르는 사람은 사업에서 결코 앞서나가지 못한다.
  • 아내에게 "10분 안에 들어갈게"라고 약속했다면 10분 안에 뛰어서라도 들어가라. 시간약속에 충실한 사람이야말로 모든 성공의 지름길로 가는 것이다.
    • (opinion) 사소한 약속이라도 꼭 지킬 수 있는 사람! 약속에 대해 핑계거리를 만들지 않는 사람!
  • 비우고 정리하지 못하는 사람은 막상 필요로 하는 것을 얻게 돼도 넣을 수가 없다. 당신의 파트너나 직원이나 사위를 구할 때도 이 세 가지만 확인하면 미래가 좀 더 확실해질 것이다. 
    • (opinion) 물건도 인관관계도 생각도 정리가 필요하다.
  • 배움이 삶에서의 목표가 된 사람은 스스로 혼자 무엇인가를 이루거나 남을 이끌 수 없다. 배움은 스스로 독립적으로 생각하고 결과를 만들기 위함이어야 가치를 발휘한다.
  • 남들과 비슷하게라도 살려면 남들과 다르게 생각하거나 남들과 다르게 행동해야 한다. 남들보다 훨씬 더 뛰어나고 싶다면 이미 세상에서 누군가에 의해 형식화된 모든 것에 의문하는 버릇을 갖는 것이 첫걸음이다. 
  • 젊음과 아름다움은 잠시지만 함께 늙어갈수록 좋아지는 사람들이 있다. 그가 받은 삶의 주름이 헝클어져 있어도 여전히 아름답고 기품 넘치는 사람들이 있다.
  • 종이에 쓰인 생각은 실체다. 눈에 보이기 때문이며 스스로 존재하기 때문이다. 
  • 협상과 흥정이란 결국 상대가 원하는 것을 줌으로써 내 것을 가져오는 것이다.
  • 모든 것을 살 수 있어도 아무것도 사지 않는 것은 모든 것을 가진 것이나 마찬가지였다.
  • 밥값을 내지 않고 모은 돈들은 그 성향의 근본이 인색함에 기인하기 때문에 절대 성공하지 못한다. 어느 누구도 인색한 사람과 인간관계를 맺고 싶어 하지 않기 때문이다.
  • 부정한 방법으로 성공하여 생긴 이익은 이익이 아니라 빚이다.
    • (opinion) 부정한 방법으로 생긴 이익에 대해 경계하자. 진정한 내것이 아니다.
  • 리더로서의 가장 큰 약점은 자신의 약점을 인정하지 않으려는 태도다.
  • 리더란 자신의 능력이 뛰어난 사람이 아니라 얼마나 자신의 부족함을 채워줄 사람들을 주변에 모을 수 있느냐에 따라 그 크기가 결정된다.
  • 작은 리더들은 말을 많이 하며 항상 가르치려 들지만, 큰 리더가 되려는 사람은 남에게 많이 듣고 도움을 청하는 것이 결코 자신의 가치를 낮추지 않으며 오히려 높이게 된다는 점을 잘 알고 있다. 
  • 실패는 반복됬지만 패배는 반복되지 않았다. 
  • 주변을 공감하면 명분이 만들어지고 명분을 이해하면 동의를 이루어낸다.
  • 검소가 나를 벗어나는 순간 인색으로 변한다.
    • (opinion) 내 기준을 남에게 강요하지 말자
  • 말이 많으면 실수를 하기 마련이고, 말이 많으면 자랑하기 마련이다. 들어주고 묻는 것만으로도 힘 안들이고 상대의 존중을 받을 수 있다는 것을 왜 자꾸 잊는지 모르겠다.
  • 세상에는 흔히 세 가지 거짓말이 있다. 좋은 거짓말, 나쁜 거짓말, 그리고 통계다. 통계는 수학을 가장한 거짓말이다. 통계는 얼마든지 그 실제 정보와 상관없이 조작될 수 있다.



새롭게 알게 된 역사

  1. 예수가 태어날 무렵 주몽은 고구려를 건국했다.

  2. 만리장성은 신화처럼 여겨지는 예수 활동시기보다 200년을 앞서간다.

  3. 우리가 흔히 고대라는 표현을 쓰는 고대 아스텍 문명의 시작은 옥스퍼드 대학교보다 100년 늦게 시작했고 세종대왕이 훈민정음을 발표한 이후 100년 넘어서 멸망했다. 

  4. 공자, 노자, 석가모니, 소크라테스는 역사적으로 거의 동시대 사람이었고 막내 뻘인 소크라테스 사후 400년이 지나 예수는 태어난다.


(opinion)
자기서적이외에도 틈틈히 경제, 사회, 역사 등 다양한 분야의 책을 읽으며 지식을 쌓아야 겠다는 생각을 했다.


반응형
반응형

스프링부트(SpringBoot) 순차적 방식과 비동기처리(asyn애노테이션), Completablefuture와 성능 비교

Spring Boot 기반의 웹 애플리케이션은 HTTP 요청이 들어왔을 때 내장된 서블릿 컨테이너(Tomcat)가 관리하는 독립적인 1개의 Worker 쓰레드에 의해 동기 방식으로 실행된다. 하지만 요청 처리 중 @Async가 명시된 메써드를 호출하면 앞서 등록한 ThreadPoolTaskExecutor 빈에 의해 관리되는 또 다른 독립적인 Worker 쓰레드로 실행된다. 
별도의 쓰레드로 동작하기에 원래의 요청 쓰레드는 그대로 다음 문장을 실행하여 HTTP 응답을 마칠 수 있다.


배경

리얼환경에서의 서비스를 위해 실제 환경(l4 - API서버 3)에서 어느정도의 트래픽을 안전하게 처리할 수 있는지에 대한 산정 필요(서버 도입 시점 등)'

해당 테스트는 단순 select로직을 통한 테스트로 참고 부탁드립니다.

메서드 내에서 여러 곳으로부터의 데이터를 받아와 처리하는 작업이 있는 경우 async애노테이션, CompletableFuture를 사용한 방식이 훨씬이

성능상 훨씬 많은 이점을 가져다 줄 수 있습니다. 

테스트 로직

기존로직

기존로직.png

변경로직 (@Asyn 애노테이션과 CompletableFuture를 통한 비동기 처리)

변경로직.png

쿼리 (위 : 변경쿼리, 아래 : 기존쿼리)

쿼리.png

성능측정

L4장비에 트래픽 부하(gatling) - 부하 툴로는 gatling을 사용하였습니다. 무료로 사용할 수 있는 툴로 쉽게 사용하실 수 있습니다.

1. Request : 9000, Duration 10초  - TPS 300

기존 로직
cm_9000_1.pngcm_9000_2.png

변경로직

asyn_9000_1.pngasyn_9000_2.png

2. Request : 24000, Duration 10초  - TPS 800

기존로직                                                                 변경로직(ThreadPool - 200)                                변경로직(ThreadPool - 400)


ThreadPool설정값 조정

스프링부트를 사용할 경우 별도 application.properties에 server.tomcat.max-threads 다음설정을 해주지 않는 경우

기본 max-thread의 개수는 200개가 된다. (The default value for max-threads is 200)

따라서 400으로 올려서 테스트 진행


스레드의 개수를 600으로 두고 테스트를 했을 떄는 다음과 같은 에러가 발생했다.

[java.util.concurrent.ThreadPoolExecutor@18da28a1[Running, pool size = 741, active threads = 741, queued tasks = 200, completed tasks = 207]] did not accept task: java.util.concurrent.CompletableFuture$AsyncSupply@47ff8bc8] with root cause

java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.CompletableFuture$AsyncSupply@47ff8bc8 rejected from java.util.concurrent.ThreadPoolExecutor@18da28a1[Running, pool size = 741, active threads = 741, queued tasks = 200, completed tasks = 207]

        at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)

        at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)


3. 결론

1번 테스트(TPS 300) 결과를 보면 Asyn annotation과 Completablefuture를 사용한 쪽이 응답 속도가 훨씬 안정적으로 처리되는 것을 볼 수 있다.(99th percentile 기준)
2번 테스트 결과(TPS 800)를 봤을 때 1/3 정도의 요청이 fail나는 것을 확인 할 수 있었고 TPS 800 은 요청에 대한 fail비율과 응답속도(100ms 이내를 기준으로 한다)로 보았을 때 서버 3대로 처리할 수 있는 요청량이 아니라는 판단을 할 수 있다.
그 이후 TPS 400, 500, 600 700으로도 테스트 한 결과 안정적
(최대 50ms - 광고 비지니스 특성상)이내로 ADX, DSP에 값을 전달하기 위해서는 
최대 TPS 300을 기준으로 운영방침을 가져갈 수 있을 것 같다.

TPS 300 -> 한 서버당 하루요청량 2500만을 기준으로 둘 수 있겠다. 

(물론 카산드라 3.0에 데이터가 유입량과 로직 추가에 따른 부분을 항상 염두해 두어야 할 것이다.)



추가적으로, 비동기방식으로 처리를 했을 때 메모리, cpu사용률이 더 높은 것을 확인 할 수 있었다.

무작정 비동기방식이 좋다고 말할 수도 동기 방식이 좋다고도 말하기 힘들 것 같다.

단순한 작업은 동기 방식 한 메서드 내에서 순차적으로 이루어지지 않아도 되는 작업이 여러 개 있는 경우(DB호출, 외부 API호출 등)이 있는 경우에는

비동기 방식이 성능상 이점을 가져다 줄 수 있을 것이다.

반응형
반응형

 

일반적으로는 리눅스에서 빌드를 하는 경우가 많이는 없다.

 

보통은 git과 jenkins를 통해 빌드 배포하고 있기 때문에 하지만 내가 가지고 있는 프로젝트중에

 

hadoop mapreduce작업을 해서 cassandra에 밀어 넣는 처리를하는 경우가 있다.

 

이 경우 hadoop관련 jar파일이 필요한데 pom.xml  dependency 경로가 서버내의 cloudera경로에 걸려있어 

 

서버내에서 maven 빌드를 진행해주어야만 하는 경우가 있었다.(물론 해당 jar파일을 공통 레파지토리나 프로젝트내에 넣어 묶을 수 있긴한데...)

 

먼저 리눅스에서 maven 빌드를 실행하려면 서버에 maven이 깔려있는지 확인이 필요한다.

 

 

> mvn -v

 

깔려있지 않다면 먼저 maven 설치가 필요하다.

 

그리고 빌드를 해서 jar파일을 만들고자하는 프로젝트 경로로 이동해서 pom.xml이 위치한 곳에서 

 

mvn package를 실행해주면 된다. (profile이나 다른 옵션을 주는 경우 해당 명령어에 -P 등을 추가해주자)

 

 

> mvn package (pom.xml이 위치하고 있는 곳에서)

 

 

이렇게 빌드를 하게되면 필요한 dependency들을 다운받아와 jar를 만드는 것을 확인할 수 있다.

 

 

 

반응형

'Programming > Maven' 카테고리의 다른 글

mvn package시 test 코드 건너뛰기  (0) 2018.01.31
MAVEN과 ANT 비교  (0) 2017.05.10
반응형


Dataframe count중 scala.MatchError 발생 ( show 명령어는 정상적으로 먹는데??? )


간만에 스파크 작업을 진행하다가 다음과 같은 에러문구를 만났다.


Caused by: scala.MatchError: [Ljava.lang.String;@17f58fdb (of class [Ljava.lang.String;)


Text 파일을 sc.textFile("path") 로 읽어와 해당 RDD를 Dataframe으로 변환하고 dataframe.count시 발생하였다.



문제의 원인은  실제 텍스트파일내의 내용을 RDD로 읽어와 split으로 나눈 후 Dataframe으로 변형하는 과정에서 


컬럼개수가 일치하지 않는 데이터가 있었다.


text파일의 포맷은 다음과 같았다.


id    advid    itemid  itemName 

1       123      456      [아임닭] 닭가슴살~~~

.

.

.


이러한 RDD를 다음과 같이 Dataframe으로 만들려고 하였다.

val rawDataDF = rawData.map(_.split("\t") match { case Array(v1,v2,v3,v4) => (v1,v2,v3,v4)}).toDF(“id”, “advid”, “item_id”, “item_name”)


전혀 문제가 없을 것 같지만 이렇게 변경 후 count명령을 내려보면 MatchError가 발생하는 것이다.


알고보니 itemName에 상품명중 탭 구분자("\t")가 들어가 있었던 상품명이 있었던 것이다.



그래서 실제로는 4개의 컬럼으로 나누어져서 Dataframe이 만들어져야 하지만 상품명에 탭구분자가 있는 경우


Array length가 4이상이되면서 macth case 조건에 정상적으로 매칭되지 않았던 것이다.



이럴 경우 Dataframe을 show로 보았을 때는 전혀 문제가 없어보일 수 있지만 count로 모든 데이터의 수를 세게 될 떄


특정 데이터에 문제가 있을 경우 matchError가 발생하게 되는 것이다.




해결방법은 map처리에서 flatMap처리로 변경 후 조건에 맞지 않는 데이터는 None처리를 진행하였다.

val df = rawData.flatMap(_.split("\t") match { case Array(v1,v2,v3,v4) => Some((v1,v2,v3,v4)) case d => None}).toDF("id", "advid", "item_id", "item_name")


또 다시 같은 삽질을 하지 않기 위해 포스팅 남겨본다.

반응형
반응형

스파크 데이터프레임(Dataframe) partitionBy를 사용해 원하는대로 손쉽게 저장하자!


스파크(Spark) 데이터프레임(Dataframe) 혹은 데이터셋(Dataset)을 통해 작업하게 되면 


sql기반의 명령을 통해서 데이터를 손쉽게 활용할 수 있다는 점과 더불어 특정 컬럼 기반으로 


데이터를 저장할 수가 있다.


잠깐 데이터프레임(Dataframe)과 데이터셋(Dataset)에 대해 언급하자면 데이터셋(Dataset)은 데이터프레임과 RDD의 단점들을


보완한 모델로 Spark 1.6이상 버전부터 사용할 수 있다.


이번에 데이터프레임(Dataframe)을 partitionBy를 통해 저장해보았는데 이런 기능이 있다라고만 알았지


막상 써보니 너무 편해서 정리하게 되었다.


다음과 같은 데이터프레임(Dataframe)이 있을 때


partitionBy를 이용하면 특정 컬럼을 기반으로 디렉토리를 나누어 저장할 수 있다.


예를들어 advid를 기준으로 데이터를 나누어 저장하고 싶을 떄


df.write.partitionBy("advid").save("/저장될경로")


라고 저장해주면 다음과 같이 파일들이 advid를 기준으로 저장되게 된다.


이 얼마나 간편한가!!!!


다들 partitionBy를 통해 데이터를 원하는대로 손쉽게 저장해서 사용하시길!!!

반응형
반응형


카산드라(Cassandra) ttl은 read의 성능에 영향을 미치는가?

테스트 환경 및 프로세스

1. 알파 카산드라(node3개)에 ttl을 설정한 테이블과 ttl설정을 하지 않은 테이블을 각각 만든다.
2. 각각의 테이블에 2만개씩의 데이터를 넣는다 (id, value1, value2)  - id(1~20000)
3. api로 해당 테이블을 select하는 요청(id는 1~20000 중 랜덤으로 선택)을 한다.(20초동안 2000번)


테스트 결과 1

99th percentile에 주목해주세요(요청의 99% 평균 처리시간을 의미합니다.

1번2번3번
NO TTL 테이블 select 요청스크린샷 2018-03-09 오후 3.26.02.png스크린샷 2018-03-09 오후 3.26.29.png스크린샷 2018-03-09 오후 3.27.33.png
TTL 걸린 테이블 select 요청스크린샷 2018-03-09 오후 3.28.12.png스크린샷 2018-03-09 오후 3.28.45.png스크린샷 2018-03-09 오후 3.29.17.png

99th percentile을 보시면 알겠지만 ttl이 걸린 테이블이 오히려 처리속도가 더 빠른경우도 있습니다....(살짝 멘붕)

아무리 그래도 ttl걸린 테이블이 당연히 latency가 높을줄 알았는데....ㅎㅎ

그래서 각각의 테이블에 10000개의 데이터를 더 놓고 테스트를 진행하였습니다.

여기서 다른점은 ttl이 걸린 테이블에 임의로 10000개의 데이터의 ttl을 1분을 주고 tombstone이 발생하도록 하였습니다.

그리고 나서 다시 api로 select 테스트를 하였습니다.


테스트 결과2 (각각 테이블에 1만개씩 더 밀어넣음 - ttl걸린테이블에는 tombstone이 발생하도록 ttl을 1분으로 설정하고 넣음)

123
NO TTL 테이블 select 요청스크린샷 2018-03-09 오후 3.38.28.png스크린샷 2018-03-09 오후 3.38.53.png스크린샷 2018-03-09 오후 3.39.16.png
TTL 걸린 테이블 select 요청스크린샷 2018-03-09 오후 3.38.00.png스크린샷 2018-03-09 오후 3.37.40.png스크린샷 2018-03-09 오후 3.36.56.png

결과를 보시면 1만개씩을 더 밀어넣었지만 기존 TTL이 걸리지 않은 테이블은 첫 번째 테스트 속도와 거의 비슷한 결과를 도출한 반면

1만개의 데이터를 tombstone이 발생하도록 밀어넣은 TTL이 설정된 테이블은 속도가 현저히 떨어진 것을 확인해볼 수 있습니다.



그렇다면 왜 이런 결과가 나온것인가?

카산드라는 read요청이 들어올 경우 첫 번째로 memtable을 뒤지고
그 다음으로 row cache데이터가 있다면 row cache데이터를 확인합니다. (카산드라는 빈번하게 요청되는 row를 위한 캐시기능을 제공합니다)
row cache에도 데이터가 없는 경우 Bloom filter(메모리에 상주) 확인하여 찾는 row의  키가 있는 SSTables를 확인하여
해당 SSTables를 통해서 데이터를 읽어오게 됩니다.

따라서 데이터가 insert되면서 Bloom filter SSTables내의 데이터의 키값들이 해싱되어 업데이트 되는 경우에는
실제로 SSTables(dis I/O)를 사용하지 않고 데이터를 가지고 오게되어 빠르게 처리가 가능합니다.

하지만 Bloom filter의 해싱된 데이터들이 업데이트 되기전 SSTables의 값이 delete나 drop등으로 변경되는 경우에는
Bloom filter와 SSTable사이간 데이터의 정밀도가 떨어지게 됩니다.

이 경우 Bloom filter는 이미 SSTable내의 Tombstone된 데이터를 가르키게 되고 잘못된 포인팅으로 인해
카산드라는 SSTables에서 직접 해당 데이터를 다시 가져오는 작업(Disk I/O 발생)을 진행합니다.
이러한 이유로 ttl이 걸린 테이블 혹은 row에서 select시 성능이 떨어질 수 있다고 생각됩니다.
더 정확한 내용은 다음 문서를 참고해보시면 좋을 것 같습니다.
[Cassandra how is data read?](How is data read?)


TTL을 설정하고도 성능을 떨어트리지 않는 방법이 있는가?

SSTables과 Bloom Filter 정밀도를 높여서 운영하는 방법입니다.
하지만 모든선택에는 tradeoff가 있듯이 정밀도를 높이게 되면 더 많은 메모리를 필요로 하게 됩니다.
설정 방법은 테이블을 만들 때 bloom_filter_fp_chance 옵션을 주는 방법입니다.
추천값은 0.1이지만 최대 1.0까지 설정이 가능합니다.
1.0으로 설정할 경우 SSTables과의 정밀도를 높일 수 있으나 더 많은 메모리를 필요로 하기 때문에
상황에 맞는 설정값으로 운영하시면 될 것 같습니다.

반응형

+ Recent posts