no image
[MYBATIS] choose 절을 이용한 DynamicSQL
MyBatis에서 choose 절을 활용한 동적 쿼리를 작성할 수 있다. 보통 특정 조건에 따라 쿼리의 형태가 다이나믹해지므로 MyBatis에서 많이 사용되는 방법으로 절이 있다. ,, 우선 위 세가지 종류를 사용한다. select * from table1 where deleted = false and a = 1 and a = 2 and a = 3 and a is not null 전체 choose 조건문의 범위를 결정하는 태그를 시작으로 의 검증부분을 통해 조건을 건다. a 라는 변수는 자바 Interface Mapper에서 넘어온 파라미터 그대로 사용할 수 있다. 태그는 else랑 비슷한 느낌이지만, 떄로는 default의 의미로 사용될 수 있다. 위 쿼리처럼 존재하는지 여부만 확인할 경우 defaul..
2022.03.03
no image
[Code] Refactoring , 리펙토링
리펙토링이란 일련의 리펙토링을 적용하여 겉으로 보이는 동작의 변화없이 소프트 웨어 구조를 바꾸는 것이다. 리펙토링은 외부 동작을 바꾸지 않고 내부 구조를 개선하는 방법이기도하고 , 코드가 작성된 후 디자인을 개선하기도 한다. 리펙토링은 처음부터 좋은 방법을 생각하기 보다 개발해가면서 지속적으로 좋은 디자인을 찾는것이 좋다. 🔓리펙토링의 목적 소프트 웨어를 보다 이해하기 쉽고, 수정하기 쉽도록 만드는 것이고 리펙토링은 겉으로 보이는 소프트웨어의 기능은 변경하지 않는 것이다. 🔓리펙토링을 하는 이유 코드의 구조가 망가지면 당시에는 괜찮을 수 있으나 망가진 구조의 효과는 계속 누적된다. 코드의 디자인을 유지하도록 해주고 불필요한 중복을 제거함으로써 각각의 작업에 대한 코드가 한 곳에만 있게 할 수 있다. 소프..
2022.02.28
no image
[MYSQL] MYSQL Partition - 테이블 분할
MYSQL_Partition 파티션은 크기가 큰 테이블을 여러 개로 분할하는 기능이다. 크기가 큰 테이블에 쿼리를 수행할 때, 인덱스를 사용하더라도 테이블의 크기가 매우 크다면 MYSQL에 부하가 걸릴것이다. 이런 문제를 줄이고 성능 향상을 위해 사용하는 기능이다. Partition을 사용하는 이유 인덱스는 SELECT 성능을 위해 사용하긴 하지만 오로지 SELECT를 위해 사용하는 것은 아니다. UPDATE,DELETE,INSERT를 위해서도 사용된다.데이터를 변경하는 쿼리를 실행하면 인덱스의 변경을 위한 추가적인 작업이 발생하지만 UPDATE 나 DELETE 를 위해서는 해당 데이터를 검색하려면 인덱스가 필수적이다. 그러나 인덱스가 커지게 된다면 SELECT의 성능 저하는 당연한것이고 INSERT나 ..
2022.02.24
no image
[mybatis] Association과 Collection
예제 상황으로 학교에는 학생이 존재하고 학생마다 학생증을 하나씩 가지고 있다. 🤖 Association(has one) Association은 has one 타입의 관계를 다룰 때 사용한다. 예를 들어 학생이; 가지고 있는 학생증은 학생 한 명만 가질 수 있다. 예를 들어 해당 학생증을 조회하려고 할 때 association 관계를 걸어서 같이 조회하면 다음과 같다. class StudentCard { ... Student student; } class Student { int studentId; ... } 우선 학생과 학생증은 1 : 1 관계이다. SELECT student_id studentId, ... FROM student WHERE student_id = #{studentId} SELECT ....
2022.02.22
no image
[DB]DB Partitioning [DB 파티셔닝]
🧑🏻‍💻DB 파티셔닝 서비스의 크기가 점점 커지고 DB에 저장하는 데이터의 구모 또한 대용량화 되면서, 기존에 사용하는 DB 시스템의 용량의 한계와 성능의 저하를 가져오게 되고 VLDB와 같이 하나의 DBMS에 너무 큰 table이 들어가면서 용량과 성능 측면에서 많은 이슈가 발생하게 되었고 , 이런 이슈를 해결하기 위한 방법으로 테이블을 파티션이라는 작은 단위로 나누어 관리하는 파티셔닝 기법이 나타나게 되었다. 파티셔닝은 논리적인 데이터 element들을 다수의 entity로 쪼개는 행위를 뜻하는 일반적인 용어이다. 큰 테이블이나 인덱스를 관리하기 쉬운 파티션이라는 작은 단위로 물리적으로 분할하는 것을 의미한다. DB에 접근하는 Application의 입장에서는 물리적인 데이터 분할이 있지만 인식하지 ..
2022.02.15
no image
빅데이터 처리
# 배치 처리(batch_processing) 일괄 처리(batch_processing)란 컴퓨터 프로그램 흐름에 따라 순차적으로 자료를 처리하는 방식을 의미한다. 일괄처리 방식은 사용자와 상호작용하는 것이 초기에는 불가능했지만, 운영체제가 발전하면서 프로그램 입출력을 통해 상호작용화는 것이 가능해졌다. 배치 처리 방식은 간단히 말하면 일정기간 또는 한정된 데이터를 모아두었다가 한 시점에 순차적으로 처리하는 방식이다. 맵리듀스(Mapreduce) 기법인 하둡 또한 배치 처리 방식 중 하나이다. 배치 처리 방식은 일정 기간의 데이터를 일괄 처리하기 때문에 실시간 데이터는 조회하기 힘들다는 단점이 있다. 이런 단점을 극복하기 위해 최근에는 실시간 분산 쿼리나 스트리밍 기법이 많이 연구되고 있다. 출처 :ht..
2022.02.11
Dev
no image
[기술면접] JAVA
자바의 실행 과정 자바 소스 파일을 javac로 컴파일하여 클래스 파일을 생성함 클래스 로더가 컴파일된 자바 바이트코드를 런타임 데이터 영역으로 로드함 실행 엔진이 자바 바이트 코드를 실행함 자바의 장단점 장점 자바는 자바 가상 머신에서 동작하기 때문에 OS에 독립적이다. 가비지 컬렉터가 메모리를 관리해주기 때문에 편리하다. 스프링과 같은 자바를 지원하는 많은 오픈소스 프로젝트가 존재해서 짧은 개발 시간 내에 안정적인 프로그램 구현이 가능하다. 단점 자바 가상 머신에서 동작하기 때문에 실행 속도가 상대적으로 느리다. 다중 상속이나 타입에 엄격한 제약이 있는 것들이 많다. JVM 구조 메서드 영역 : static 변수, 전역 변수, class 정보들 저장 스택 영역 : 지역변수, 함수 등이 할당 힙 영역 ..
2022.01.24
Dev
no image
[기술면접]알고리즘 + 자료구조
알고리즘 알고리즘은 어떠한 문제를 해결하기 위한 여러 동작들의 모임을 의미한다. 버블 소트(bubble sort) 버블 소트는 서로 인접한 두 원소를 비교하여 정렬하는 알고리즘이다.(시간 복잡도 O(n^2)) 힙 소트(heap sort) 힙 소트는 주어진 데이터를 힙 자료구조로 만들어 최댓값 또는 최솟값부터 하나씩 꺼내서 정렬하는 알고리즘이다.(시간 복잡도 O(nlog2 n)) 머지 소트(merge sort) 머지 소트는 주어진 배열을 크기가 1인 배열로 분할하고 합병하면서 정렬을 진행하는 분할/정복 알고리즘이다. 퀵 소트(Quick sort) 퀵 소트는 매우 빠른 정렬 속도를 가진 분할 정복 알고리즘 중 하나로 합병 정렬과 달리 리스트를 비 균등하게 분할한다. 피봇을 설정하고 피봇보다 큰 값과 작은 값..
2022.01.23
Dev
728x90

