저작권 안내: 저작권자표시 Yes 상업적이용 No 컨텐츠변경 No

스프링4 입문

스프링 4

DDD Start

객체 지향과
디자인 패턴

JSP 2.3

JPA 입문

윈도우8 PC에 Virtualbox를 설치하고 게스트OS로 윈도우7을 생성했다. 그런데, 이상하게 윈도우7 머신에서 네트워크가 안 되는 문제가 발생했다. 그래서 Vagrant로 Centos 머신을 생성했다. 역시나 Centos 머신도 네트워크가 안 됐다. 포트포워딩 설정을 해도 Centos에 붙질 않았다.


Virtualbox와 Vagrant를 재설치해보고 보안 관련 프로그램도 살펴봤는데 영 문제가 해결되지 않앗다. 이래 저래 삽질을 하면서 증상은 다음과 같음을 알 수 있다.

  • 게스트OS에서 ping은 됨
  • 게스트OS에서 TCP 연결이 안 됨 (예, 윈도우 게스트OS에서 브라우저로 연결이 안 됨. telnet으로 외부 서비스에 특정 포트로 연결이 안 됨)

증상이 이상해서 범위를 좁혀서 구글에서 검색을 하다가 아래 명령어를 통해서 해결할 수 있음을 알아냈다.


netsh winsock reset


그런데, 이 명령어를 실행하고 나니 DB 보안 프로그램인 샤크라맥스가 동작하지 않았다. 실제 원인은 샤크라와 버추얼박스 간에 문제였던 것있다. 샤크라맥스를 언인스톨하고 다시 설치했더니 이제 샤크라맥스도 정상 실행되고 버추얼박스에 생성한 게스트OS의 네트워크도 정상 동작한다.


정확히는 모르지만 버추얼박스를 설치한 뒤에 샤크라를 설치해야 버추얼박스의 네트워크 기능이 정상 동작하는 듯 하다.

저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 2017.06.21 09:25  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

오는 3월 21일 신림프로그래머 공개 모임의 "이벤트 소싱 학습 내용 공유" 시간에 사용할 발표 자료입니다.



저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 2015.03.22 00:09  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  2. bluepoet 2015.06.05 14:56 신고  댓글주소  수정/삭제  댓글쓰기

    전에 들었던 이벤트소싱이 어떤 내용인가 자료 살펴봤는데

    내용만으로도 상당히 잼있을 것 같네요.

    나중에 저도 실습한번 해봐야겠슴돠^^

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

