TIL - 0820

정리해보기

객체지향

  • 객체지향 : 분업화, 하나의 세상을 이루기위해서 하나의 존재만이 있는 것이 아니라 여러 존재들이 협업하면서 세상을 이룸, 협업이 필요하다면 필요한 객체가 다른 객체에 메세지를 보내 요청함, 파일로 코드를 분리한 것과는 전혀 다른 개념임(저장 공간만 달리할 뿐 하나로 처리하는건 마찬가지)

  • 객체지향의 장점 : 역할 별로 객체를 나누다보니 어떤 한 기능을 수정할 때 담당 객체의 코드만 수정해주면 됨 - 변경점이 하나로 모임, 변경사항이 생기더라도 유연하게 대처할 수 있음(코드 간의 의존성이 적기때문에 - 물론 객체지향적인 프로그래밍을 했다면), 역할 별로 코드가 나뉘어져있다보니 부분 기능을 이해하기 좋음

  • 객체지향의 단점 : 개인적으로 러닝커브라고 생각됨 객체지향을 어렵게 배우면 어렵게 배울 수 있기때문에 잘못 접근하면 굉장히 어려워짐(특히 객체지향 원칙, 패턴부터 접근해서 공부한다면), 객체지향에 대한 이해 없이 코드를 이해하려고 하면 역할 별로 코드가 많이 나뉘어져있으므로 보기 어려울 수 있음(장점이 곧 단점이 될 수 있음 - 객체지향에 대해 모른다면), 런타임 상이면서 멀티 쓰레드 환경일 때 공유 객체에 대해 동시에 접근해서 동시에 상태값을 바꿔 예기치 못한 결과가 나올 수 있음 - Lock 정책을 잘 사용하던지, 입력값 -> 결과값만 도출하고 상태값을 변경시키지 않는 함수형 프로그래밍 개념이 도입된 스트림 API를 적극적으로 사용하던지 해야함

  • 기억에 남는 디자인 패턴 : 전략 패턴, 전략이라는 인터페이스를 만들어 놓은 뒤 여러 전략을 만들고 전략을 사용하는 쪽에서 여러 전략을 런타임 상에서 DI 받으면서 전혀 다른 동작을 할 수 있게 만들 수 있음 - 객체지향 요청, 위임, DIP(큰 개념에 의존), DI 등 중요 개념을 하나의 패턴을 실전에 적용하다보니 이해할 수 있게 되어서 기억에 남음

  • DI : 기능은 필요한데, 자신의 역할과는 별개의 기능이 필요할 때 굳이 구현하기보다 위임할 수 있게 필드로 선언해둠, 그리고 매번 바꿔치기할 수 있는 창구를 만들어두는 것(인젝션 방법은 3가지가 있음 - 필드, 생성자, 메소드), 모든 일을 내가 하는게 아니라 그 역할을 맡은 이에게 위임

Java

  • jvm의 역할이 무엇인가요 : 자바 프로그램(.class - 컴파일러에 의해 바이트코드로 컴파일) 실행, 가상의 컴퓨터 구조를 갖춤 - 프로그램인데, 컴퓨터처럼 만들어진 프로그램
  • 힙과 스택의 차이점 : 쓰레드 간의 공유를 하는 메모리 공간과 쓰레드 간의 독립적으로 할당되는 공간, 전역 객체(공유)의 경우에 race condition이 생기는 이유 - 힙 메모리에 저장되고 힙 메모리는 쓰레드 간 공유가 됨
  • 리플렉션 API의 용도 : 런타임에 클래스가 로드되어 메모리에 있다면 메모리에 있는 것을, 아직 로드 되어있지 않다면 클래스로더로 클래스를 로드(메소드 영역)하여 클래스의 정보를 가져올 수 있는 API - 선언된 메소드 개수 혹은 이름, 어노테이션 적용 정보, 클래스명 등등
  • Collection API에 대한 이해 - SET : 한번에 중복된 데이터를 걸러낼 수 있는 콜렉션 API - key만 가지는 hashtable
  • enum을 사용해서 상수를 정의하는 이유 : 안전한 프로그래밍을 할 수 있기 때문에 - 문자열로 인자를 받으면 잘못된 값을 받았을 때에 대해서 조건문 처리로 걸러내야하지만 애초부터 enum을 정의하고 enum을 인자로 받으면 선언되어있는 enum 원소(객체)만 인자로 받을 수 있음, 또한 enum 에 기본적으로 정의되어있는 메소드들을 사용할 수 있고 사용자 정의 메소드를 만들 수 있음(primitive type을 wrapper로 바꿔서 사용하는 이유와 같음)

  • 단위테스트를 하면? 여러 테스트 케이스에 대해 한꺼번에 테스트할 수 있음, 안전한 프로그래밍 가능(기능을 추가, 삭제 등 변경할 때마다 테스트케이스를 실행하고 성공이 되었을 때 프로그래밍한 부분에 대해서 잘 만들어졌구나에 대해 걱정하지않아도 됨)