MyBatis에서 choose 절을 활용한 동적 쿼리를 작성할 수 있다. 보통 특정 조건에 따라 쿼리의 형태가 다이나믹해지므로 MyBatis에서 많이 사용되는 방법으로 <choose>절이 있다.

<choose></choose>,<when></when>,<otherwise></otherwise>

우선 위 세가지 종류를 사용한다.

select *
from table1
where deleted = false
<choose>
    <when test="a != null and a == 1">and a = 1</when>
    <when test="a != null and a == 2">and a = 2</when>
		<when test="a != null and a == 3">and a = 3</when>
    <otherwise>
        and a is not null
    </otherwise>
</choose>

전체 choose 조건문의 범위를 결정하는 <choose> 태그를 시작으로 <when>의 검증부분을 통해 조건을 건다. a 라는 변수는 자바 Interface Mapper에서 넘어온 파라미터 그대로 사용할 수 있다.

<otherwise>태그는 else랑 비슷한 느낌이지만, 떄로는 default의 의미로 사용될 수 있다. 위 쿼리처럼 존재하는지 여부만 확인할 경우 default값을 is not null로 설정할 수도 있다.

그리고 mybatis의 특징으로 <when> 태그의 내부는 모든 태그가 들어올 수 있다. 또, when 절 안에 if 절로 세분화가 가능하고,foreach 절을 사용해서 loop를 돌릴 수도 있다.

select *
from tableA
where deleted = false
<choose>
    <when test="a != null and a.length > 0">
    	and a in <foreach item="a" collection="a_list" open="(" seperate="," close=")">#{a}</foreach>
    </when>
    <otherwise>
        and a is not null
    </otherwise>
</choose>
728x90
728x90

리펙토링이란 일련의 리펙토링을 적용하여 겉으로 보이는 동작의 변화없이 소프트 웨어 구조를 바꾸는 것이다.

리펙토링은 외부 동작을 바꾸지 않고 내부 구조를 개선하는 방법이기도하고 , 코드가 작성된 후 디자인을 개선하기도 한다.

리펙토링은 처음부터 좋은 방법을 생각하기 보다 개발해가면서 지속적으로 좋은 디자인을 찾는것이 좋다.

🔓리펙토링의 목적

소프트 웨어를 보다 이해하기 쉽고, 수정하기 쉽도록 만드는 것이고 리펙토링은 겉으로 보이는 소프트웨어의 기능은 변경하지 않는 것이다.

🔓리펙토링을 하는 이유

  • 코드의 구조가 망가지면 당시에는 괜찮을 수 있으나 망가진 구조의 효과는 계속 누적된다.
  • 코드의 디자인을 유지하도록 해주고 불필요한 중복을 제거함으로써 각각의 작업에 대한 코드가 한 곳에만 있게 할 수 있다.
  • 소프트웨어의 디자인을 개선시켜주고 더 이해하기 쉽게 해준다.
  • 디버깅을 하기 편리해진다.

🔓리펙토링을 해야하는 시기

  • 3번의 중복/ 3번의 동일한 행위하면 리펙토링을 한다.
  • 기능을 추가할 때 되도록이면 리펙토링을 하는 것이 좋다. 기능을 추가할 때 객체 지향의 특징을 살리려면 switch-case문은 지양하는 것이 좋다.
  • 버그를 수정 해야할 때 리펙토링을 한다.

🔓리펙토링 단계

  • Naming
    • 컴퓨터가 이해하는 코드는 개발에서 당연한 것이다. 좋은 프로그래머는 사람도 이해하기 쉽게 작성해야 한다.
  • 클래스의 메소드는 클래스의 변수를 사용한다.
    • 클래스 정보를 사용하고 있지 않다면 사용하고 있는 쪽으로 움직여야 한다.
  • 임시 변수 제거
    • 임시 변수는 종종 불필요한 파라미터를 많이 만들게 된다. 임시 변수는 하나의 메소드로 구현하여 리펙토링 하는게 좋다.
  • 다른 객체의 속성을 기반으로한 switch문
    • switch문을 함수로 추출하여 자신의 데이터를 사용하는 것으로 리펙토링 해야한다.
  • 메소드에서 두개의 클래스를 변수로 사용한다면 변화하기 쉬운쪽으로 메소드를 이동시켜 변화의 폭을 최대한 작게 만들어야 한다.
  • 기능이 한쪽으로 모여진 클래스를 추상화하여 상속관계로 표현할 수 있다.
  • 추후 리펙토링 → 테스트 → 리펙토링 → 테스트를 반복한다.

🔓리펙토링 예제

  1. 함수,변수명 변경
//before
public int getOrderPrice(int arg1, int arg2){
        return arg1 * arg2;
    }

//after
public int getOrderTotalPrice(int price , int quantity){
        return price * quantity;
}

첫번째 리펙토링 예제는 함수명을 직관적으로 바꾸고 , 변수명을 의미에 맞게 수정한 것이다.

  1. 메소드 추출을 통해 코드를 간소화 한다.
//before
public int getOrderTotalPrice1(int price, int quantity,double discount){
     return (int) ((price * quantity) * (discount/100));
}

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

//after
public int getOrderTotalPrice2(int price, int quantity,double discount){
    return (int) calculationOrderTotalPrice(price,quantity,discount);
}

private double calculationOrderTotalPrice(int price, int quantity, double discount) {
     return ((price * quantity) * (discount/100));
}

기능을 가지고 있는 메서드는 외부에서 건들지 못하도록 private 선언을 해준다.

🛠클린 코드와 리펙토링

클린 코드와 리펙토링은 큰 의미로 보면 비슷하다. 그러나 클린코드보다 리펙토링이 더 큰 의미를 가지고 있다.

클린코드는 단순히 가독성을 높이기 위한 작업으로 이루어 지지만 리펙토림은 클린 코드를 포함한 유지보수를 위한 코드 개선이 이루어 진다.클린 코드와 같은 부분은 설계부터 잘 설계된느 것이 중요하고 리펙토링은 추후에 개선해 나가는 것이 바람직 하다.

 

https://github.com/ryudongjae/blog-ex

 

GitHub - ryudongjae/blog-ex: 📁블로그 예제 코드

📁블로그 예제 코드 . Contribute to ryudongjae/blog-ex development by creating an account on GitHub.

github.com


REFERENCE

https://tasddc.tistory.com/85

728x90

'Dev > JAVA' 카테고리의 다른 글

[디자인 패턴]GoF 디자인 패턴  (0) 2022.03.15
[JAVA]반복문 안에서 List 요소 삭제  (0) 2022.03.04
[Design Pattern] 빌더 패턴(Builder Pattern)  (0) 2021.12.02
[JAVA]Optional이란?  (0) 2021.06.17
[JAVA]상속(Inheritance)  (0) 2021.06.16
728x90

MYSQL_Partition

파티션은 크기가 큰 테이블을 여러 개로 분할하는 기능이다.  크기가 큰 테이블에 쿼리를 수행할 때, 인덱스를 사용하더라도 테이블의 크기가 매우 크다면 MYSQL에 부하가 걸릴것이다. 이런 문제를 줄이고 성능  향상을 위해 사용하는 기능이다.

 

Partition을 사용하는 이유

인덱스는 SELECT 성능을 위해 사용하긴 하지만 오로지 SELECT를 위해 사용하는 것은 아니다. UPDATE,DELETE,INSERT를 위해서도 사용된다.데이터를 변경하는 쿼리를 실행하면 인덱스의 변경을 위한 추가적인 작업이 발생하지만 UPDATE 나 DELETE 를 위해서는 해당 데이터를 검색하려면 인덱스가 필수적이다.