예전 김창준님의 강의 영상을 보고 정리한 내용(강의 영상은 '개인이 조직을 변화시키는 법 http://agile.egloos.com/5742985 에서 볼 수 있음)


성공한 창업가들의 5가지 원칙


Bird in hand principle

  • 성공한 창업가 : goal 생각 없이 mean을 생각하고, 방법으로 뭘 할 수 있을지?
    • goal은 안정된 환경인 경우
  • mean 중심 전략의 세 가지 좋은 출발 점: What I know, Whom I know, Who I am

Crazy Quilt principle

  • stakeholder를 늘려나가는 것
  • 사람을 내 편으로 만들기
  • TDD 도입 성공하는 모습의 예: 초기부터 스터디를 같이 해서 내 편 만들기
Affordable loss principle 
  • ROI 중심이 아니라, 잃어도 되는 돈의 양을 정하고 착수
  • 랜덤한 상황에서는 오래 살아 남아야 함

Pilot in the plane principle

  • 예측은 못 해도, 제어를 할 수 있음 (non predictable control)
  • 제어할 수 있는 만큼은 예상 안 해도 된다.

Lemonade principle

  • 생각못한 상황이 발생할 때, 그것을 이용해라

관련 링크:

  • http://en.wikipedia.org/wiki/Effectuation


저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

신림프로그래머 모임에서 발표할 'JI 개발 이야기 리뷰' 자료입니다.



저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

신림프로그래머 모임에서 공유했던 '리뷰의 기술' 책 소개 자료입니다.



저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

스프링캠프 2014에서 정리해 놨던 걸 이제서야 블로그에 옮긴다.


실용적 소프트웨어 설계를 위한 근본적인 질문들 (안영회)

- SW는 유기체

- Contract & Integrity: 유비쿼터스 랭귀지, 스펙 등

- Contract & Integrity >> 표준화

- 용도에 맞는 설계 적용: 예, 복잡한 상태 변화를 표현하기 위한 상태 다이어그램

- 레거시 수정의 어려움 중 하나: 멘탈 모델이 그려지지 않음 (예, 이름을 잘 정해서 응집을 높이는 등 멘탈 모델을 향상시킨다.)

- 개발 팀 별 컨텍스트를 아우르는 협업


마이크로 서비스 구축 사례 (박찬욱)

- 10년간 운영해 온 커머스 사이트 시스템을 RESTful API 기반 마이크로 서비스로 쪼개는 과정

- 화면과 API를 쪼개고, 각 화면과 API도 별도로 분리

- 20개 사이트!!! 그 동안 프로젝트를 Copy&Paste&Modify 해서 사이트 추가 -> 수정의 어려움, 비용과 제약 (기술부채) 확산

- 그 과정:

 > 한 통의 WAR를 두 개 코드 분리: 화면 코드 - 로직(API) 코드

 > 화면을 위한 확장(예, 디바이스 추가)은 화면용 프로젝트(WAR)만 추가

 > 재사용 단위를 API로 맞춤

- 장점:

 > 영역별 확장

 > 분산해서 개발할 수 있는 환경

- REST 클라이언트를 스프링데이터처럼 런타임에 자동생성되도록 함

- API Spec을 별도 메이븐 모듈로 작성해서, 양쪽에서 의존으로 추가 -> 의존성 관리 어려움으로 코드가 아닌 스펙만 제공하는 것 고려 중

- 무엇을 API로 뽑아야 하나?

- Join의 최소화를 위해 적극적 캐시 도입

- 문제 발생시 문제 발생한 곳을 찾는 어려움 (여러 장비의 로그를 확인해야 함) -> Trace Key를 모든 로그에 보관


주키퍼, Vert.x 활용 실시간 푸쉬 서비스 개발 (이연복)

- 철가방 시스템에서 주문중계 서비스의 실시간 알림 기능 구축 사례

- 사용자가 앱으로 주문 발생시 가맹점에 어떻게 (최대한 실시간으로) 전달할 것인가?

- 쉬운 방법: 주문이 들어오면 전화로 다시 가맹점에 주문 전달 (정보 누락 등 문제 발생)

- 가맹점에 주문을 통지 받을 수 있는 프로그램을 배포(Flex Air로 제작)

- Flex Air와 서버 간 통신은 BlazeDS를 사용

- Flex Air와 Zookeeper 간의 중간 통신은 Vert.x로 만든 LB로 사용

- Vert.x의 분산 이벤트 버스로 클러스터 구현

- 이벤트버스를 이용해서 버티클 간 통신(데이터 전달 등)


스타트업 망한 이야기 (강규영)

(들었던 내용을 모두 옮겨 적고 싶었지만 서서 들은 관계로..... 아래 두 가지만 적음)

- 넘치는 쪽지를 비활성 유저에게 보내기: 일단 유저에게 통지하고, 그 유저가 액티브 상태가 되면, 실제 쪽지 전송 (미리 보내지 않음)

- 한글 자소 분리해서 필터 학습


REST (김강우)

- REST: REpresntional State Transfer

- REpresntational -> Resource

- State Transfer

 > State: 상태의 전이가 발생

 > 상태 전이를 위한 방법: POST(C), GET(R), PUT(U), DELETE(D)

 >> POST(C): /order (성공: 201 응답이면 좋을 것, Location: /order/{생성된ID})

 >> GET(R): /order/{id}

 >> PUT(U): /order/{id} (200(데이터 보냄), 204(데이터는 안 보냄), 409(Conflict, 예, 누군가 이미 변경했다면, 즉, 낙관적 락!))

 >> DELETE(D): /order/{id}

- Hypermedia 응답에 상태 전이를 위한 링크 포함 (HATEOAS: Hypermedia As The Engine Of Application State)

 > 장점1: 다음 전이 상태를 쉽게 응답으로 알 수 있음

 > 장점2: 연결되는 주소를 알 수 있음 (결제 주소가 넘어 옴)

- EntityTag(etag)

 > 수정시, etag를 일종의 Resource의 버전으로 사용가능

- 전체 수정, 부분 수정: POST? PUT?


저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

이클립스 Luna (4.4)에 Dark 테마가 추가됐다. 뭔가 있어 보여서 Dark 테마를 적용해 봤는데, 아래 그림처럼 에디터 부분이 어울리지 않는 색상을 사용하는 것이 거슬렸다.



뭐가 있겠지 싶어서 구글 신께 여쭤보니 Eclipse Color Theme 라는 걸 설치하라고 알려주신다. Help -> Eclipse Market Place에서 Eclipse Color Theme 플러그인을 설치하면 된다. 이 플러그인을 설치하면 아래 그림처럼 Preferences > General > Appearance에 color Theme 메뉴가 생기는데, 이 메뉴에서 Dark 테마에 어울리는 색상 테마를 선택하면 된다.



다음은 색상 테마로 Sublime Text 2를 적용한 결과 에디터 화면이다.






저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

2014년 2월 27일 코엑스에서 열린 Gaming on AWS 세미나에서 기억나는 내용을 정리해 본다. 세미나 제목에도 있지만, 게임 업계의 AWS 적용 후기가 주된 내용이다.


여러 세션을 종합해보면 AWS를 사용하는 이유는 다음의 몇 가지로 좁혀진다.


이유

내용 

글로벌 서비스

해외 IDC에 장비를 둘 경우, 해외의 엔지니어 고용, 해외 법, 장애 대응 등 서비스 운영에 많은 어려움이 있다. 각 지역별로 서버를 둬서 최종 사용자의 위치에 따라 가까운 서버에 연결하도록 만들려면 어려움은 더욱 배가 된다. AWS를 사용하면 이런 문제점을 대부분 해소할 수 있다. 


AWS는 북미, 유럽, 남미, 동남아, 중국, 일본 등 10여개의 리전이 있고, 50여개의 Edge가 존재한다. 또한, Route53을 통해 최종 사용자의 위치에서 가장 가까운 리전이 사용되도록 할 수 있다.

운영 민첩성

새로운 인스턴스를 생성하는데 소요되는 시간이 불과 몇 분에 불과하다. 또한, 트래픽 변동성이 심한 서비스에 대해, 트래픽 상황에 따라 자동으로 인스턴스를 생성하거나 제거할 수 있다.

재시작을 통해 같은 인스턴스의 스케일업/다운이 가능하다.

비용

최대 트래픽 기준으로 인프라를 구축할 필요가 없고 실제 사용량에 따라 비용을 지불하기 때문에 전체적인 운영비용을 절감할 수 있다. 또한, RC(Reserved Capacity)를 사용하면 할인된 금액으로 서비스를 사용할 수 있다.


한빛소프트의 경우 미국IDC를 AWS로 옮겨서 운영 비용을 32% 낮출 수 있었다고 한다. (6억 3천에서 4억 3천으로 낮춤)


AWS 인스턴스의 성능/서비스와 관련해서 다음의 내용을 언급했다.

  • 네트워크 Latency: SR-IOV를 지원하는 인스턴스 타입 추가해서 Latency 감소
    • SR-IOV: 가상 머신이 하이퍼바이저를 거치지 않고 랜카드와 직접 통신
  • EBS(Elastic Block Store)를 이용해서 DISK IO 속도 높일 수 있음
  • ELB: Pre Warm을 통해 급작스런 트래픽 증가시 발생하는 ELB의 성능 저하 현상을 방지할 수 있음
  • CDN: 전 세계에 50개의 Edge가 있고, 한국에도 존재
  • 분석을 위한 서비스 제공: Redshift(DW도구), Kinesis(실시간 분석 도구), EMR(맵리듀스)
  • 보안 서비스
    • 기존과 같은 방식의 관제 서비스를 받기 어렵지만, 마켓플레이스를 이용해서 보안 서비스를 제공받을 수 있음
    • VPC를 통한 VPN 지원
  • 최근 서울-Tokyo리전에 대한 Latency가 200ms에서 40ms 수준으로 떨어졌음. 따라서, 국내 대상 서비스를 하는 경우에도 Tokyo 리전이 매력이 있음
재미났던 점: 쿠키런 발표 내용 중 AutoScale 관련한 내용
  • Chef를 이용해서 서버 설정 관리
    • Chef를 이용해서 설정한 서버를 AMI로 만들어서 S3에 보관,
    • AutoScale 시에는 이 AMI를 이용해서 서버 확장
    • AMI 생성 시점과 그 이후의 변동분은 Chef에 의해 반영
  • CloudFormation 이용해서 인프라 형상 관리 (예, 평균 CPU 사용률이 60%가 넘으면 인스턴스가 4개 추가와 같은 규칙을 설정 파일로 관리)
  • CircleCI를 이용해서 최신 WAR 파일을 S3에 보관하고, 자동 추가되는 인스턴스는 Chef에 의해 S3에서 WAR를 가져와서 실행 (새로운 인스턴스는 새 버전을 사용)
  • 새 버전 배포 방식: 새 인스턴스를 실행하고 기존 인스턴스를 제거하는 방식으로 롤링 업데이트
  • 로그는 LogStash를 이용해서 수집, Elastic Search에 보관해서 로그 탐색 (1달치 보관)
    • 인스턴스 종료시 10분이 넘어가면 AWS에서 인스턴스를 강제로 제거함
    • 따라서, 인스턴스 종료시점에 후처리가 10분을 넘기면 데이터 유실이 발생함, 이 점에 주의
흥미로웠던 부분: 게임 분석과 관련해서 5Rocks에서 발표한 내용
  • 한국 게임 서비스들의 트래픽을 분석해보면 최소/최대 사이에 10배 정도 차이가 남
  • 최대 트래픽이 발생하는 시점은 오후12시~1시 (점심 시간), 그 다음은 9시~11시
  • 분석 역량의 차이가 게임의 흥망과 연결
    • 못하는 회사: 단순히 DAU(Daily Active User), Session Count, ARPU 통계만 확인
    • 잘하는 회사
      • 추가로 (구매, 빈도, 레벨 등 기준으로) 상위 User와 비교
      • 레벨/종복/기타 분류 별 ARPU 비교
    • 일본 회사가 잘하는 것: FQ(Frequency) 분포를 이용한 분석
      • 방문회수,게임시간 등으로 그룹을 나눠 분석
      • 휴면 유저도 휴면일수 등으로 구분해서 관리/분석


저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

오늘(2014-02-05) 있었던 SSAG 2차 세미나(http://beyondj2ee.wordpress.com/2014/01/23/2309/) 내용을 두서없이 생각나는대로 정리해 본다.


첫 번째 세션, MongoDB를 사용하면서 알게 된 것들, 한대희님 발표


이음 서비스로 유명한 이음소시어스에서 Hey라는 서비스를 구축하면서 사용했던 MongoDB 적용 후기

  • Hey 서비스에 MongoDB를 사용한 이유
    • 설치 쉬움
    • RDBMS와 유사한 인덱스 지원
    • Ruby ORM 존재
    • 매칭 데이터가 증가하지 않을까 기대감 (샤딩 고려)
  • 인프라 구성
    • AWS에서 MongoDB 이미지를 이용해서 3대로 Replica Set 구성
    • 구성: Primary 1대, Secondary 1대, Arbiter 1대
  • 모니터링
    • NewRelic / MMS (mms.mongodb.org): 모니터 + 백업 지원 (연간 50$ 이하 사용시 무료라 함)
  • 사용하면서 불편했던 점
    • 익숙하지 않은 쿼리 (SQL 만큼 편하지 않음)
    • 데이터 타입 문제
    • 빈번한 Update시 데이터 블록 재구성에 따른 성능 저하
    • DB Level Lock (진짜인지 추가로 확인 필요)
  • 서비스의 규모가 최초 예상을 밑돌아 샤딩 등의 확장성 검증은 하지 못했음
  • 어디에 쓰면 좋을까?
    • 데이터가 간 관계가 없음
    • 데이터가 순차적으로 증가
    • Insert 위주 (예, 로그나 채팅 메시지 등)
    • 수평 확장 대상
  • 적용 전 고민
    • 데이터 간 조인이 필요 없는지?
    • Update나 Delete가 자주 발생하는지?
    • Schemaless가 필요한지?
    • Write 성능이 중요한지?
    • 데이터가 샤딩을 필요로 할 만큼 커지는지?
  • 기타 두 분의 배틀 내용 중 기억나는 단어
    • MariaDB DokuDB 성능 좋음
두 번째 세션, AWS 인프라 구축 경험, 김민태님 발표

목소리나 발표 모습이 매우 낯이 익다 했더니, 작년 12월에 있었던 OKJSP 13주년 컨퍼런스에서 프론트 관련 주제로 발표한 분이셨다.
  • checkit.us 서비스를 만들면서 적용한 이야기
  • 서버 측 기술: nodejs, MongoDB
  • 최초: heroku를 선택했음
    • 프로토타입 목적으로는 적합할지 모르나, 너무 느림
  • AWS를 선택한 이유
    • 레퍼런스가 많음
    • PaaS 보다 자유로움 + PaaS 만큼 편리한 부분도 있음
    • 글로벌 서비스에 장점이 있음
  • 도입
    • 최초: t1.micro로 테스트
    • AWS로 이전하는데 약 1달 정도 소요 (최초 2주는 AWS 자체를 알아가는 과정)
    • 현재 구성: EC2 1개, MongoDB 3개, ELS (서비스 트래픽에 따라 EC2 인스턴스가 2개까지도 가는 상황)
      • 월 비용은 1,000$ ~ 1,300$ 사이
  • 한국은 약간 느린 감이 있지만, 서비스엔 충분함
세 번째 세션(?), AWS 비용 최적화 방법 안내

아마존에서 직접 오셔서 최적화 방법을 안내함
  1. 과하게 자원을 쓰지 말 것 (90% 이상 펑펑 놀고 있다면, 스펙을 낮춰야 함)
    1. CPU, Disk 등 과도하게 놀지 않도록
  2. 자동 수평 확장 기능을 사용할 것 (쓴 만큼 내므로)
    1. 예, 쿠키런의 경우 트래픽이 없을 땐 2대에서 많을 땐 60대로 자동 확장/축소
  3. RI(Reserved Instance)를 사용해라
    1. 연 단위 계약을 하면 비용이 절감 됨
    2. RI를 적용할 인스턴스는 약간 고사양 장비로 맞추고, 자동 확장되는 인스턴스는 RI에 비해 상대적으로 낮은 스펙을 사용하는 방식 등을 고려




저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

윈도우에서 작성한 리눅스 쉘 파일을 리눅스에 배포할 때, 종종 실행이 제대로 되지 않는 경우가 있는데, 그것은 윈도우의 라인 구분자가 CR(캐리지 리턴, \r)-LF(라인 피드, \n)인 반면에 리눅스는 LF이기 때문이다. 라인 구분에 포함된 캐리지리턴으로 인해 잘못된 텍스트 값을 사용하게 되고 이로 인해 파일이름이라든가, 여러 부분에서 문제가 발생하는 것이다.


리눅스에서 CR-LF를 LF로 변환해주는 몇 가지 방법이 있지만 (검색해보니 다양한 방법이 있다), 개발PC가 윈도우다 보니 배포 과정에서 어떻게 처리하는 방법이 없을까 고민했는데, 배포 도구로 사용중인 Ant에서 처리하는 방법을 찾았다.


Ant에 보면 FixCRLF 라는 태스크가 있는데, 이 태스크를 사용하면 특정 파일의 라인 구분자를 손쉽게 변경할 수 있게 된다. 아래는 이 태스크의 사용 예를 보여주고 있다.


<target name="deploy" depends="package">

<copy todir="./target-real">

<fileset dir="./src/script">

<include name="*.sh"/>

</fileset>

</copy>

<fixcrlf srcdir="./target-real" includes="**/*.sh" eol="lf" />

...

<echo message="===== Complete Deploying ======" />

</target>


위 코드에서 <fixcrlf> 태그는 ./target-real에 있는 모든 sh의 라인 구분자를 LF로 변환해주기 때문에, 별도의 귀찮은 작업들(리눅스에서 변경해준다거나, 개발 환경의 라인 구분자를 변경한다거나 하는 등)을 할 필요가 없다.

저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

김창준님의 "당신이 제자리 걸음인 이유: 지루하거나 불안하거나(http://agile.egloos.com/5749946)" 글을 필요할 때 마다 매 번 읽으면 좋겠지만, 보다 수시로 볼 수 있도록 책상 주변에 붙여놓기 위해 아래 이미지를 한 장 만들어본다.





저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 개발자 2014.01.20 10:02 신고  댓글주소  수정/삭제  댓글쓰기

    좋은글 공유할께요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

글을 읽다 보면 1급 함수(first-class function)처럼 1급(first-class)이란 단어가 나오는데, 이 단어의 의미를 간단히 정리해 보았다.

  • 파라미터로 전달될 수 있다
  • 리턴 값으로 사용될 수 있다
  • 변수에 할당할 수 있다
  • 런타임에 생성될 수 있다
first-class function 의 의미는 함수를 파라미터로 전달하고, 변수에 할당하고, 리턴 값으로 함수를 받을 수 있고, 런타임에 함수를 생성할 수 있다는 의미가 된다.



저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

  1. 이루리 2013.06.20 15:22 신고  댓글주소  수정/삭제  댓글쓰기

    그러면 1급함수가 아닌 함수는 어떤것인가요? 검색해두 정보를 못찾아 질문드려요~

    • 최범균 madvirus 2013.06.21 08:49 신고  댓글주소  수정/삭제

      1급함수가 아닌 함수가 아니라,,, 언어에서 함수를 1급으로 처리하느냐에 대한 겁니다.
      자바의 경우는 다음과 같은 코드가 안 되죠.

      // public void myFunc()이 있다고 가정
      Some some = new Some();
      some.callAny(myFunc); // 파라미터로 메서드 자체를 줄 수 없음

      자바에서는 메서드가 1급으로 처리되지 않기에, 메서드 자체를 생성자나 변수나 파라미터 등에 전달할 수 없습니다. 메서드만 따로 생성하는 것도 안 되구요.

      반면에 자바스크립트에서는 아래와 같은 코드가 가능하죠.

      function someFunc() { ... }
      otherFunc(someFunc) // 함수 자체를 파라미터로 전달 가능
      var a = someFunc; // 함수를 변수에 할당 가능

      즉, 자바 스크립트에서는 함수를 1급으로 처리하고 있습니다.

  2. 지나가다 2017.06.08 17:57 신고  댓글주소  수정/삭제  댓글쓰기

    좀 엉뚱한 질문같지만, 그러면 왜 굳이 "1급" 이라고 부르나요?
    1급 함수가 있으면 2급(second-function), 3급도 있다는 소린가요?

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

팀에서 했던 빅데이터 개요 발표 자료


저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.



저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

조회수, 좋아요. 이 두 값은 전형적인 카운트이다. 글을 읽거나 좋아요 버튼을 누를 때 마다 값이 1씩 증가하는 특징을 갖는다. 예를 들어, 게시글의 경우 다음과 같이 '조회' 수와 '좋아요' 수를 갖는데, 이들 값은 사용자가 글을 조회하거나 '좋아요'를 할 때 마다 1씩 증가하게 된다.


public class Article {

    ...

    private int viewCount;

    private int likeCount;

    ...

}


카운트와 캐시


이제 서비스에 있어서 캐시는 기본이 된 듯 하다. 급증하는 트래픽을 장비로만 막는데는 한계가 있기 때문에, 캐시는 반드시 고려해야 하는 대상이다. 이 캐시를 적용할 때 개발자를 짜증나게 만드는 것이 있는데, 그것은 바로 카운트 방식의 값이다.


예를 들어, 게시판에서 하나의 게시글을 Article 이란 모델로 표현했다고 할 경우, 게시글은 읽기만 해도 증가하기 때문에 Article 및 Article의 List를 담고 있는 캐시는 글의 조회수가 증가될 때마다 캐시에서 제거되어야 한다. (또는 백엔드에서 다시 값을 읽어와 캐시에 넣어야 한다.) 조회수 증가가 크지 않은 사이트는 이렇게 하더라도 전혀 문제가 되지 않겠지만, 캐시를 도입하는 이유는 트래픽이 많아졌기 때문이다. 그런데, 트래픽이 많아졌다는 것은 특정 게시글에 대한 조회 요청이 많다는 것을 의미하고, 이는 조회수의 증가가 발생한다는 것을 의미한다. 조회수의 증가는 캐시에 보관된 게시글 정보가 더 이상 유효하지 않다는 것을 의미하므로 캐시에서 게시글 정보 또는 관련 게시글 목록 정보가 캐시에서 제거된다는 것을 뜻한다. (조회수에 민감하지 않다면 캐시에 보관된 데이터를 일정 시간 동안 사용할 수 있겠지만, 실제로 고객들은 조회수, 좋아요 등의 숫자에 매우 민감하기 때문에 제대로 반영해 주어야한다.) 캐시에서 제거되었으므로 결국 DB에서 다시 읽어와 캐시에 담게 된다. 하지만, 조회수가 증가하기 때문에 결국 다시 캐시에서 제거되고 DB에서 읽어와 캐시에 담는 과정이 반복될 것이다.


트래픽이 증가해서 캐시를 적용했는데, 카운트 증가 때문에 캐시 효과가 없어지는 어처구니 없는 상황이 발생하는 것이다. 사실, 게시글의 내용과 카운트 값은 변경의 빈번도가 완전히 다르다. 제목과 같은 내용은 변화 빈도가 낮은 반면에 카운트 값은 특정 기간 동안에 빈번도가 굉장히 높다.


카운트의 분리


따라서, 특정 컨텐츠에 대한 캐시 효과를 극대화하려면 카운트 류의 값을 별도로 분리해주어야 한다고 생각한다. 예를 들어, 게시글의 경우 다음과 같이 두 개의 모델로 분리한다.



즉, 내용을 담고 있는 Article과 해당 Article의 카운트 값을 갖는 ArticleCount로 구분할 수 있을 것이다. ArticleCount의 id는 Article과 동일한 id를 가질 것이다.


Article과 ArticleCount가 분리되었으니, 이 두 객체를 다루는 서비스도 분리된다.


public interface ArticleService {

    public Article getArticle(Long id);

}


public interface ArticleCountService {

    public ArticleCount getArticleCount(Long id);

    public void increaseViewCount(Long id);

}


조립하기


완전한 게시글 읽기 기능은 Article과 ArticleCount를 필요로 하므로, 다음과 같이 두 서비스를 사용해서 구현한다.


public class ReadArticleService {

    public ArticleDto readArticle(Long id) {

        Article article = articleService.getArticle(id);

        articleCountService.increaseViewCount(article.getId());

        ArticleCount count = articleCountService.getArticleCount(article.getId());

        return new ArticleDto(article, count);

    }

    ...

}


public class ArticleDto {

    private Article article;

    private ArticleCount count;


    public ArticleDto(Article article, ArticleCount count) {

        this.article = article;

        this.count = count;

    }


    public Long getTitle() {

        return article.getTitle();

    }

    public int getViewCount() {

        return count.getViewCount();

    }

    ...

}


AritcleDto는 Article과 ArticleCount로부터 값을 읽어오는 getTitle(), getViewCount() 등의 메서드를 제공한다.


캐시 분리 적용


이제 ArticleService의 getArticle()에 캐시 기능을 적용하자. 


public class ReadArticleService {

    public ArticleDto readArticle(Long id) {

        Article article = articleService.getArticle(id); // 캐시에서 읽어 옴

        articleCountService.increaseViewCount(article.getId()); // DB에서 반영

        ArticleCount count = articleCountService.getArticleCount(article.getId()); // DB에서 읽어 옴

        return new ArticleDto(article, count);

    }


ArticleService.getArticle()은 이제 캐시에서 Article 객체를 가져온다. 반면 ArticleCount는 항상 DB에서 가져온다. 이제 조회수와 같은 카운트 값이 빈번하게 변경하더라도 Article 객체가 캐시에서 제거되지 않으므로, Article에 대한 캐시 히트율이 높아질 것이다.


지금까지는 그냥 생각일 뿐, 실제로 조회수가 급격하게 증가하는 상황에서 성능이 어떻게 될지는 아직 테스트 해 보지 못했다. 이건 나중에 기회가 되면 한 번 해 보기로 하자.

저작자 표시 비영리 변경 금지
신고
Posted by 최범균 madvirus

댓글을 달아 주세요

  1. bluepoet 2012.11.29 16:12 신고  댓글주소  수정/삭제  댓글쓰기

    색다른 아이디어의 글 잘 읽었습니다.

    카운트에 대한 객체를 따로 빼내고, 글 정보 자체를 캐시한다음

    해당 글의 카운트 정보만 업데이트하고 그 정보만 DB에서 읽어온다면

    DB 인덱스 설계에 따라 달라지긴 하겠지만, Article에 대한 글정보를 업데이트하고

    가져오는 것보단 비용이 덜하지 않을까 생각됩니다.

    다만, 리스트를 뿌릴 때 Article 하나에서 가져오는 것과

    Article과 ArticleCount를 조인해서 가져오는 것과의 비용은 잘 따져서

    선택해야 될 것 같습니다.

    스트레스 테스트 하시면 결과도 공유해주시면 좋을 것 같네요

페이스북 친구들과 댓글을 공유하고 싶다면 아래를 이용해주세요.

티스토리 툴바