Spring

  • 스프링에 대해 정의해보세요 : Java EE로 어플리케이션을 만들 때 조금 더 개발자가 편하게 만들 수 있게 제공되는 프레임워크 - 짜여진 틀에 프로그래밍만 해두면 실행됨, 프로그래밍할 때에도 API 그대로 사용하지않고 추상화된 API를 사용함(장점이자 단점 - 원리를 알기위해 추상화된 부분에 대해 공부할 필요가 있음 - 장애 발생 시 혹은 잘되는데 이유를 몰라 파악을 하려면 확실히 알아야 파악가능함)

  • 빈 컨테이너와 스프링 빈 : 스프링 빈 == 스프링 빈 컨테이너에서 관리하는 인스턴스(생명주기를 관리 : 생성부터 사용 제거까지)
  • AOP : 비즈니스 로직은 아니지만 시스템을 구성하는데에 있어서 필요한 인프라로직을 만들고, 여러 군데 인프라 로직을 적용하려다보니 중복이 발생해서 인프라 로직만 따로 빼내어서 프로그래밍하는 것, 어디에 적용될지 / 어떤 인프라 로직이 적용될지를 정하기만하면 됨(예를 들어 선언적 트랜잭션인 @Transactional) - 전처리, 후처리 로직을 만들고 싶은데 중복이 되니깐 따로 빼내어서 한 곳에 프로그래밍 한 뒤 적용만 시킴(중복 제거와 동시에 비즈니스 로직과 인프라 로직을 분리할 수 있음)

ORM - JPA/Hibernate

  • ORM : 객체와 관계형 데이터베이스의 테이블을 맵핑해주는 프레임워크, 객체지향 개발자들이 객체지향적으로 지속적으로 개발 할 수 있도록 도와줌(패러다임 불일치를 맞춰줌 - equals/pk, 데이터타입, 연관관계/JOIN)
  • JPA/Hibernate : JPA는 자바진영의 ORM 표준, Hibernate는 JPA 구현체(사실 Hibernate가 너무 잘만들어져있어서 JPA가 Hibernate 개발자를 리더로 JPA를 만듦)
  • JPA 성능 상 이점 : 메모리 상에서 해결할 수 있는 문제를 모두 해결한 뒤 꼭 필요할 때 데이터베이스 접근 뒤 쿼리를 날림 - 지연쓰기, 캐시, lazy loading(꼭 필요할 때 연관관계의 객체를 쿼리로 날리고 가져옴 - 메모리 상에서도 이득)
  • JPA 단점 : 러닝커브가 너무 높음(게다가 RDBMS에 대해서 잘 모르면 JPA도 잘 쓸 수 없음)