그러나 인덱스가 커지게 된다면 SELECT의 성능 저하는 당연한것이고 INSERT나 UPDATE,DELETE 작업도 마찬가지로 느려진다.

테이블에서 데이터를 파티셔닝 할 수 있다면 효과적으로 데이터 처리가 가능하고 성능을 개선할 수 있다.

 

크기가 큰 테이블을 파티셔닝하지 않고 사용하는 것과 작은 파티션으로 나누어 크기를 줄였을 때 인덱스가 어떤식으로 사용되는지 아래 그림을 보자.

http://blog.skby.net/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%85%8C%EC%9D%B4%EB%B8%94-%ED%8C%8C%ED%8B%B0%EC%85%94%EB%8B%9D-table-partitioning/

왼쪽 그림처럼  파티셔닝을 하지 않고 그냥 사용하면 인덱스도 매우 커지고 물리적인 메모리 공간도 많이 필요해서 효율적이지 못하다.

그러나 오른쪽처럼 작은 파티션으로 나누어 사용한다면 물리적 메모리를 효율적으로 사용할 수 있고 성능적인 측면에서도 파티셔닝 하지 않은 것보다 효율적으로 사용할 수 있다.

 

MYSQL Partition 내부 동작

REATE TABLE rt_blog (

id INT NOT NULL,
writeDate DATETIME NOT NULL,
...
PRIMARY KEY(id)

)

PARTITION BY RANGE ( YEAR(writeDate) ) (

PARTITION p2020 VALUES LESS THAN (2021),
PARTITION p2021 VALUES LESS THAN (2022),
PARTITION p2022 VALUES LESS THAN MAXVALUE

);

동작 방식을 확인하기 위해 임시로 테이블을 생성했다.

 

이 테이블에서 writeDate에서 연도는 파티션을 하기위한 파티션 키로서 해당 레코드가 어느 파티션에 저장될지를 결정하는 역할을 한다.

 

[PartitionTable INSERT]

INSERT 쿼리가 실행되는 MYSQL서버는 INSERT되는 컬럼 값 중에서 파티션 키인 writeDate컬럼 값을 이용해 파티션 표현식을 평가하고, 그 결과에 따라 저장될 파티션을 결정한다.

 

INSERT되는 데이터가 파티션이 결정되면 그 후에는 일반적인 과정과 동일하게 진행된다.

 

[PartitionTable UPDATE]

UPDATE 쿼리를 실행하려면 변경 대상 데이터가 어느 파티션에 저장되어있는지 찾아야 한다. 이때 UPDATE쿼리의 WHERE조건에 파티션  키 컬럼이 조건으로 존재하면 그 값을 통해  데이터가 저장된 파티션에서 빠르게 해당 데이터를 검색할 수 있다.

 

만약 MYSQL에서 파티션 키 이외의 컬럼만 변경될 떄는 파티션이 적용되지 않은 일반 테이블과 마찬가지고 컬럼 값만 변경한다. 그러나 파티션 키 컬럼이 변경될 때는 해당 파티션에서 데이터를 삭제한 후 해당 데이터를 새로운 파티션으로 복사한다. 그 다음 파티션 키 컬럼을 변경 시켜준다.

 

[PartitionTable SELECT]

가장 중요한 SELECT 쿼리 성능이다. 파티션 테이블을 검색할 때 아래 조건에 따라 성능에 영향을 크게 준다.

 

SQL이 수행되기 위해 파티션 테이블을 검색할 때 성능에 크게 영향을 미치는 조건

  • WHERE 절의 조건으로 검색해야 할 파티션을 선택 가능한가
  • WHERE 절의 조건이 인덱스를 효율적으로 사용할 수 있는가

 

첫번째 조건의 결과에 의해 두번째 선택사항의 작업이 달라질 수도 있다.

그리고 두 조건이 모두 성립할 때 성능적으로 가장 효율적으로 처리될 수 있다. 두 조건이 성립되면 파티션의 개수와 상관없이 검색을 위해 필요한 파티션의 인덱스만 스캔한다.

 

MYSQL_Partition 형식

1 . Range

범위를 기반으로 파티션을 나누는 형식이다.

Range Partition은 날씨 기반 데이터가 누적되고 날짜에 따라 분석 삭제할 경우, 범위 기반으로 데이터를 여러 파티션에 균등하게 나눌 수 있는 경우, 대량의 과거 데이터 삭제 같은 경우에 사용한다.

Range Partition에서 null은 어떤 값 보다 작은 값으로 취급되기 때문에 컬럼에 null인 데이터가 insert 된다면 가장 작은 값을 저장하는 파티션에 저장된다.

 

아래는 연도를 범위를 기준으로 파티션을 생성한 것이다.

CREATE TABLE test (
    id INT NOT NULL,
    lname VARCHAR(30),
    datt DATE NOT NULL DEFAULT '2000-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    store_id INT NOT NULL
) PARTITION BY RANGE (YEAR(datt)) (
    PARTITION p0 VALUES LESS THAN (2020) ,
    PARTITION p1 VALUES LESS THAN (2021) ,
    PARTITION p2 VALUES LESS THAN (2022) ,
    PARTITION p3 VALUES LESS THAN MAXVALUE
    );

 

Partition 추가 

ALTER TABLE test ADD PARTITION(PARTITION p4 VALUES LESS THAN (2023));

Partition 삭제

ALTER TABLE test DROP PARTITION p4;

Partition 병합

ALTER TABLE test 
REORGANIZE PARTITION p2,p3 INTO (
PARTITION p23 VALUES LESS THAN (2020)
);

그리고 날짜 컬럼에 대한 Range 파티션 적용시 YEAR(),TO_DAYS()함수만 사용하길 권장한다. 두 함수는 MYSQL 서버 내부적으로 파티션 프루닝 처리가 되어 성능상의 문제가 발생하지 않지만 그 외의 함수는 파티션 프루닝이 제대로 작동하지 않을 수도 있기 때문에 지양하길 권장한다.

2 . List

List Partition은 RangePartition과 비슷하고,코드나 카테고리 등 특정 값을 기반으로 파티션을 나눈다.

List Partition은 파티션 키 값이 코드 값이나 카테고리와 같이 고정 값일 경우에 사용하고 파티션 키 값을 기준으로 레코드 건수가 균일하고 검색 조건에 파티션 키가 자주 사용되는 경우에 사용한다.

List는 Range와 다르게 null을 명시할 수 있지만, MAXVALUE는 지정할 수 없다.

 

CREATE TABLE test (
    id INT NOT NULL,
    name VARCHAR(30),
    datt DATE NOT NULL DEFAULT '2000-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT NOT NULL,
    store_id INT NOT NULL
) PARTITION BY LIST (job_code) (
    PARTITION p0 VALUES IN (2) ,
    PARTITION p1 VALUES IN (1,9) ,
    PARTITION p2 VALUES IN (3,6,7) ,
    PARTITION p3 VALUES IN (4,5,8, NULL)
    );

Partition 추가 

ALTER TABLE test ADD PARTITION(PARTITION p4 VALUES IN (3,10));

 

Partition 삭제

ALTER TABLE test DROP PARTITION p4;

 

Partition 병합 

ALTER TABLE test 
REORGANIZE PARTITION p2,p3 INTO (
PARTITION p23  VALUES IN (3,6,7,4,5,8,NULL)
);

 

3 . Hash

Hash Partition은 Hash 함수에 의해 레코드가 저장될 파티션을 결정하는 방식이다.

Hash Partition은 테이블의 모든 레코드가 비슷한 사용빈도를 보이지만 너무 커서 파티션이 필요한 경우 사용된다.

CREATE TABLE test (
    id INT NOT NULL,
    name VARCHAR(30),
    datt DATE NOT NULL DEFAULT '2000-01-01',
    separated DATE NOT NULL DEFAULT '9999-12-31',
    job_code INT NOT NULL,
    store_id INT NOT NULL
) PARTITION BY HASH (id)
PARTITIONS 4;

