'분류 전체보기' 카테고리의 글 목록 (4 Page) :: 잡다한 프로그래밍
반응형

웹 아키텍쳐에서 DB는 병목 지점이다. (대용량 처리시 아키텍쳐를 어떤식으로 구성해야하는지 고민해보자)

 

1. 스케일업(scale-up), 스케일 아웃 (scale-out)이란?

 

  • 하나의 서버의 사양을 보다 높은 사양으로 업그레이드하는 것을 말한다.(더 좋은 성능으로 더많은 요청을 처리)

스케일업

  • 서버의 대수를 늘려 부하를 분산시켜 더많은 요청을 처리

스케일 아웃

 

  스케일업 스케일 아웃
유지보수 및 관리 쉬움 여러 노드를 관리해야함 (분산 필요)
확장성 제약있음 (서버의 성능을 높이는데 한계) 자유로움
장애복구 서버가 1대, 다운타임 존재 장애에 탄력적인 대응 가능

 

※ 스케일 아웃시 같은 입력에대해서는 항상 같은 결과를 반환해야함

- 따라서 다음과 같은 구조를 띄게 된다.

데이터 베이스의 스케일 아웃은 어려운가?

- 스케일 아웃에는 상태가 없어야 하는데, DB에는 데이터의 상태가 존재함 따라서 서버보다 더많은 비용이 발생 (스케일 아웃이 가능한 방법이 존재함)

※ 참고 https://willseungh0.tistory.com/131

 

따라서 서버 아키텍쳐는 상태관리는 DB에 위임 서버는 상태 관리를 하지않는 형태로 발전

 

DB는 왜 병목지점?

  • 앞서 말한 스케일 아웃이 어렵기 때문에 병목지점이 될 수 있음
  • DB는 디스크에서 데이터를 가져오기 때문에 속도가 상대적으로 느림 (병목지점이 될 수 있음)
  • 서버와 DB사이에 네트워크 구간이 존재 (네트워크 상황에 따라 요청속도가 느려질 수 있음)
반응형
반응형

1. 엘라스틱 서치 쿼리에대해 간단하게 정리하고자 한다.

 

기본적으로 아래와 같은 형태를 띄고 있다.

- query: 기존 DB의 where 조건문에 해당 (query, filter)

- size: 0으로 설정할경우 결과는 보지않고 집계결과만 보겠다는 의미

- aggs: 집계 부분 기존 쿼리의 Group by에 해당

GET _search
{
  "query":{
  },
  "size":0,
  "aggs": {
  }
}

 

집계 정리

1. SELECT count(*) FROM test group by userNo

- 유저 번호로 그룹핑한 결과를 보고 싶을때

{
  "size":0,
  "aggs": {
    "user_no (집계 대상 이름)" : {
      "terms": {
        "field": "user.no"
      }
    }
  }
}

결과

  "aggregations" : {
    "aa" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 0,
          "doc_count" : 66
        },
        {
          "key" : 107,
          "doc_count" : 14
        }
        ...
        이하 생략

 

2. userNo 값으로 집계한 결과를 대상으로 특정 url로 집계하고 싶을때

{
  "size":0,
  "aggs": {
    "aa" : {
      "terms": {
        "field": "user.no"
      },
      "aggs": {
        "url_name": {
          "terms": {
            "field": "url.keyword"
          }
        }
      }
    }
  }
}