데이터베이스(RDBMS)

  • Relation : 2차원 표에 데이터를 저장하는 데이터베이스를 말함, 하나의 테이블에 모든 데이터를 저장하는 것이 아니라 기준별로 테이블을 나누고 각 테이블 간의 관계를 가질 때 관계를 맺어줄 수도 있어서 Relation이라는 말을 붙였다고 하기도 함
  • 트랜잭션 : 여러 쿼리를 하나의 작업으로 만드는 것, 즉 쿼리 하나라도 실패하면 실패하는 것이므로 상태를 원상태로
  • 트랜잭션 처리 시 가져야할 4가지 특성 : 원자성(하나로 묶인 쿼리는 더이상 쪼갤 수 없는 작업 단위), 지속성(트랜잭션 전후로 데이터 무결성이 지속되어야함 - 개체, 참조, 데이터 범위 무결성), 격리성(트랜잭션 간 간섭을 일으켜서는 안됨 - 성능과도 맞물려있음), 내구성(한번 반영된 데이터는 영구적으로 저장되어야함 - COMMIT되면 영구저장)

  • 트랜잭션 여러개 처리할 때 간섭과 성능 사이 트레이오프 Lock 레벨(격리 레벨) 4가지
    1. Read Uncommitted : 데이터베이스 반영되지않은 데이터 변경까지도 다른 트랜잭션에서 읽을 수 있음, 간섭이 가장 심한 단계, 성능 상으로는 가장 좋음(완전한 동시처리), 반복읽기가 불가하고, 예상치 못한 결과가 나올 수도 있음(상태 변경 시킨 쪽이 롤백 되었을 시 - 이미 변경된 값을 읽어 작업할 수 있기대문에), 팬텀 읽기가 가능(같은 트랜잭션에서 읽었는데 개수가 다름)
    2. Read Committed : 데이터베이스에 반영된 것만 읽기 가능, Dirty Read는 해결되었지만, 반복읽기와 팬텀읽기는 여전히 가능
    3. Repeatable Read : 반복 읽기가 가능함, Select된 부분에 대해서는 수정이 불가함(Lock), 추가와 삭제는 가능해서 팬텀읽기는 가능함
    4. Serializable : 완전한 직렬 처리, 성능 상 가장 느리지만 확실하게 데이터베이스 반영 - 처리를 하기위해서는 필요함, 팬텀 읽기까지 불가
  • 인덱스 : 빠르게 써치하기위해 따로 특정 컬럼 데이터를 자료구조(BTree)에 정리(정렬해서)해둠 : 원래 데이터는 특정 컬럼 기준 정렬되지않은 채로 있음, 무조건적으로 좋지는 않음(저장 크기가 늘어남, 변경이 많이 일어날 때 수정을 그만큼 해야함), 중복 수치가 많은 데이터를 인덱스로 만들 경우 그 효율을 보지못함(남/여) - 카디널리티가 높은 데이터

네트워크 - HTTP 통신

  • 호스트 식별에 필요한 요소 : IP(호스트 식별) + Port(프로세스 식별) - 클라이언트/서버
  • HTTP는 무상태 : TCP 커넥션 제거 - 이전 클라이언트에 대한 정보를 가져있지않음 - 정보를 저장하기위해 쿠키를 사용, 정보를 클라이언트에 저장하면 쿠키, 식별값만 클라이언트에 저장하고 실제 클라이언트 정보를 서버에 저장하면 세션
  • HTTP와 HTTPS 차이 : 서버가 신뢰할 수 있는 서버인지 확인하는 절차가 하나 더 생김, 민감한 정보를 전달할 때 잘못된 곳으로 전달될지 모르니 신뢰할 수 있는 서버인지 확인 절차를 거치게됨, 데이터를 암호화하기도 함

Architecture

  • REST API에서 REST는 무엇인가? 웹어플리케이션 컴포넌트(클라이언트, 서버)의 독립적인 성장을 위해 어떻게 API의 디자인을 해야할지 정해둔 원칙 - 단순히 json을 리턴이라고해서 REST API가 아니라 JSON WEB API 혹은 HTTP API, HATEOAS(어플리케이션 상태 전이는 링크를 통해서 - 그러려면 현재 상태에서 전이될 수 있는 링크를 서버에서 전달해줘야함, 무엇을 할지 클라이언트가 선택할 수 있도록 선택지를 줘야함)와 uniform-interface(self-descriptive : 부가적인 정보없이도 메세지 그자체로만 보고 클라이언트가 어떤 처리를 할지 알아야함, 그렇지않으면 디펜던시가 생겨 서버에 변경이 생길 때마다 클라이언트는 독립적으로 처리를 하지못하고 서버에 연명해야함)를 보통 못지킴, 하위 호환성도 깨뜨리면 안됨 - 오래되었다고 해서 무조건 없애버리고 새롭게 바꿔버리면 안됩니다요

  • 사용자 트래픽이 증가하여 서버를 증설하려고 하는데, 아키텍쳐에 대해서 그려보고 예상되는 문제와 해결 : 클라이언트에 대한 상태를 서버에서 관리하고 있을 때 상태에 대한 공유(동기화 - 비효율적) 혹은 세션 클러스터링 혹은 JWT 사용(key만 공유하기)
  • 리버스 프록시 : 몸빵 역할 - 리퀘스트를 모두 받아들임, 실제 서버를 감출 수 있음(보안) - 공격을 미리 차단시킬 수 있음, 분산처리 가능(일종의 중간계층이 하나 더 생기는 것)