Partition 추가 

파티션의 갯수로 MOD 연산한 결과에 따라 각 레코드를 저장할 파티션을 결정하므로 새로이 파티션이 추가될 경우 파티션에 저장된 모든 레코드는 재배치 되어야 하므로 많은 부하가 발생한다.

//파티션 이름을 부여
ALTER TABLE test ADD PARTITION(PARTITION p5 ENGINE = INNODB);

 

Partition 삭제 

 

파티션 키 값을 이용하여 데이터를 각 파티션으로 분산한 것이므로 각 파티션에 저장된 레코드의 부류를 사용자가 예측할 수 없기에 해시나 키를 이용한 파티션에서는 파티션 단위의 삭제는 불가능하다.

 

Partition 분할 ,Partition 병합

분할은 불가능 하고 추가만 가능하다. 병합 기능도 제공하지 않지만 갯수를 줄이는 것은 가능하다.

4 . Key

MD5() 함수를 이용한 Hash 값을 기반으로 파티션을 나누고 Hash Partition과 거의 동일하다.

Key Partition은 선정된 파티션 키값에 대하여 내부적으로 MD5()를 이용하여 해시값을 계산하고, 그 값에 MOD를 적용하여 저장할 파티션을 결정한다.

 

 

728x90
728x90

예제 상황으로 학교에는 학생이 존재하고 학생마다 학생증을 하나씩 가지고 있다.

 

🤖 Association(has one)

 

Association은 has one 타입의 관계를 다룰 때 사용한다. 예를 들어 학생이; 가지고 있는 학생증은 학생 한 명만 가질 수 있다. 예를 들어 해당 학생증을 조회하려고 할 때 association 관계를 걸어서 같이 조회하면 다음과 같다.

class StudentCard {
  ...
  Student student;
}

class Student {
  int studentId;
  ...
}

우선 학생과 학생증은 1 : 1 관계이다.

<select id="selectStudent" resultType="Student">
  SELECT student_id studentId, ... FROM student WHERE student_id = #{studentId}
</select>
<resultMap id="studentCardResult" type="com.xxx.StudentCard">
  <association property="student" column="stuendId" javaType="Student" select="selectStudent"/>
</resultMap>

<select id="selectStudentCard" resultMap="studentCardResult">
  SELECT ..., student_id studentId, ... FROM studentCard WHERE studentCard_id = #{studentCardId}
</select>

association 태그에 colume은 조회할 selectStudent의 파라미터로 전달되고 studentCard를 조회하면서 함께 student를 조회하여 StudentCard 인스턴스 안에 멤버 변수로 있는 Student 인스턴스의 내용도 채워지게 된다.

 

 

{
“studentCard_id”:”1”,
“student”:{
 	“studentId”: “1”,
	“studentName” : “kim”,
	“age”:”19”
	}
	.
    .
    .
}

이런식으로 학생증을 정보를 조회했을 때 학생 정보가 같이 반환된다고 생각하면 된다.

🤖 Collection (has many)

class School {
 int schoolId;
 List<StudentCard> studentCards;
...
}

class StudentCard {
  int studentCardId;
  Student student;
  ....
}

StudentCard(학생증)과  School(학교)은 1 :N 관계이다. 

<resultMap id="schoolResult" type="School">
  <collection property="studentCards" javaType="java.lang.ArrayList" column="schoolId" ofType="StudentCard" select="selectStudentCardId"/>
</resultMap>

<select id="selectStudentCards" resultType="StudentCard">
  SELECT * FROM studentCard WHERE school_id = #{schoolId}
</select>

<select id="selectSchool" resultMap="schoolResult">
  SELECT school_id schoolId, .... , FROM school WHERE school_id = #{schoolId}
</select>

 

collection 태그에 javaType으로 ArrayList로 지정해주고 해당 List의 Generic Type을 StudentCard로 지정해주었다. 이런 식으로 작성하면 학교를 조회하면 학교에 존재하는 학생증 정보를 List에 넣을 수 있다.

 

{
“school_id”:”1”,
“school_name : “kkk”,
“studentCards”:{
		studentCard1:{
			“studentCardId”: “1”,
		},
        
		studentCard2:{
			“studentCardId”: “2”,
			.
			.
			.
		},

		studentCard3:{
			“studentCardId”: “3”,
			.
			.
			.
		},
			.
			.
			.
 		}

}

위처럼 조회 시 학교에 포함된 학생증 인스턴스도 포함되어 표시된다.

728x90
728x90

🧑🏻‍💻DB 파티셔닝

서비스의 크기가 점점 커지고 DB에 저장하는 데이터의 구모 또한 대용량화 되면서, 기존에 사용하는  DB 시스템의 용량의 한계와 성능의 저하를 가져오게 되고 VLDB와 같이 하나의 DBMS에 너무 큰 table이 들어가면서 용량과 성능 측면에서 많은 이슈가 발생하게 되었고 , 이런 이슈를 해결하기 위한 방법으로 테이블을 파티션이라는 작은 단위로 나누어 관리하는 파티셔닝 기법이 나타나게 되었다.


파티셔닝은 논리적인 데이터 element들을 다수의 entity로 쪼개는 행위를 뜻하는 일반적인 용어이다. 큰 테이블이나 인덱스를 관리하기 쉬운 파티션이라는 작은 단위로 물리적으로 분할하는 것을 의미한다. DB에 접근하는 Application의 입장에서는 물리적인 데이터 분할이 있지만 인식하지 못한다.

 

파티셔닝의 목적으로는 성능, 가용성, 관리 이용성 등이 있다.

성능적인 측면에는 특정 DML(Data Manipulation Language : 데이터 조작 언어)과 Query의 성능을 향상하고, Full Scan에서 데이터 Access의 범위를 줄여 성능 향상을 가져온다. 또, 대용량 Data Write 환경에 효율적이다.

많은 Insert가 있는 OLTP 시스템에서 Insert작업을 작은 단위인 partition들로 분산시켜 경합을 줄인다.

 

가용성적인 측면에는 물리적인 파티셔닝으로 인해 전체적인 데이터의 훼손 가능성이 줄어들고 데이터 가용성이 향상되고 , 각 분할 영역(partiton 별로)을 독립적으로 백업하고 복구할 수 있다.

테이블의 patition 단위로 Disk I/O를 분산하여 경합을 줄이기 때문에 UPDATE 성능을 향상한다.

 

관리 이용성 측면에는 큰 테이블들을 제거하여 관리를 쉽게 해 준다.

 

🛠파티셔닝 장단점

장점

  • 관리적 측면에서는 파티션 단위의 백업, 추가, 삭제, 변경이 가능하여 전체 데이터를 손실할 가능성이 줄어들어 데이터 가용성이 향상된다.
  • 파티션 단위로 백업 및 복구가 가능하다.
  • 파티션 단위로 I/O분산이 가능하여 UPDATE 성능을 향상한다.
  • 성능적 측면에서는 파티션 단위 조회 및 DML 수행이 가능하여 FULL SCAN에서 데이터 허용 범위를 줄여 성능 향상을 가져온다.
  • 필요한 데이터만 빠르게 조회할 수 있기 때문에 쿼리 자체가 가볍다.



단점

  • 테이블 간 조인에 대한 비용이 증가하고 테이블과 인덱스를 별도로 파티셔닝 할 수 없다.
  • 테이블과 인덱스를 같이 파티셔닝 해야 한다.

 

➡️수평 파티셔닝

하나의 테이블의 각 행을 다른 테이블에 분산시키는 것이다.

샤딩()과 동일한 개념이고 스키마를 복제한 후 샤드 키를 기준으로 데이터를 나누는 것을 말한다.

즉, 스키마가 같은 데이터를  두 개 이상의 테이블에 나누어 저장하는 것을 말한다.

 