결과

  "aggregations" : {
    "user_no" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 0,  # 유저별 그룹핑
          "doc_count" : 664745,
          "url" : {
            "doc_count_error_upper_bound" : 94,
            "sum_other_doc_count" : 4659,
            "buckets" : [ # url별 그룹핑
              {
                "key" : "http://aaa.com",
                "doc_count" : 655
              },
              {
                "key" : "https://test.com/",
                "doc_count" : 469
              },
              {
              .. 이하생략

 

3. 일별, 사용자별로 그룹핑 한다면? (2번은 집계한 결과의 집계, 3번과차이가 있음)

{
  "size":0,
  "aggs": {
    "abnormal_status" : {
      "composite": {
        "sources": [
         # time을 일별로 묶어줌, calendar_interval = day, week, hour..
          { "date": { "date_histogram": { "field": "time", "calendar_interval": "day", "format": "yyyy-MM-dd"}}},
          { "name": { "terms": { "field": "userNo" } } }
        ]
      }
    }
  }
}

 

결과

 "aggregations" : {
    "abnormal_status" : {
      "after_key" : {
        "date" : "2022-07-14",
        "name" : 2
      },
      "buckets" : [
        {
          "key" : {
            "date" : "2022-01-03",
            "name" : 0
          },
          "doc_count" : 1
        },
        {
          "key" : {
            "date" : "2022-05-30",
            "name" : 0
          },
          "doc_count" : 1
        }
        ... 이하생략

 

4. count(distinct column) > 사용자별로 (그룹핑) 몇개의 ip를 가지고있는가 (count(distint))

{
  "size":0,
  "aggs": {
    "user" : {
      "terms": {
        "field": "userNo"
      },
      "aggs": {
        "ip": {
          "cardinality": {
            "field": "ip"
          }
        }
      }
    }
  }
}

결과

"aggregations" : {
    "multi_ip_top_n" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 0,
          "doc_count" : 45,
          "ip_cardinality" : {
            "value" : 3
          }
        },
        {
          "key" : 2,
          "doc_count" : 9,
          "ip_cardinality" : {
            "value" : 2
          }
        },
        {
          "key" : 25,
          "doc_count" : 5,
          "ip_cardinality" : {
            "value" : 2
          }
        },
        .. 이하 생략

 

5. sum, avg, min, max > status

status를 사용할경우 앞의 4가지를 전부 구할 수 있다.

  "size":0,
  "aggs": {
    "user_no" : {
      "terms": {
        "field": "user.no"
      },
      "aggs": {
        "sum": {
          "sum": {
            "field": "queryCnt"
          }
        },
        "avg": {
          "avg": {
            "field": "queryCnt"
          }
        },
        "min": {
          "min": {
            "field": "queryCnt"
          }
        },
        "max": {
          "max": {
            "field": "queryCnt"
          }
        }
      }
    }
  }
}
{
  "query":{
    "bool":{
      "filter": [
        { "range": { "reqTime": { "gte": 20210623000000, "lte": 20220723235959 }}}
      ]
    }
  },
  "size":0,
  "aggs": {
    "user_no" : {
      "terms": {
        "field": "user.no"
      },
      "aggs": {
        "stats": {
          "stats": {
            "field": "queryCnt"
          }
        }
      }
    }
  }
}

 

집계시 기억해야 할 점

 

엘라스틱 서치에서 제공하는 기본 집계의 수는 10000건이다. 이 이상으로 설정할 수 있지만 권장하지 않는다하고, 따라서 이에 맞게 결과를 도출하려 해야한다.

 

그럼에도 불구하고 10000건이상, 혹은 전체를 불러오고 싶을경우?(ex 페이징처리가 필요하다)

 

composite집계를 이용하여 처리할 수 있다.

앞선 composite 집계 결과를 보면 다음과 같이 after_key를 포함하고있다. 집계시 해당 키값을 넣어주게 되면 해당 키 다음부터 조회할 수 있다.

이런 방법으로 전체를 조회하거나 원하는 페이지를 조회할 수 있다.

 "aggregations" : {
    "abnormal_status" : {
      "after_key" : {
        "date" : "2022-07-14",
        "name" : 2
      },
      "buckets" : [
        {
          "key" : {
            "date" : "2022-01-03",
            "name" : 0
          },
          "doc_count" : 1
        },
        {
          "key" : {
            "date" : "2022-05-30",
            "name" : 0
          },
          "doc_count" : 1
        }
        ... 이하생략

 

{
  "size":0,
  "aggs": {
    "abnormal_status" : {
      "composite": {
        "sources": [
         # time을 일별로 묶어줌, calendar_interval = day, week, hour..
          { "date": { "date_histogram": { "field": "time", "calendar_interval": "day", "format": "yyyy-MM-dd"}}},
          { "name": { "terms": { "field": "userNo" } } }
        ],
        "size": 10000,
        "after": #해당부분에 afterKey값을 넣어주면 그 위치부터 시작함
      }
    }
  }
}

 

※ 이외에 알아둘만한 집계 함수

percentiles > 해당 퍼센트에 해당하는 기준값이 얼마인지 알 수 있다.

    "percentiles_bucket" : {
      "values" : {
        "75.0" : 75,
        "80.0" : 80,
        "85.0" : 85,
        "90.0" : 90,
        "95.0" : 95,
        "99.0" : 99
      }
    }

script사용

아래와 같이 집계중 script를 사용할 수 있는 집계들이 있다.

아래 집계는 time 필드를 HH형태로 바꾸어 집계한 결과이다.

ex 20220805124333 > 12

  "aggs": {
    "hourly_privacy_count" : {
      "terms": {
        "script": {"source": "doc['time'].value.getHour()"}
      }
 }
반응형
반응형

자바스크립트의 호이스팅에 대해 알아보는 시간을 가진다.


1. 호이스팅 (Hoisting)

- 자바스크립트에서 선언하는 변수값은 모두 유효 범위의 최상단으로 선언된다 = 즉 나는 밑에서 선언했지만 제일 상단에서 선언한것처럼 동작한다. 라는 의미를 가진다.

  • 자바스크립트 Parser가 함수 실행 전 해당 함수를 한번 훑는과정을 거친다.
  • 함수 안에 존재하는 변수/함수 선언에 대한 정보를 내부적으로 끌어올려서 처리한다(코드상의 변화가 있지는 않음)

 호이스팅의 대상

  • var 변수 선언, 함수 선언문에서 호이스팅이 일어난다.
    • let, const 에서는 호이스팅이 일어나지 않음 (ES6에서 개선) ※ 호이스팅은 일어나나, 발생하지 않는것처럼 참조 에러가 발생함

변수는 어떤식으로 생성 될까?

1. 변수의 선언

  • 변수를 실행 컨텍스트의 변수 객체에 등록함.

2. 초기화 단계

  • 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다.
  • 이때 변수는 undefined로 초기화 된다.

3. 할당 단계

  • 실제 undefined로 초기화된 변수에 값을 할당한다.

 

앞서 말한 var키워드는 선언, 초기화가 한번에 이루어진다. 즉 스코프에 변수를 등록하고 공간을 확보한 후 undefined로 초기화한다. 하지만 let키워드는 선언과 초기화가 분리되어 진행되므로, 초기화 이전에 접근하면 에러가 발생한다.

 

- 앞서 이론적인 부분을 코드적으로 이해해보도록 하자

변수 선언에서의 호이스팅 예시

console.log(val); //선언 + 초기화
val = 'text'; //선언 + 초기화 + 할당
var val = 'hi';

- 해당 코드를 js가 아닌 다른 언어로 생각했을경우 1 번째 line에서 에러가 발생해야한다 하지만 결과는 undefined값이 찍힌다. 이유는 앞선 선언 + 초기화가 되어있기 때문이다

console.log(val); // 호이스팅에 의해 끌어올려졌지만 초기화는 안된 상태
let val = 'hi'

let을 사용하게되면 선언만 이루어지고 초기화는 되지않아서 에러가 발생한다.

 

함수 선언에서의 호이스팅 예시

test(); // 함수 선언문 정상동작 호이스팅 O
test2(); // 함수 표현식 오류 발생 호이스팅 X 

function test() {
	console.log('test');
}

var test2 = function() {
	console.log('test2');
}

- 함수 선언문같은 경우 호이스팅이 된다. 하지만 함수 표현식의 경우 호이스팅이 이루어지지 않는다.

함수 선언문의 경우 = 함수 전체가 최상단으로 호이스팅 된다. 하지만 함수 표현식의 경우 변수가 호이스팅 되기때문에 에러가 발생한다

 

클래스의 호이스팅

그렇다면 ES6에 추가된 클래스는 어떨까? (let, const가 변수 선언 전에 사용하면 에러가발생하듯 class의 경우도 오류가 발생할까?)

let test = new Test('hi'); // ReferenceError: Person is not defined
console.log(peter);

class Test {
  constructor(val) {
    this.val = val;
  }
}

생각한 대로 클래스는 ReferenceError를 내뱉는다. 함수 선언문의 경우 호이스팅 되어 이전에 사용할 수 있었지만. ES6에서 추가된 클래스의 경우는 호이스팅 되어도 초기화가 되지않기 때문에 (let, const 처럼) 에러를 내뱉는다.

 

- 마찬가지로 클래스 표현식 let val = class Test {....} 로 정의할 경우도 에러를 발생시킨다.

 

이상 간단한 호이스팅 정리였다.

반응형
반응형

자바스크립트의 프로토 타입, 클래스에 대해 알아보는 시간을 가진다.


1. 프로토타입 (prototype)

- 프로토 타입은 JS에 클래스가 생기기전 객체를 다를 객체로 상속하기 위해 사용하는 개념이다 (ES6의 클래스는 타 언어의 클래스와 거의 흡사하고, 내부적으로는 prototype을 따른다고 함)

 

- 앞서 JS에서 객체 생성자란 무엇인지, 상속은 어떤방식으로 하는지 간단하게 확인해보자.

function People(name, age) {
  this.name = name;
  this.age = age;
  this.info = function() {
    console.log('이름: ' + name);
    console.log('나이: ' + age);
  }
}

const test = new People('A', '30');
const test2 = new People('B', '20');

test.info();
test.info();

- 결과는 예상한대로 이름 : A, 나이 :30 이름: B, 나이: 20이 나온다.

 

여기서 프로토타입을 사용하면 다음과 같이 바뀐다.

function People(name, age) {
  this.name = name;
  this.age = age;
}

People.prototype.info = function() {
    console.log('이름: ' + this.name);
    console.log('나이: ' + this.age);
}

const test = new People('A', '30');
const test2 = new People('B', '20');

test.info();
test.info();

그렇다면 프로토타입을 사용했을때 무엇이 달라질까?

 

- 프로토 타입을 사용하지 않은경우 객체하나를 생성할때마다 info라는 메소드가 할당된다. 즉 2개의 객체를 생성하면 2개의 info가 할당되는 셈이다

 

- 반면 프로토타입을 사용한경우 People객체는 하나의 info메소드를 생성하고 객체에서 참조하여 사용하게 된다.

즉 2개의 객체를 생성했지만 info 메소드는 1개만 생성되는 차이가 있다.

 

- 이로서 프로토 타입은 불필요한 메모리 낭비를 막을 수 있는 중요한 개념이다.

 

프로토타입을 이용한 상속은 다음과 같다.

function People(name, age) {
    this.name = name;
    this.age = age;
}

People.prototype.info = function() {
    console.log('이름: ' + this.name);
    console.log('나이: ' + this.age);
}

function Child (name, age) {
    People.call(this, name, age);
}

Child.prototype = People.prototype;

const child = new Child('test', '30');

child.info();

2. 클래스

- 타언어의 클래스와 매우 유사하다 (JAVA, C...등)

ES6에서 새로 생긴 문법으로 기존 prototype을 활용한 객체 생성자를 클래스로 더 쉽게 표현할 수 있다.

class People {
  constructor(name, age) {
    this.name = name;
    this.age = age;
    this.info = function() {
      console.log('이름 :' + this.name);
      console.log('나이 :' + this.age);
    }
  }
}

const people = new People('A', '10');
people.info();

- 클래스 상속은 다음과 같다.

class People {
  constructor(name, age) {
    this.name = name;
    this.age = age;
    this.info = function() {
      console.log('이름 :' + this.name);
      console.log('나이 :' + this.age);
    }
  }
}

class Child extends People {
  constructor(name, age) {
    super(name, age);
  }
}


const child = new Child('A', '10');
child.info();
반응형
반응형

V자바스크립트의 실행 컨텍스트에 대해 간단하게 알아보는 시간을 가진다.

- 먼저 실행 컨텍스트란 왜 자바스크립트가 그렇게 동작하는지를 의미한다.


1. 실행 컨텍스트

function sum(a, b) {
	let res = a + b;
    return res;
}

let num = sum(1,2);

- 같은 코드가 존재한다고 가정했을때 동작 순서는 다음과 같다.


2. 콜 스택

- 코드가 실행될때 호출 스택이 쌓이는 부분

function sum(a, b) {
	let r = a + b;
    return r;
}

function calc(a, b, expr) {
	let result = expr(a, b);
    return result;
}

let num = calc(1, 2, sum);

- 다음과 같은 실행 순서로 동작한다

- 16번 후 expr() pop되어 제거
- 17번 후 calc() pop되어 제거

 


3. 스코프

- 현재 접근할 수 있는 변수들의 범위를 의미함

반응형

'프로그래밍 > Javascript' 카테고리의 다른 글

[JS] 호이스팅, Hoisting 이란?  (0) 2022.06.01
[JS] 프로토타입, 클래스란?  (0) 2022.05.26
반응형

Spring Security를 이용하면서 Config파일이 동작하지 않는 문제가 발생했다.

 

1. 문제

아래와 같이 config를 작성했는데 동작하지 않았다. 심지어 모든 /** 경로를 허용해도 계속 스프링 시큐리티 기본 로그인 화면만 뜨는 문제가 발생했다.


2. 원인

- 원인은 생각보다 간단했다. 나의 경우 spring boot를 사용하고 있었고, boot를 실행하는 스프링부트 어플리케이션 클래스가 최상단에 위치해야 config파일이 정상적으로 동작한다

 

즉 기존에 SecurityConfig가 스프링 어플리케이션 파일보다 바깥쪽에 위치하여 설정이 되지않았던 것이다.

 

 

※ 하지만 왜 스프링부트는 정상적으로 동작한걸까? 한번 확인이 필요하다.

반응형
반응형

Vue 에서 ES6 화살표 함수를 적용하려 할 때 다음과 같은 문제가 발생한다.

1. 문제점

created: () => console.log(this.a)  // 오류. this 는 vue instance 가 아닌 window
// 다른 상태 mounted, udpated, destroyed 등 포함
data: () => ({
  item: ''
}),
methods: {
  // 화살표함수
  methodA: () => {
    // this 는 window
    alert(this == window) // true
    this.methodB() // 오류
  },
  // 기존 함수
  methodB: function(){
    // this 는 현재 vue instance
    this.methodA() // 정상
  },
  // 리터럴 축약 함수
  methodC() {
    this.methodA() // 정상
  }
  
  addTodo: () => {
  	console.log(this.item) //undefined
  }
}

2. 원인

화살표 함수의 this는 기존 es5의 function에서의 this와는 다르게 화살표 함수 내부에서는 this를 새로 정의하지 않는다.

즉 화살표 함수 바로 바깥의 함수(혹은 class)의 this를 사용한다. (클로저)

methods: {
  // 화살표함수
  addTodo: () => {
  	console.log(this.item) //undefined
  }
}

methods 객체에서 this가 따로 만들어져 있지 않으므로 this는 window 객체를 의미하고 vue data를 찾지 못하게 된다.


3. 추가 내용

new Vue({
	el: "#app",
  data: {
    originalNumber: 0,
    arrowNumber: 0,
  },
  methods : {
    originalFunction: function () {
      setTimeout(function () { // 기존함수 선언법
      	console.log('original timeout')
      	this.originalNumber = 3
      }, 3000)
    },
    arrowFunction: function () {
      setTimeout(() => { // 화살표 함수
      	console.log('arrow timeout')
      	this.arrowNumber = 3
      }, 3000)
    }
  }
})

반대로 함수 안에 화살표함수와 function()을 사용했을때는 어떨까?

 

결과는 function()은 오류가나고, 화살표 함수는 정상 동작한다.

 

화살표함수의 this.는 상위 메소드의 this 즉 vue 인스턴스를 가르키고 있고, function()의 this는 vue가 아닌 새로운 function()함수를 가르키고있기 때문이다

반응형
반응형

1. 코틀린이란?

- 코틀린(Kotlin)은 인텔리제이(IntelliJ IDEA)라는 제품으로 유명한 젯브레인(JetBranins)에서 만든 언어로, 2011년 최초로 공개된 후 오랜 시간 개발을 거쳐 2016년 2월 1.0 정식 버전이 출시되었습니다.

코틀린은 간결한 문법과 풍부한 기능, 높은 안정성을 토대로 높은 생산성을 보장하는 것을 목표로 개발되었습니다. 또한, 자바와 호환되어 자바로 작성된 프로젝트에 코틀린 코드를 추가할 수도 있고 자바 코드를 모두 코틀린으로 대체 할 수도 있습니다. 뿐만 아니라, 코트린은 구글의 연례 개발자 행사인 구글I/O 2017에서 안드로이드의 공식 지원 언어로 채택되었습니다.


2. 코틀린의 컴파일 과정

Java 코드와 Kotlin 코드가 함께 있는 프로젝트의 빌드 과정

  1. Kotlin 컴파일러가 Kotlin 코드를 컴파일해 .class 파일을 생성한다.
    이 과정에서 Kotlin 코드가 참조하는 Java 코드가 함께 로딩되어 사용된다.
  2. Java 컴파일러가 Java 코드를 컴파일해 .class 파일을 생성한다.
    이때 이미 Kotlin이 컴파일한 .class 파일의 경로를 클래스 패스에 추가해 컴파일한다.

3. 코틀린 자바의 차이

3.1 변수 선언

- 자바 변수 선언

String value = "test";       // 변수
final String value = "test";    // 상수

//new 키워드로 클래스 선언
Test test = new Test();

- 코틀린 변수 선언

var/val 변수명: 변수타입 = 초기화

변수 타입 생략 가능 (컴파일러가 타입을 정해줄 수 있음 = 타입추론(TypeInference))

var value: String = "test"   // 변수
val value: String = "test"   // 상수

var value = "test"
val value = "test"

val test:Test = Test()

 

3.2 변수 null 여부

자바 변수 선언

@NotNull
String value = "test";
@Nullable
String value = "test";

- 코틀린 변수 선언

특징으로는 컴파일시 null여부를 확인한다.

var value: String = "test"   // @NotNull
val value: String? = "test"   // @Nullable

3.3 접근 제한자

자바 접근 제한자

public    : 모든 접근을 허용
protected : 같은 패키지(폴더)에 있는 객체와 상속관계의 객체들만 허용
default   : 같은 패키지(폴더)에 있는 객체들만 허용
private   : 현재 객체 내에서만 허용

- 코틀린 접근 제한자

- 코틀린 공식 문서에 따르면 internal이 말하는 '같은 모듈'은 아래 상황을 뜻합니다. 쉽게 생각해 같은 프로젝트 라고 생각하면 좋을 것 같습니다.

  • IntelliJ IDEA Module
  • Maven Project
  • Gradle Source Set(with the exception that the test source set can access the internal declarations of main)
  • a set of files compiled with one invocation of the <kotlinc> Ant task
public		: JAVA와 동일
private		: JAVA와 동일
protected	: JAVA와 동일
internal	: 같은 모듈 내에서 어디서든 접근 가능

 

3.4 함수 선언

자바 함수 선언

public int sum(int a, int b) {
	return a + b
}

- 코틀린 함수 선언

fun으로 선언, 함수명(파라미터): 리턴타입

사용되는 파라미터 (a, b)는 상수인것이 특징

fun sum(a: Int, b: Int): Int {
    return a + b
}

 

3.5 클래스 선언

- 자바 클래스 선언

public class Test {
    private String name;

    public Test(String name) {
        this.name = name;
    }
    
    public String getName() {
    	return name;
    }
}

 

- 코틀린 클래스 선언

class Test(val name: String)

//getter, setter 자동으로 만들어줌

내부 name변수 사용할때는 test.name으로 사용할 수 있음

val test:Test = Test("mylee")

// mylee
println(test.name)

test.name = "testName"

// testName
println(test.name)

4. 코틀린의 장 단점

4.1 널 안정성 (null safety)

만약 아래와 같은 함수를 가진 자바 라이브러리를 코틀린에서 사용한다고 할 때 코틀린에서 리턴타입 String을 String?(nullable)로 인식한다.

String getStr() {
  ....
  return str;
}

따라서 아래와 같은 코드는 컴파일 시점에서 에러가 발생한다.

NotNull 변수에 nullable을 리턴하는 함수를 사용했기 때문이다. 이렇게 컴파일 시점에서 Null 에러를 잡아낼 수 있다.

(nullable을 리턴하는 코틀린 함수여도 마찬가지)

var test: String = getStr()

만약 아래와 같이 !! 연산자를 이용하면 컴파일 오류를 피할 수 있다. (!! 연산자는 Null이 아님을 보장할 수 있음) 하지만 Null값이 들어오면 에러 발생

var test: String = getStr()!!

 

safety call (안전한 호출)

자바에서 다음과 같이 String을 대문자로 변환할 때 만약 변수가 null이라면 에러가 발생한다.

String str; 가 있다고 가정

// str값이 null일 경우 에러 발생
System.out.println(str.toUpperCase());

따라서 if문이나, 삼항연사자 같은 방법으로 에러를 피함

 

코틀린에서는 이런 Null에러를 피하기위해 Safety call을 제공한다.

?. 연산자를 사용하면 null일경우 다음 함수를 호출하지 않는다.

println(str?.toUpperCase())

?: (엘비스 연산자)

삼항연산자와 비슷한 구조인데 b?.length가 null일경우 오른쪽 -1을 리턴하게 된다.

println(b?.length ?: -1)

 

4.2 코드가 간결해짐

- 클래스, 함수형 프로그래밍 등 코드가 간결해 질 수 있음. 예제로 filter같은 예시를 들어놓은 블로그가 있는데 자바에서 Stream사용하는거랑 큰 차이가 있는지는 잘 모르겠음.

 

4.3 함수형 프로그래밍 가능

- 자바 8 이상에서 Stream 같이 사용하면서 느낀 장점 사용 가능

 

4.4 자바와의 호환

- 프로젝트내에서 자바와 함께 사용할 수 있다.

 

단점 : 빌드시간이 오래걸린다(?)

- 큰 프로젝트를 빌드해보지 않아서 겪어보지 못함

----------------------------------------------------------------------

반응형

+ Recent posts