특징

  • 퍼포먼스, 가용성을 위해 key 기반으로 여러 곳에 분산 저장하고 일반적으로 분산 저장 기술에서 파티셔닝은 수평 분할을 의미한다.
  • 보통 수평 분할을 한다고 했을 때는 하나의 데이터베이스 안에서 이루어지는 경우를 지칭한다.

장점 

  • 데이터의 개수를 기준으로 나누어 파티셔닝 한다.
  • 데이터의 개수가 작아지고 따라서 인덱스의 개수도 작아지게 된다. 자연스럽게 성능은 향상된다.

단점 

  • 서버 간의 연결과정이 많아진다.
  • 데이터를 찾는 과정이 기존보다 복잡하기 때문에 lantency가 증가하게 된다.
  • 하나의 서버가 고장 나게 되면 데이터의 무결성이 깨질 수 있다.

➡️수직 파티셔닝

테이블의 일부 열을 빼내는 형태로 분할한다.

모든 칼럼들 중 특정 컬럼들을 쪼개서 따로 저장하는 형태이고 스키마를 나누고 데이터가 따라 옮겨 가는 것을 말한다.즉 , 하나의 엔티티를 2개이상으로 분리하는 작업이다.

 

🛠수직 파티셔닝 장점

  • 자주 사용하는 컬럼 등을 분리시켜 성능을 향상할 수 있다.
  • 한 테이블을 SELECT 하면 결국 모든 칼럼을 메모리에 올리게 되므로 필요없는 컬럼까지 올라가서 한 번에 읽을 수 있는 ROW가 줄어든다. 이는 I/O 측면에서 봤을 때 필요한 컬럼만 올리면 훨씬 많은 수의 ROW를 메모리에 올릴 수 있으니 성능상의 이점이 있다.
  • 같은 타입의 데이터가 저장되기 때문에 저장 시 데이터 압축률을 높일 수 있다.

 

💡파티셔닝(partitioning) 분할 기준

📁Range Partitioning [범위 파티셔닝]

create table 주문( 주문번호 number, 주문일자 varchar2(8), 고객id varchar2(5) )
partition by range(주문일자) (
  partition p2009_q1 values less than('20090401')
, partition p2009_q2 values less than('20090701')
, partition p2009_q3 values less than('20091001')
, partition p2009_q4 values less than('20100101')
, partition p2010_q1 values less than('20100401')
, partition p9999_mx values less than( MAXVALUE )
);
  • 파티셔닝 테이블에 값을 입력하면 각 레코드를 파티션 키 컬럼 값에 따라 분할 저장하고, 읽을 때도 검색 조건을 만족하는 파티션만 읽을 수 있어 데이터 조회 시 성능을 크게 향상해준다.
  • 파티션 키로는 하나 이상의 칼럼을 지정할 수 있고, 최대 16개까지 허용된다. 보관 주기 정책에 따라 과거 데이터가 저장된 파티션만 백업하고 삭제하는 등 데이터 관리 작업을 효율적이고 빠르게 수행할 수 있는 것도 큰 장점이다.
  • 관리자의 실수로 신규 파티션 생성을 빠트리면 월초 또는 연초에 데이터가 입력되지 않는 에러가 발생하므로, maxvalue 파티션을 반드시 생성해 두는 것이 좋다.

 

📁Hash Partitioning [해시 파티셔닝]

  • 파티션 키에 해시함수를 적용한 결과 값이 같은 레코드를 같은 파티션 세그먼트에 저장해 두는 방식
  • 검색할 때는 조건절 비교 값에 해시함수를 적용해 읽어야 할 파티션을 결정하며, 해시 알고리즘 특성상 “==” ,“In-List” 이 두 조건으로 검색할 때만 파티션 Pruning이 동작한다.
  • 테이블 파티셔닝 여부를 결정할 대는 데이터가 얼마나 고르게 분산될 수 있느냐가 중요한 관심사이다. 해시 파티셔닝 할 때 특히 데이터 분포를 신중히 고려해야 하는데, 사용자가 직접 파티션 기준을 정하는 Range, 리스트 파티셔닝과 다르게 해시 파티셔닝은 파티션 개수만 사용자가 결정한다.

📁List Partitioning

create table 인터넷매물( 물건코드varchar2(5), 지역?류varchar2(4) )
partition by list(지역?류) 
(partition p_지역1 values ('서울'), 
partition p_지역2 values ('경기', '인천'), 
partition p_지역3 values ('부산', '대구', '대전', '광주'),
 partition p_기타values (DEFAULT) ) ;
  • 순서와 상관없이 불연속적인 값의 목록으로써 결정된다.
  • 단일 칼럼으로만 파티션 키를 지정해야 한다.
  • 리스트 파티션에도 default파티션을 생성해 두어야 안전하다.

📁결합 파티셔닝

  • 결합 파티셔닝을 구성하면서 서브 파티션마다 세그먼트를 하나씩 할당하고 서브 파티션 단위로 데이터를 저장한다.
  • 주 파티션 키에 따라 1차적으로 데이터를 분배하고, 서브 파티션 키에 따라 최종적으로 저장할 위치를 결정한다.

 

 

 

728x90

빅데이터 처리

ryudjae
|2022. 2. 11. 14:55
728x90

# 배치 처리(batch_processing)

일괄 처리(batch_processing)란 컴퓨터 프로그램 흐름에 따라 순차적으로 자료를 처리하는 방식을 의미한다. 일괄처리 방식은 사용자와 상호작용하는 것이 초기에는 불가능했지만, 운영체제가 발전하면서 프로그램 입출력을 통해 상호작용화는 것이 가능해졌다.
배치 처리 방식은 간단히 말하면 일정기간 또는 한정된 데이터를 모아두었다가 한 시점에 순차적으로 처리하는 방식이다. 맵리듀스(Mapreduce) 기법인 하둡 또한 배치 처리 방식 중 하나이다. 배치 처리 방식은 일정 기간의 데이터를 일괄 처리하기 때문에 실시간 데이터는 조회하기 힘들다는 단점이 있다. 이런 단점을 극복하기 위해 최근에는 실시간 분산 쿼리나 스트리밍 기법이 많이 연구되고 있다.

출처 :https://ko.wikipedia.org/wiki/%EC%9D%BC%EA%B4%84_%EC%B2%98%EB%A6%AC

실시간 분산 쿼리는 클러스터를 구성하는 노드가 각자 쿼리를 처리하게 해 한 번에 처리할 데이터의 크기는 작게 하면서 이를 병렬 처리해 응답 시간을 실시간 수준으로 높이는 방식이다.

스트리밍 처리는 끊임없이 들어오는 데이터를 유입 시점에 분석해 원하는 데이터 뷰로 미리 만드는 방식이다. 이 방식은 CEP(complex event processing)이라고 부른다.

분산 쿼리의 기본 동작 방식

분산 환경에서 데이터를 단일 부로 제공하는 것은 어렵다. 파티셔닝과 셔플은 기본적인 분산 처리 방식을 이다.

  • @파티셔닝
    • 파티셔닝은 특정 키를 기준으로 이 테이블을 여러 노드로 분할해 저장하는 방식이다. 키를 범위로 나눠 저장하거나(range partitioning), 키 값을 해시 키로 사용해 수평적으로 데이터를 나눠 저장할 수 있다(hash partitioning). 파티셔닝은 노드 간의 키 중첩을 없애기 때문에 각 노드 에서 파티션 키를 조인 키로 쓰는 경우 독립적인 조인 처리가 가능하다.
  • @셔플
    • 만약 파티션키로 조인하는 것이 아닌 다른 키로 조인해야 한다면, 데이터를 조인 키 단위로 모으는 재분할(re-partitioning) 과정이 필요하다. 이 과정을 셔플이라 하고, 셔플은 노드 간 데이터 전송을 많이 발생시키므로 부담이 된다. 만약 조인 할 테이블이 작은 크기의 테이블이라면 , 굳이 셔플하지 않고도 그 테이블만 다른 모든 노드로 복제한 다음 각 노드에서 조인할 수 있다. 이러한 방식을 broadcast Join이라고 한다.




데이터 집계(aggregation)는 두 단계로 나눌 수 있다. 개별 노드에서 각자 결과를 집계하고 그 결과를 모아 전체 결과로 집계한다. 그루핑(Group BY) 또는 정렬(Order By)도 집계 처리와 같이 두 단계로 수행한다. 각 노드의 수행 결과를 모아 처리하는 방식은 map reduce와 유사하다.



스트리밍 방식

스트리밍 데이터는 시간에 따라 지나가 버리지만 쿼리는 시점에 관계없이 동일한 조건으로 요청할 수 있다. 혹은 클러스터 내 노드 중 하나에 장애가 발생하더라도 쿼리를 다시 수행을 마쳐야 할 수도 있다. 계속 들어오는 데이터를 지속적으로 쌓아 두려면 많은 리소스가 필요한데, 리소스의 제약이 있다면 처리를 다음과 같은 방식으로 처리를 할 수 있다.

lineage tracking

분산 처리를 위한 노드 토폴로지에서 데이터는 일련의 이벤트처럼 흘러 다닌다. 최초에 입력된 데이터는 여러 노드에 걸쳐 처리된 후 최종 결과를 데이터베이스에 저장한다. 노드는 입력된 데이터를 특정 조건으로 필터링하거나, 이전 노드에서 온 데이터를 합치거나(merging), 그루핑(grouping)하거나, 정렬(ordering)하거나 집계(aggregation)할 수 있다. 이런 처리 과정 중 특정 노드에서 수행에 실패하면 이를 검출하고 다시 수행해야 한다.
lineage tracking은 각 이벤트마다 이진 값 형태의 시그니처(signature)를 부여한다. 어떤 노드로 이벤트를 보내면 다운스트림 노드는 이벤트를 처리한 후 그 이벤트의 시그니처를 XOR 연산하고, 결국 이벤트가 최종 목적지에 도달하면 그 시그니처 값은 0이 된다. 이 시그니처는 이벤트 ID별로 테이블에 유지하며 주기적으로 확인한다. 만약 유입된 지 일정 시간(timeout)이 지난 이벤트의 시그니처가 0이 아니라면, 수행 실패로 간주하고 데이터 유입 지점부터 재수행 한다. 이 장애 검출 방법은 중앙에서 관리할 필요가 없는(decentralized) 방식으로 이벤트 처리가 최소 한 번은 수행됨을 보장한다. 하지만 두 번 이상도 수행될 수 있기 때문에 트랜잭션 처리는 어렵다.

state checkpointing

checkpoint란 보통 특정 시점의 상태(state)를 영구 저장하는 것을 의미한다. 데이터를 변경할 때마다 영구 저장하지 않는다면, 시점을 복구하기 위해서는 변경 시작부터 복구할 시점까지 수행한 내용을 모두 재수행(redo)해야 한다. 이때, 재수행 하는 양을 줄이기 위해 중간중간 상태를 영구 저장해 두고, 저장 시점 이후부터 재수 행해도 된다. 배치 단위의 트랜잭션 처리에서도 이런 처리가 필요하다. 배치 처리가 상태를 가진다면(stateful), 즉 이전의 배치 결과를 보고 현재 배치를 처리한다면, 시점 복구를 위해서는 상태 정보가 필요하다. 예를 들면 카운트 계산 방법으로 기존 카운트에 현재 데이터 윈도에 대한 카운트만 증가시키는 경우가 있다. 복구를 하려면 시작부터 재수행을 해야 하는데, 이때 계산할 것이 많아 리소스가 많이 필요할 수 있다. 따라서, 배치 처리를 커밋할 때 계산 상태(computational state)도 같이 저장한다. 즉, 그 시점에 각 노드별로 메모리에 적재된 데이터 상태를 HDFS 같은 곳에 영구 저장한다. 하지만 상태 정보가 많다면 효율적으로 동작하지 않을 수 있다. 이런 경우 상태 변경을 모두 로그(transaction log)로 저장했다가 수행해서 특정 상태로 되돌릴 수 있다.


출처 : https://d2.naver.com/helloworld/694050

 

# 실시간 처리(Real_time Processing)

실시간 처리 시스템은 처리할 데이터의 입력과 동시에 실시간으로 처리하여 즉시 응답해주는 데이터 처리 방식이다. 즉, 사용자가 처리하여야 할 문제를 해경할 수 있도록 해 주는 데이터 처리 방식이다. 실시간 처리 시스템의 장점으로 데이터가 발생하면 신속하게 즉시 처리가 된다. 항상 최신의 데이터를 유지할 수 있다. 그리고 데이터 처리의 전체적인 시간이 단축되어 시스템 이용자가 즉시 응답을 주고받을 수 있다. 그러나 단점으로 부수적인 통신 장비들이 요구되어 유지보수가 어렵고 시스템에 이상이 생겼을 경우 복구하기 힘들다.

  • Near_Real_Time : 초단위 수준의 지연시간 보장
  • Real_Time : 밀리세컨드 (1000분의 1초) 수준의 데이터 처리 보장
  • Real Real _Time : 마이크로 세컨드(100만분의 1초) 수준의 데이터 처리 보장

 

728x90

[기술면접] JAVA

ryudjae
|2022. 1. 24. 00:57
728x90

자바의 실행 과정

  1. 자바 소스 파일을 javac로 컴파일하여 클래스 파일을 생성함
  2. 클래스 로더가 컴파일된 자바 바이트코드를 런타임 데이터 영역으로 로드함
  3. 실행 엔진이 자바 바이트 코드를 실행함

자바의 장단점

장점

  • 자바는 자바 가상 머신에서 동작하기 때문에 OS에 독립적이다.
  • 가비지 컬렉터가 메모리를 관리해주기 때문에 편리하다.
  • 스프링과 같은 자바를 지원하는 많은 오픈소스 프로젝트가 존재해서 짧은 개발 시간 내에 안정적인 프로그램 구현이 가능하다.

 

단점

  • 자바 가상 머신에서 동작하기 때문에 실행 속도가 상대적으로 느리다.
  • 다중 상속이나 타입에 엄격한 제약이 있는 것들이 많다.

 

JVM 구조

  • 메서드 영역 :  static 변수, 전역 변수,  class 정보들 저장
  • 스택 영역 : 지역변수, 함수 등이 할당
  • 힙 영역 : new 연산자를 통한 동적 할당된 객체 저장. 가비지 컬렉션에 의해 관리됨
  • PC 레지스터 : 현재 스레드가 실행되는 부분의 주소와 명령을 저장한다.
  • Native Method Stack : 자바 외의 언어로 작성된 코드를 위한 메모리 영역이다.

pojo란 무엇인가

Plain Old Java Object. 간단히 포조라는 말 그대로 해석하며 오래된 방식의 자바 오브젝트로서 J2EE 등의 중량 프레임워크들을 사용하면서 해당 프레임워크에 종석 된 무거운 객체를 만들게 된 것에 반발하여 특정 자바 모델이나 기능, 프레임워크 등을 따르지 않는 자바 오브젝트를 지칭하는 말로 사용되었다.



Primitive type , Reference type

  • 기본형(primitive type) :  스택 메모리 영역에 실제 값을 저장하는 데이터 타입. byte, float, int, long, string, double, char, boolean // call by value(값 호출) 방식 사용
  • 참조형(reference type) : 메모리 상에 객체가 있는 위치를 저장하는 것. String, 클래스, 인터페이스, new 연산자로 정의. 실제 값은 힙 영역에 저장되고 스택 영역에는 주소만 저장됨 call by reference(주소 호출) 방식 사용

Garbage Collector

가비지 컬렉터는 더 이상 참조되지 않는 메모리를 청소해주는 JVM의 실행 엔진의 한 요소이다. JVM은 new와 같은 연산에 의해 새롭게 생성된 객체들 중에 더 이상 참조되지 않는 객체를 정리해준다. 가비지 컬렉터는 Heap 영역을 위주로 탐색하여 메모리를 정리한다.

전역 변수 , 지역변수

전역변수 :  함수 바깥에 선언하여 클래스 전체에서 사용 가능한 변수. 여러 메소드에서 공통적으로 사용가능

지역변수 :  함수 내부에서 선언하여 해당 함수 속에서만 사용 가능한 변수

static

정적 멤버 : 메모리 공간 할당 시 처음 설정된 메모리 공간이 변하지 않는 것

객체를 생성하지 않고도 사용할 수 있는 필드와 메서드. 객체마다 가지고 있을 필요가 없는 공용적인 데이터라면 static으로 선언

 

String, StringBuilder, StringBuffer

  • String은 new 연산자를 통해 생성하게 되면 메모리 공간이 절대 변하지 않으므로 연산 시 메모리의 값이 변하는 것이 아니라 새로운 String인스턴스가 생성된다. 이러한 상황이 발생하면 가비지 컬렉터에 의해 제거되야하고 연산이 많아지면 성능이 저하된다.
  • StringBuilder, StringBuffer는 새로운 인스턴스를 생성하는 것이 아닌 메모리의 값을 변경하므로 문자열 연산이 자주 있을 때 사용하면 좋다.
  • StringBuffer는 멀티 스레드 환경에서 동기화가 가능하다. 그러나 StringBuilder는 동기화를 지원하지 않기 때문에 멀티 스레드 환경에서 적합하지 않다.

접근 제한자

  • public : 모든 클래스 접근 가능
  • protected : 같은 패키지, 해당 클래스를 상속받은 외부 패키지의 클래스 접근 가능
  • private : 같은 클래스에서만 접근 가능
  • default : 같은 패키지에서만 접근 가능

클래스/ 인스턴스

  • 클래스 : 객체를 만들어내기 위한 설계도 혹은 툴
  • 인스턴스 : 객체에 메모리가 할당되어 실제로 활용되는 실체
  • 객체 : 클래스를 기반으로 선언된 대상
  • + wapper class : 기본 타입에 해당하는 데이터를 객체로 포장해 주는 클래스를 래퍼 클래스(Wrapper class)라고 한다.

상속

  • 부모 클래스가 가지고 있는 상수, 메서드를 자식 클래스에서 물려 받아 같이 공유하면서 확장하는 것
  • 자식 클래스의 부모클래스 메서드 재정의

캡슐화

  • 객체의 필드(속성), 메소드를 하나로 묶고, 실제 구현 내용을 외부에 감추는 것을 말한다.
  • 외부 객체는 객체 내부의 구조를 얻지 못하며 객체가 노출해서 제공하는 필드와 메소드만 이용할 수 있다.

다형성

하나의 객체 여러 가지 타입을 가질 수 있는 것을 의미한다. 자바에서는 다형성을 부모 클래스 타입의 참조변수로 자식 클래스 타입의 인스턴스를 참조할 수 있도록 구현.

추상 클래스와 인터페이스

  • 추상클래스 
    • 추상 메서드를 하나 이상 가진 클래스
    • 직접적으로 객체 생성이 불가능하고 클래스를 상속받아 오버 라이딩을 하여 사용해야 함
    • 추상 메서드와 일반 메서드 모두 선언 가능
  • 인터페이스
    • 모든 메서드가 구현부가 없는 추상 메서드로 이루어진 클래스
    • 다중 구현이 가능하다.
    • 상수만 선언할 수 있다.

오버 로딩과 오버 라이딩

  • 오버 라이딩 : 상위 클래스가 가지고 있는 메서드를 하위 클래스에서 재정의하여 사용하는 기술
  • 오버 로딩 : 매개변수 타입과 개수를 변경하면서 같은 이름의 메서드를 여러 개 사용하는 기술

Generic(제너릭)

클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법

객체 타입을 컴파일 시에 확인하고 형 변환을 하지 않아도 되기 때문에 코드의 안정성과 재사용성을 높여준다.

Stream API

  • stream API는 자바 8부터 추가된 기능으로 컬랙션, 배열등의 저장 요소를 하나씩 참조하며 함수형 인터페이스를 적용하며 반복적으로 처리할 수 있도록 해주는 기능이다.
  • 스트림을 사용하면 코드를 간결하게 작성하여 가독성을 높일 수 있다.
  • 그러나 잘못 사용하면 기존의 자바 방식보다 오히려 성능이 떨어질 수 있다.

JAVA Collection

  • Set : 순서를 유지하지 않는 데이터의 집합으로 중복을 허용하지 않는다.
    • HashSet : 가장 빠른 임의 접근 속도, 순서 예측불가
    • TreeSet : 정렬방법 지정 가능
  • Map : Key-Value의 쌍으로 이루어진 데이터 집합으로 순서가 유지되지 않으며 값의 중복은 value만 허용한다. 
    • HashMap : 중복이 안되고 순서가 없다. null값 가능
    • Hashtable : HashMap보다 느리지만 동기화 지원. null불가
    • TreeMap : 정렬된 순서대로 key-value를 저장해서 검색이 빠름
  • List : 순서가 있는 데이터의 집합으로 데이터의 중복을 허용한다. 
    • ArrayList : 단방향 포인터 구조로 각 데이터마다 인덱스를 가지고 있어 조회 성능이 뛰어남
    • LinkedList :  양방향 포인터 구조로 삽입, 삭제가 빈번할 경우 위치 정보만 수정하면 되기 때문에 유용하다.
    • Vector : 내부에서 자동으로 동기화 처리가 일어나 비교적으로 성능이 좋지 않고 무거움

 

Synchronized

자바에서 지원하는 synchronized 키워드는 여러 스레드가 하나의 자원을 이용하고자 할 때, 한 스레드가 해당 자원을 사용 중인 경우, 데이터에 접근하지 못하도록 막는 키워드이다.

  • 메서드 Synchronized :  한 시점에 하나의 스레드만이 해당 메서드를 실행할 수 있다.
  • 변수 Synchronized : 한 시점에 하나의 스레드 만이 해당 변수를 참조할 수 있다.

싱글톤

  • 하나의 클래스에 대해 하나의 인스턴스만 만들어서 사용하기 위한 패턴이다.
  • 해당 인스턴스가 정대적으로 1개만 존재한다는 것을 보증하고 싶은 경우나 동일한 인스턴스를 자주 생성해주어야 하는 경우 사용한다.
  • 하지만 이러한 싱글톤 패턴은 객체 지향 설계의 원칙에 적합하지 않으며, LifeCycle 제어가 힘들고, 멀티스레드 환경에서 여러 개의 객체가 생성되는 문제가 발생할 수 있습니다. 그러한 이유로 멀티스레드 환경이라면 static 앞에 synchronized 키워드를 붙여 동기화 작업을 추가해주어야 합니다.

더보기

Thread-safe 멀티 스레드 환경에서 동작해도 원래 의도한 형태로 동작하는 코드

직렬화

객체를 스트림을 통해 입출력하려면 바이트 배열로 변환하는 것이 필요한데, 이를 '직렬화'라고 합니다. 반대로 스트림을 통해 받은 직렬화된 객체를 원래 모양으로 만드는 과정을 역직렬화라고 합니다.

Servlet , JSP

  • Servlet : 자바 언어로 웹 개발을 위해 만들어진 것으로, 컨테이너가 이해할 수 있게 구성된 순수 자바 코드로만 이루어진 것이다.
  • JSP : html 기반에 자바 코드를 블록화 하여 삽입한 것으로 Servlet을 좀 더 쉽게 접근할 수 있도록 만들어진 것이다.

JDBC

JDBC는 자바에서 DB의 종류에 상관없이 데이터 베이스에 더욱 쉽게 접근할 수 있도록 하는 API

OOP(객체 지향 프로그래밍)

현실 세계를 프로그래밍으로 옮겨와 현실세계의 사물들을 객체로 보고, 그 객체로부터 개발하고자 하는 특징과 기능을 뽑아와 프로그래밍하는 기법이다.

 

OOP 장점

  • 유지보수가 용이하다.
  • 캡슐화, 상속 , 다형성 등과 같은 기법을 이용할 수 있다.

OOP의 5가지 설계 원칙

  • SRP(Single Responsibility Principle, 단일 책임원칙) : 클래스는 단 하나의 목적을 가져야 한다.
  • ISP(Interface Segregation Principle, 인터페이스 분리 원칙) :  클라이언트는 이용하지 않는 메서드에 의존하지 않도록 인터페이스를 분리하여야 한다.
  • LSP(Liskov Substitution Principle, 리스 코프 치환 원칙) :  상위 타입 객체를 하위 타입으로 바꿔도 프로그램은 일관되게 동작해야 한다.
  • OCP(Open-Close Principle, 개방 폐쇄 원칙) : 클래스 확장에는 열려있고, 변경에는 닫혀 있어야 한다.
  • DIP(Dependency Inversion Principle, 의존 역전 법칙) : 클라이언트는 추상화에 의존해야 하며, 구체화에 의존해선 안된다.

 

728x90
728x90

알고리즘

알고리즘은 어떠한 문제를 해결하기 위한 여러 동작들의 모임을 의미한다.

 

버블 소트(bubble sort)

  • 버블 소트는 서로 인접한 두 원소를 비교하여 정렬하는 알고리즘이다.(시간 복잡도 O(n^2))

 

힙 소트(heap sort)

  • 힙 소트는 주어진 데이터를 힙 자료구조로 만들어 최댓값 또는 최솟값부터 하나씩 꺼내서 정렬하는 알고리즘이다.(시간 복잡도 O(nlog2 n))

 

머지 소트(merge sort)

  • 머지 소트는 주어진 배열을 크기가 1인 배열로 분할하고 합병하면서 정렬을 진행하는 분할/정복 알고리즘이다.

 

퀵 소트(Quick sort)

  • 퀵 소트는 매우 빠른 정렬 속도를 가진 분할 정복 알고리즘 중 하나로 합병 정렬과 달리 리스트를 비 균등하게 분할한다.
  • 피봇을 설정하고 피봇보다 큰 값과 작은 값으로 분할하여 정렬을 한다.

 

삽입 소트(insertion sort)

  • 삽입 정렬은 두 번째 값부터 시작하여 그 앞에 존재하는 원소들과 비교하여 삽입할 위치를 찾아 삽입하는 정렬 알고리즘이다.
  • 삽입 정렬의 평균 시간 복잡도는 O(n^2)이고, 가장 빠른 경우 O(n)까지 높아질 수 있다.

 

동적 프로그래밍(Dynamic Programming)

동적 프로그래밍은 주어진 문제를 풀기 위해서, 문제를 여러 개의 하위 문제로 나누어 푼 다음, 그것을 결합하여 해결하는 방식이다. 동적 프로그래밍에서는 어떤 부분 문제가 다른 문제를 해결하는 데 사용될 수 있어, 답을 여러 번 계산하는 대신 한 번만 계산하고 그 결과를 재활용하는 메모제이션 기법으로 속도를 향상할 수 있다.

 

동적 프로그래밍의 두 가지 조건

  • Overlapping Subproblem(중복되는 부분 문제) : 주어진 문제는 같은 부분 문제가 여러 번 재사용된다.
  • Optimal Substructure(최적 부분 구조): 새로운 부분 문제의 정답을 다른 부분 문제의 정답으로부터 구할 수 있다.

 

재귀 알고리즘

재귀 알고리즘은 함수 내부에서 함수가 자기 자신을 또다시 호출하여 문제를 해결하는 알고리즘이다. 재귀 알고리즘은 자기가 계속해서 자신을 호출하므로 반복을 중단할 조건이 필요하다.

 

private static int recursiveFactorial(int num) { 
	if(num > 1) { 
    	return recursiveFactorial(num - 1) * num; 
      }
     return 1; 
 } 
     
private static int loopFactorial(int num) { 
     	int answer = 1; 
        for (int i = 2; i <= num; i++) {
        	answer *= i; 
        } 
       return answer;
 }

자료구조 

자료구조는 데이터를 원하는 규칙 또는 목적에 맞게 저장하기 위한 구조이다.

 

  1. Stack
    • 세로로 된 바구니와 같은 구조로 먼저 넣은 값이 마지막으로 나오는 FILO(First In Last Out) 구조이다.
  2. Queue
    • 가로로 된 통과 같은 구조로 먼저 넣은 값이 가장 먼저 나오는 FIFO(First In First Out) 구조이다.
  3. Heap
    • 최댓값 또는 최솟값을 찾아내는 연산을 쉽게 하기 위해 고안된 구조로, 각 노드의 키 값이 자식의 키 값보다 작지 않거나 그 자식의 키 값보다 크지 않은 완전 이진트리이다.
  4. Tree
    • 정점과 간선을 이용해 사이클을 이루지 않도록 구성한 그래프의 특수한 형태로, 계층이 있는 데이터를 표현하기에 적합하다.

우선순위 큐와 내부 구조 및 시간 복잡도

  • 우선순위 큐는 가장 우선순위가 높은 데이터를 먼저 꺼내기 위해 고안된 자료구조이다. 우선순위 큐를 구현하기 위해서는 일반적으로 힙을 사용한다.
  • 힙은 완전 이진트리를 통해서 구현되었기 때문에 우선순위 큐의 시간 복잡도는 O(logn)이다.

해시 테이블과 해시 테이블의 시간 복잡도

  • 해시 테이블은 key-value 형태로 데이터를 저장하는 자료구조 중 하나로 빠른 데이터 검색이 필요할 때 유용하다.
  • 해시 테이블은 Key값에 해시 함수를 적용해 고유한 index를 생성하여 그 index에 저장된 값을 꺼내오는 구조이다.
  • 해시 테이블은 고유한 인덱스 값을 조회하기 때문에 평균적으로 O(1)의 시간 복잡도를 갖는다. 다만, 충돌이 발생한 경우 충돌된 인덱스 값에 대해 연결된 데이터를 조회하여 원하는 값을 조회하기 때문에 O(N)까지 증가할 수 있다.

LinkedList와 ArrayList

ArrayList는 데이터들이 순서대로 늘어선 배열의 형식을 취하고 있지만, LinkedList는 자료의 주소 값으로 서로 연결된 형식을 가지고 있다.

  • ArrayList
    • 원하는 데이터에 무작위로 접근할 수 있다.
    • 리스트의 크기가 제한되어 있으며, 리스트의 크기를 재조정하는 것은 많은 연산이 필요하다.
    • 데이터 추가/삭제를 위해서는 임시 배열을 생성하고 복제하고 있어 시간이 오래 걸린다.
  • LinkedList
    • 리스트의 크기에 영향 없이 데이터를 추가할 수 있다.
    • 데이터를 추가하기 위해 새로운 노드를 생성하여 연결하므로 추가/삭제 연산이 빠르다.
    • 무작위 접근이 불가능하고 , 순차 접근만 가능하다.

 


Reference

https://mangkyu.tistory.com/90

728x90

'Dev' 카테고리의 다른 글

빅데이터 처리  (0) 2022.02.11
[기술면접] JAVA  (0) 2022.01.24
[기술면접] SpringFramework  (0) 2022.01.23
[기술면접]운영체제(Operating System)  (0) 2022.01.21
[기술면접]데이터베이스(Database)  (0) 2022.01.12