기술 면접 대비 ver_5 (20210905)

최진민·2021년 7월 13일
0
post-thumbnail

JAVA & OOP


JAVA

  • 객체 지향 프로그래밍 언어

  • 특징

    • 자바 가상 머신(JVM)을 설치하면 운영체제의 상관없이 작동(운영체제에 독립적)
    • 기본 자료형(Primitive Type)을 제외한 모든 요소들이 객체로 표현
    • 객체 지향(OOP)의 특징들이 잘 적용된 언어
    • Garbage Collector를 통한 자동적 메모리 관리
    • Multi-Thread
  • 클래스, 객체, 인스턴스

    /* 클래스 */
    public class Animal {
      ...
    }
    /* 객체와 인스턴스 */
    public class Main {
      public static void main(String[] args) {
        Animal cat, dog; // '객체'
    
        // 인스턴스화
        cat = new Animal(); // cat은 Animal 클래스의 '인스턴스'(객체를 메모리에 할당)
        dog = new Animal(); // dog은 Animal 클래스의 '인스턴스'(객체를 메모리에 할당)
      }
    }
    • 클래스 : 세계
    • 객체 : 세계의 대상
    • 인스턴스 : 대상을 실체화
    • 클래스 타입으로 선언 ⇒ 객체
    • 객체를 실제 메모리에 담아 사용한다 ⇒ 인스턴스

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

  • Object-Oriented Programming

  • 데이터를 객체로 취급하여 프로그램에 반영

  • 절자 지향 프로그래밍과는 다르게 객체들의 상호작용을 통해 프로그램이 동작

  • 장점

    • 소프트웨어 생산성 향상
      • 코드의 재사용성
      • 디버깅
    • 실세계의 쉬운 모델링
    • 보안성
      • 캡슐화, 다형성 등
  • 💖특징

    • 1) 추상화

      • 객체들의 공통적인 특징(속성, 기능)을 도출
      • 객체 지향 관점에서는 클래스를 정의하는 것 = 추상화 (클래스가 없는 객체 지향 언어 ex) JavaScript)
    • 2) 캡슐화

      • 실제 구현되는 부분을 외부에 드러내지 않도록 은닉
      • 객체가 독립적으로 역할을 하도록 데이터 + 기능을 한 데 묶어 관리
    • 3) 상속

      • 하나의 클래스가 가진 특징(메서드, 데이터)을 다른 클래스가 물려받는 것
      • 이미 작성된 클래스를 받아 새로운 클래스 작성
    • 4) 다형성

      • 동작 방식이 다르고 이름이 같은 메서드를 호출

      • 동일한 명령의 해석을 연결된 객체에 의존

      • 오버라이딩: 부모 클래스의 메서드와 같은 이름, 매개변수를 갖고 내용은 다르도록 자식 클래스에서 메서드를 재정의하는 것.

        public class Main {
            public static void main(String[] args){
                Child c = new Child();
        
                c.print(20);
            }
            static class Parent {
                int a = 10;
        
                void print(int x){
                    System.out.println(this.a + x);
                }
            }
            static class Child extends Parent {
                int a = 10;
        
                @Override
                void print(int x){
                    System.out.println(x + x);
                }
            }
        }
        
        //40
      • 오버로딩: 한 클래스 내에서 이름만 같고 매개변수의 타입과 수를 다르게 하여 메서드를 정의하는 것.

        public class Main {
            public static void main(String[] args){
                A a = new A();
        
                a.print(10);
                a.print(10, 20);
            }
            static class A {
                int a = 10;
        
                void print(int x){
                    System.out.println(this.a + x);
                }
        
                void print(int x, int y){
                    System.out.println(this.a + x + y);
                }
            }
        }
        
        //20
        //40
    • 5) 동적 바인딩

      • 가상 함수를 호출하는 코드를 컴파일 시, 바인딩을 실행시간에 결정
      • 파생 클래스의 객체에 대해, 기본 클래스의 포인터로 가상 함수가 호출될 때 발생
      • 함수 호출 시, 동적 바인딩을 통해 파생 클래스에 오버라이드된 함수 실행
      • 프로그래밍의 유연성을 높혀주고, 자식 클래스에서 재정의된 함수 보장

Interface vs Abstract

  • Interface

    • 일종의 추상 클래스
    • 추상 메서드상수만을 멤버로 갖는다.
    • 상속 관계가 없는 클래스간 서로 공통되는 로직 구현
    • extends는 하나의 클래스 상속, implements다중 상속
  • Abstract

    • 추상 메서드를 하나 이상 가진 클래스
    • 자신의 생성자로 객체 생성 불가능
    • 자식 클래스를 참조하여 부모클래스의 객체 생성
    • 자식 클래스 제어
  • 공통점

    • new연산자로 인스턴스 생성 불가능
    • 프로토 타입만 있는 메서드를 갖는다.
    • 사용하려면 하위 클래스에서 확장/구현 해야 한다.
  • 차이점

    • 사용하는 키워드가 다르다.
    • Abstract는 일반 메서드 사용 가능, Interface는 메서드 선언만 가능
    • Interface만이 다중상속 가능
  • 예제

    public class Main {
        public static void main(String[] args) {
            String str = "str";
    
            C c = new C();
    
            System.out.println(c.getStrInterface(str));
            System.out.println(c.getStrAbstract(str));
        }
    }
    
    interface A {
        String getStrInterface(String strA);
    }
    
    abstract class B {
        String getStrAbstract(String strB){
            return strB;
        }
    }
    
    class C extends B implements A {
        String c = "c";
    
        @Override
        public String getStrInterface(String strA) {
            return c + strA;
        }
    
        @Override
        String getStrAbstract(String strB) {
            return super.getStrAbstract(strB);
        }
    }
    
    //cstr
    //str
    • 💥특히, C 클래스에서 A인터페이스에 선언한 메서드를 정의하지 않으면 오류가 난다.
    • B 는 정의하지 않아도 된다. 재정의하여 다른 내용으로 변경하고 싶을 때 메서드 오버라이딩(다형성)!

Call by Reference vs Call by Value

  • Call by Reference
    • 매개 변수의 원래 주소 값을 저장
    • 클래스 객체를 인수로 전달한 경우
    • ex) ==
  • Call by Value
    • 기본 데이터형을 주로 사용
    • 주어진 값을 복사하여 사용
    • 메서드 내 처리 결과는 메서드 밖에 영향을 미치지 못한다.
    • ex) equals()

Static

  • 클래스가 로딩될 때, 메모리 공간을 할당하는데 처음 설정된 메모리 공간이 변하지 않음을 의미

  • 객체를 아무리 만들어도 해당 변수는 하나만 존재 (객체와 무관한 키워드)

  • 🧨Static vs Instance

    • Static Method

      • 메소드 내에서 인스턴스 변수를 사용하지 않는다.

      • 객체를 생성하지 않고 호출

        public class Main {
            static int add(int x, int y) {
                return x + y;
            }
        
            public static void main(String []args) {
                System.out.println(add(1, 2));
            }
        }
    • Instance Method

      • 객체 생성 후 사용 가능

        class Pos {
            int x;
            int y;
        
            public Pos(int x, int y) {
                this.x = x;
                this.y = y;
            }
        
            public int add(int x, int y){
                return x + y;
            }
        }
        
        public class Main {
            public static void main(String[] args) {
                Pos p = new Pos(1, 2);
                System.out.println(p.add(p.x, p.y);
            }
        }

Garbage Collection

  • 시스템에서 더이상 사용하지 않는 동적 할당된 메모리 블럭을 찾아 자동으로 다시 사용 가능한 자원으로 회수
  • 가비지 컬렉션을 수행하는 부분 = 가비지 컬렉터

Primitive Type vs Reference Type

  • Primitive Type
    • 변수에 값 자체를 저장
    • 정수형 : byte, short, int, long
    • 실수형 : float, double
    • 문자형 : char
    • 논리형 : boolean
    • .🔔Wrapper Class로 변경 가능
      • Wrapper Class : 간단한 데이터를 객체로 만들어야 될 때 지원하는 클래스
      • intInteger
      • charCharacter
      • 그 외는 첫글자의 소문자를 대문자로 (floatFloat 등)
  • Reference Type
    • 메모리상에 객체가 있는 위치 저장
    • Class, Array, Interface 등

접근 제한자

  • public : 접근 제한이 없다. (같은 프로젝트 내 어디서든 접근 가능)
  • protected : 같은 패키지 내, 다른 패키지에서 상속받아 자식 클래스에서 접근 가능
  • defalut : 같은 패키지 내 접근 가능
  • private : 같은 클래스 내 접근 가능
  • 🧨사용 이유
    • 정보의 은닉화, 즉, 클라이언트 입장에서 접근할 수 있는 클래스나 메서드를 숨길 수 있다.

Thread in JAVA

Synchronized, Runnable

  • synchronized

    • 여러 쓰레드가 한 개의 자원을 사용하고자 할 때, 현재 데이터를 사용하고 있는 쓰레드를 제외하고 다른 쓰레드가 데이터에 접근할 수 없도록 한다.
    • 장점
      • Thread간 동기화를 통해 datathread-safe 보존
      • 데이터의 안정성과 신뢰성 보장
    • 단점
      • 남발하면 프로그램 성능 저하를 일으킬 수 있다.
  • Runnable : Java의 Thread 구현 인터페이스

    • 메소드 : run()
  • 💥동기화하지 않은 예제

    public class Test {
        public static void main(String[] args) throws InterruptedException {
            Task task = new Task();
    
            Thread t1 = new Thread(task);
            Thread t2 = new Thread(task);
    
            t1.setName("t1");
            t2.setName("t2");
    
            t1.start();
            t2.start();
        }
    }
    
    class Task implements Runnable {
        Account acc = new Account();
    
        @Override
        public void run() {
            while (acc.current > 0) {
                // 100, 200, 300 중의 한 값을 임의로 선택해서 출금(withDraw)한다.
                int money = (int) (Math.random() * 3 + 1) * 100;
                acc.withDraw(money);
            }
        }
    }
    
    class Account {
        int current = 1_000;
    
        public void withDraw(int money) {
            if (current >= money) {
                try {
                    Thread thread = Thread.currentThread();
    
                    System.out.println(thread.getName() + "의 출금 금액 ->> " + money);
    
                    Thread.sleep(1000);
    
                    current -= money;
    
                    System.out.println(thread.getName() + "의 현재 금액: " + current);
    
                } catch (Exception e) {
                }
            }
        }
    }
    t2의 출금 금액 ->> 300
    t1의 출금 금액 ->> 300
    t1의 현재 금액: 700
    t1의 출금 금액 ->> 100
    t2의 현재 금액: 400
    t2의 출금 금액 ->> 100
    t2의 현재 금액: 300
    t2의 출금 금액 ->> 200
    t1의 현재 금액: 200
    t1의 출금 금액 ->> 200
    t1의 현재 금액: 0
    t2의 현재 금액: -200
  • 💖동기화 예제

    class Account {
        int current = 1_000;
    
        public synchronized void withDraw(int money) { //변경
            /.../
        }
    }
    t1의 출금 금액 ->> 300
    t1의 현재 금액: 700
    t2의 출금 금액 ->> 200
    t2의 현재 금액: 500
    t1의 출금 금액 ->> 200
    t1의 현재 금액: 300
    t2의 출금 금액 ->> 300
    t2의 현재 금액: 0
  • 네 가지 유형의 synchronized

    • 1) 인스턴스 메소드 동기화

      public synchronized void add(int num){
          this.count += num;
      }
      • 인스턴스 당 한 쓰레드
    • 2) Static 메소드 동기화

      public static synchronized void add(int num){
          this.count += num;
      }
      • 클래스(쓰레드가 어떤 Static 메서드를 실행했든 말든)당 한 쓰레드
    • 3-1) 인스턴스 메소드 안의 동기화 블록

      public void add(int num){
          synchronized(this){
              this.count += num;
          }
      }
      • 동기화 블록 안에 전달된 객체 = 모니터 객체
      • 같은 모니터 객체를 기준으로 동기화된 블록 안의 코드를 오직 한 쓰레드만이 실행
    • 3-2) 두 개의 동기화된 블록

      public class MyClass {
      
          public synchronized void log1(String msg1, String msg2){
             log.writeln(msg1);
             log.writeln(msg2);
          }
      
          public void log2(String msg1, String msg2){
             synchronized(this){
                log.writeln(msg1);
                log.writeln(msg2);
             }
          }
      }
      • 한 쓰레드는 한 시점에 두 동기화된 코드 중 하나만 실행 가능
      • log2()this대신 다른 객체를 전달한다면 한 시점에 각 메서드 실행 가능
    • 4) Static 메소드 안의 동기화 블록

      public class MyClass {
      
          public static synchronized void log1(String msg1, String msg2){
             log.writeln(msg1);
             log.writeln(msg2);
          }
      
          public static void log2(String msg1, String msg2){
             synchronized(MyClass.class){
                log.writeln(msg1);
                log.writeln(msg2);  
             }
          }
      }
      • 한 시점에 오직 한 쓰레드만 두 개의 메소드 실행 가능

Serializable, transient, volatile

  • 자바 직렬화 (Serializaion)

    • 사용 이유

      • 각 주소값이 가지는 데이터들을 Value Type 데이터로 변환해준다. 즉, 데이터를 저장, 통신전에 '데이터 직렬화(Serialization)' 작업이 필요
    • 🧨정의

      • 메모리를 디스크에 저장하거나 네트워크 통신에 사용하기 위한 형식으로 변환하는 것을 말한다.
      • 내부의 객체(또는 데이터)를 외부에서도 사용할 수 있도록 byte형태로 변환
      • 역직렬화 (Deserialization) : byte형태를 객체로 변환
      • 시스템 측면 : JVM의 메모리(스택 or 힙)에 상주한 객체(또는 데이터)를 바이트 형태로 변환
    • 특징

      • Object 객체는 최상위 객체기 때문에 직렬화가 불가능

      • 부모 클래스에서 직렬화를 상속받으면 자식 클래스도 자동 직렬화

        public class SuperUserInfo implements Serializable {
            String name;
            String password;
        }
        
        public class UserInfo extends SuperUserInfo {
            int age;
        }
      • 다만, 아래와 같이 부모 클래스가 직렬화를 구현하지 않는다면 부모 클래스의 데이터(name, password)는 직렬화 대상에서 제외된다.

        public class SuperUserInfo {
            String name;
            String password;
        }
        
        public class UserInfo extends SuperUserInfo implements Serializable {
            int age;
        }
  • transient

    • transient가 선언된 데이터(변수)는 Serializable 대상에서 제외된다.
    • 사용 이유
      • 보안상 중요한 변수나 꼭 저장되지 않아도 될 변수에 대해 사용
  • volatile

    • JAVA 변수를 Main Memory에 저장(특히, 읽거나 쓸 때)

    • 변수를 읽어들일 때마다, CPU cache가 아닌 M.M에서 읽어들인다.

    • 🧨사용 이유

      • 멀티 쓰레드 환경에서 Thread가 변수를 읽어올 때, 각각 cache에 담긴 값이 다르기 때문에 변수값 불일치가 발생하는데 이를 해결하기 위함
      • 다시 말해, 멀티 쓰레드 환경에서 하나의 Threadread & write 하고 나머지 Threadread하는 상황에서 최신의 값을 보장
      • 여러 쓰레드가 동시에 write하는 경우에는 synchronized를 통해 동기화하여 원자성을 보장

테스트 코드의 중요성

  • 기능 추가에 대해 유연한 대처 (시간 절약)
  • 좋은 테스트 코드는 그 자체로 문서

JVM

자바, JVM, JDK, JRE

  • 목표 : 무엇인지, 어떤 점이 다른지 이해한다.

  • ⭕JVM (Java Virtual Machine)
    • 자바 바이트 코드(.class)를 어떻게 실행할지에 대한 표준 스펙 (⇒ OS에 특화된 코드로 변환(인터프리터, JIT 컴파일러)하여 실행)
    • JVM 벤더 : 오라클, 아마존, Azul...
    • ❗특정 플랫폼에 종속적
  • ⭕JRE (Java Runtime Environment)
    • 자바 App.을 실행할 수 있도록 구성된 배포판
    • JVM + Library (자바 런타임 환경에서 사용하는 프로퍼티 세팅이나 리소스 파일도 포함)
    • 개발 관련 도구는 포함하지 않는다.
  • ⭕JDK (Java Development Kit)
    • JRE + 개발 툴
    • 자바 11부터는 JDK만 제공, JRE는 제공하지 않는다.
    • 소스코드를 작성할 때, 사용하는 자바 언어는 플랫폼에 독립적
  • ⭕Java
    • 프로그래밍 언어
    • JDK에 들어있는 javac(자바 컴파일러)를 사용하여 바이트코드(.class) 컴파일
    • 자바 유료화? 오라클에서 만든 Oracle JDK 11 버전부터 상용으로 사용할 때 유료.
  • ⭕JVM 언어
    • 자바와의 의존성이 타이트하지는 않다. ⇒ 다른 프로그래밍 언어로도 동작한다.
      • ex) 클로저, 그루비, JRuby, Jython, Kotlin, Scala, ...
  • 참고

JVM 구조

  • 클래스 로더 시스템

    • .class에서 바이트 코드를 읽고 메모리에 저장
    • 로딩 : 클래스를 읽어드림
    • 링크 : 레퍼런스를 연결
    • 초기화 : static 값들 초기화 및 변수에 할당
  • 메모리

    • 1) 메소드 영역 : 클래스 레벨의 정보(클래스 이름, 부모 클래스 이름, 메소드, 변수) 저장. 공유 자원.

      • 아무것도 상속받지 않은 클래스 같이 보이더라도 상위 클래스가 있다.

        package me.jinmin;
        
        public class App {
            public static void main(String[] args) {
                System.out.println(App.class.getSuperclass());
            }
        }
        print:
        class java.lang.Object
    • 2) 힙 영역 : 객체(instance)를 저장. 공유 자원.

    • 3) 쓰레드 영역

      • 스택 영역 : 쓰레드마다 런타임 스택을 형성하고 그 안에 스택 프레임(=메소드 콜)을 쌓는다.

      • PC(Program Counter) register : 쓰레드마다 현재 실행할 스택 프레임을 가리키는 포인터

      • 네이티브 메소드 스택 : https://javapapers.com/core-java/java-jvm-run-time-data-areas/#ProgramCounter_PC
        Register

        • 네이티브 메소드❓ : 메소드에 네이티브 키워드가 붙어있고 구현을 Java가 아닌 C, C++로 한 것.

          @HotSpotIntrinsicCandidate
          public static native Thread currentThread();
  • 실행 엔진

    • 인터프리터 : 바이트코드를 한 줄 씩 실행(이해)
    • JIT (Just in Time) 컴파일러 : 반복적인 바이트 코드를 발견하면 JIT 컴파일러로 반복 코드를 네이티브 코드로 바꿔둔다. 그 후 인터프리터는 네이티브 코드로 컴파일된 코드를 바로 사용 (⇒ 실행 속도 향상)
    • GC(Garbage Collector) : 더이상 참조되지 않는 객체를 모아 정리 (⇒ 메모리 효율)
      • (1) Throughput
      • (2) stop-the-world
  • 네이티브 메소드 인터페이스 (JNI)

    • 자바 애플리케이션에서 C, C++, 어셈블리로 작성된 함수를 사용할 수 있는 방법 제공
    • Native 키워드를 사용한 메소드 호출
  • 네이티브 메소드 라이브러리

    • C, C++로 작성된 라이브러리
    • 항상, JNI를 통해서 사용해야 한다.

클래스 로더

  • 로딩, 링크, 초기화 순

  • 로딩

    • 클래스 로더가 .class 파일을 읽고 내용에 따라 적절한 바이너리 데이터를 만들고 메소드영역에 저장

    • 메소드 영역에 저장하는 데이터

      • FQCN (Fully Qualified Class Name) : 패키지 이름, 클래스 이름, 클래스 로더까지
      • 클래스 | 인터페이스 | 이늄(class | interface | enum)
      • 메소드 & 변수
    • 로딩이 끝나면 해당 클래스 타입의 Class 객체를 생성해서 영역에 저장.

      package me.jinmin;
      
      public class App {
          public static void main(String[] args) {
              Class<App> appClass; //로딩이 끝나면 만들어지는 요거.!!!
          }
      }
  • 링크

    • Verify, Prepare, Resolve(optional)의 3단계로 형성
    • Verify : .class가 유효한지 검증
    • Prepare : 메모리를 준비하는 과정, 클래스 변수(static 변수)와 기본값에 필요한 메모리
    • Resolve(optional) : 심볼릭 메모리의 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체
  • 초기화

    • Static 변수의 값을 할당 (static 블럭이 있으면 이 때 실행)
  • ❤클래스 로더는 계층 구조, 기본적인 3개의 클래스 로더로 이루어져 있다.

    • Bootstrap 클래스 로더 : JAVA_HOME\lib에 있는 코어 자바 API 제공. 최상위 우선순위

    • Platform 클래스 로더 : JAVA_HOME\lib\ext 폴더 또는 java.ext.dirs 시스템 변수에 해당하는 클래스를 읽음.

    • Application 클래스 로더 : 애플리케이션 클래스 경로(-classpath 옵션 or java.class.path 환경 변수의 값에 해당하는 위치)에서 클래스를 읽음.

      package me.jinmin;
      
      public class App {
        public static void main( String[] args ) {
          ClassLoader classLoader = App.class.getClassLoader();
          System.out.println(classLoader);
          System.out.println(classLoader.getParent());
          System.out.println(classLoader.getParent().getParent());
        }
      }
      print:
      jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc
      jdk.internal.loader.ClassLoaders$PlatformClassLoader@43a25848
      null //native여서 참조 불가

OS


Thread

  • Thread : 프로세스 내에서 실행되는 독립적인 실행 단위
  • Process : 운영체제에서 실행중인 작업 단위 (하나 이상의 Thread 포함)
  • Thread 장점
    • 빠른 프로세스 생성
    • 적은 메모리
    • 쉬운 정보 공유
  • 💥교착상태 (Deadlock) (참고 : https://chanhuiseok.github.io/posts/cs-2/)
    • 교착 상태 발생을 위한 필요 충분 조건 4가지
      • 1) 상호 배제 (Mutual Exclusion) : 한 번에 한 개의 프로세스만이 공유 자원을 사용할 수 있다.
      • 2) 점유와 대기 (Hold and Wait) : 자원을 최소 하나 보유하고 다른 프로세스에 할당된 자원을 점유하기 위해서 대기하는 프로세스 존재
      • 3) 비선점 (No-preemption) : 이미 할당된 자원을 강제로 뺏을 수 없다.
      • 4) 환형 대기 (Circular Wait) : 대기 프로세스의 집합이 순환 형태로 자원을 할당받기를 대기
    • 교착 상태 해결법
      • 예방 : 필요 충분 조건 4가지 중 하나라도 발생하지 않게 예방
      • 회피 : 은행원 알고리즘
      • 탐지 + 회복

Multi-Thread vs Multi-Process

  • Multi-Thread
    • 장점
      • 적은 메모리 공간
      • 문맥 교환이 빠르다.
    • 단점
      • 동기화 문제 (하나의 쓰레드 장애 → 전체 쓰레드 장애)
  • Multi-Process
    • 장점
      • 안정성 (하나의 프로세스가 죽더라도 다른 프로세스에 영향을 미치지 않는다.)
    • 단점
      • 많은 메모리 공간
      • CPU 시간 차지
  • 멀티 쓰레드를 사용하는 이유
    • 스레드를 활용하여 자원의 효율성을 증가시킨다.
    • 다만, 개발자가 동기화문제를 잘 고려해야한다.

Data Structure


Stack, Queue

  • Stack
    • LIFO (Last In First Out : 후입선출) 구조
  • Queue
    • FIFO (First In First Out : 선입선출) 구조

클라우드 컴퓨팅

  • 인터넷을 통해 서버, 스토리지, 소프트 웨어 등 필요한 IT 자원을 받아 사용하는 것

  • 서비스 형식

    • IaaS (Infrastructure as a Service) : IT 인프라(서버, 데이터 스토리지, 데이터베이스, 네트워크, 운영체제 등) 제공

    • PaaS (Platform as a Service) : 소프트웨어 애플리케이션을 위한 환경 제공 (웹 앱, 모바일 앱 등)

    • 서버리스 : PaaS, 앱 기능 빌드에 초점, 특정 함수나 트리거가 발생할 때만 리소스 활용

    • SaaS (Software as a Service) : 모든 인프라와 소프트웨어 제공

    • 주요 업체


AWS EC2, RDS, S3

  • EC2 : 가상 컴퓨팅 환경을 제공받아 가상의 서버 구축
  • RDS : 관계형 DB를 위한 데이터베이스 전용 서버 구축
  • S3 : 필요한 파일(이미지, 동영상)을 저장하여 S3 주소를 통해 접근

Web


Servlet, JSP

  • Servlet : Container가 이해할 수 있도록 구성된 순수 자바 코드 (Html in JAVA)
  • JSP (Java Server Page) : html 기반에 자바 코드를 블록화하여 삽입 (JAVA in Html)
  • MVC 1
    • JSP 페이지 안에서 로직 처리를 위해 자바 코드가 함께 사용
    • 구조가 단순
    • JSP 내에서 html자바 코드함께 사용되어 복잡하고 유지보수가 어려움
  • MVC 2
    • JSP와 서블릿이 역할을 분담
    • JSP: 요청 결과를 출력하는 VIEW 처리 + 서블릿: 흐름제어, 컨트롤러 역할
    • 구조가 복잡하나 유지보수가 용이

GET vs POST

  • GET
    • C → S 전송 시, 주소 뒤에 이름이 결합된 스트링 형태로 전달
    • 쿼리가 보여지기에 보안성이 낮음
    • 길이 제한 (= 전송 데이터 한계)
    • POST보다 빠른 속도
  • POST
    • 일정 크기 이상의 데이터 전송
    • 서버로 보내기 전 인코딩, 서버에서 디코딩
    • 데이터 노출 X → 보안성이 높음
    • GET보다 느린 속도
    • 문자열 데이터 뿐만 아니라 객체(라디오 버튼, 텍스트 박스 등) 값 전송
  • 차이점
    • 목적
      • GET은 주로 웹 브라우저 → 웹 서버 데이터 요청
      • POST는 웹 브라우저 → 웹 서버 데이터 전달
    • 보안
      • GET은 데이터가 인코딩되어 URL에 노출 → 보안 낮음
      • POST는 데이터 노출 X → 보안 높음
    • 제한
      • GET은 255개의 문자를 초과하면 안된다.
      • POST는 많은 데이터 전달 가능, 제한 없다.

  • 사용 이유 : 현재의 HTTP 프로토콜연결 지향적이지 않다. 새로운 페이지를 요청할 때마다 새로운 접속이 이루어지고 전 페이지와 현 페이지의 관계가 지속되지 않는다. 따라서 웹페이지에 방문자가 머무르고 있을 때, 방문자의 상태를 지속시키기 위해 Session or Coookie를 사용
  • Session
    • 특정 웹사이트에서 사용자가 머무르는 기간 또는 한 명의 사용자의 한번의 방문을 의미한다.
    • Session에 관련된 데이터는 Server에 저장된다.
    • 웹 브라우저의 캐시에 저장되어 브라우저가 닫히거나 서버에서 삭제시 사라진다.
    • Cookie에 비해 보안성이 좋다.
  • Cookie
    • 인터넷 웹 사이트의 방문 기록을 남겨 사용자와 웹 사이트 사이를 매개해 주는 정보이다.
    • Cookie는 인터넷 사용자가 특정 웹서버에 접속할 때, 생성되는 개인 아이디와 비밀번호, 방문한 사이트의 정보를 담은 임시 파일
    • Cookie는 Client PC에 저장되는 정보기 때문에, 다른 사용자에 의해서 임의로 변경이 가능하다. (정보 유출 가능, Session보다 보안성이 낮은 이유)
  • 보안성이 낮은 Cookie 대신 Session을 사용하면 되는데 안하는 이유?
    • 모든 정보를 Session에 저장하면 Server의 메모리를 과도하게 사용하게 되어 Server에 무리가 감

TCP, UDP

  • TCP (Transmission Control Protocol)
    • 연결형 서비스
    • 높은 신뢰성
    • 연결 설정 (3-way handshaking)
    • 연결 해제 (4-way handshaking)
    • 데이터 흐름 제어, 혼잡 제어
    • 전이중, 점대점 서비스 (양방향 송수신 서비스)
  • UDP (User Datagram Protocol)
    • 비연결형 서비스
    • 낮은 신뢰성
    • 데이터의 전송 순서가 뒤바뀔 수 있다.
    • 데이터 송수신 여부 확인 X
    • TCP 보다 빠름
  • 참고 : https://mangkyu.tistory.com/15

JWT 사용 이유, 절차

  • 💖 (중요) 사용 이유
    • 사용자 인증에 필요한 정보를 토큰에 담는다.
      • 별도의 저장소가 필요 없다. (=State-less한 서버)
      • Session은 State-ful
    • 토큰 기반으로 한 다른 인증 시스템 접근 가능 ex) OAuth 2.0
  • 인증 절차
    • 사용자가 로그인 시도
    • 서버는 요청을 확인하고 Secret Key를 통해 Access Token 발급
    • 인증 이후, 사용자가 API 요청 시, Authorization header에 Access Token을 담아 요청
    • 서버는 JWT signature를 체크하여 인증된 사용자 정보를 확인 후 원하는 데이터 반환

Database


JDBC

  • JDBC (Java Data Base Connection) : JAVA를 통해 DB에 접근하도록 하는 프로그래밍

트랜잭션

  • 성질 (ACID)

    • 원자성, Atomicity : 트랜잭션 작업들이 DB에 전부 반영된지, 안 된지를 보장
    • 동일성, Consistency : 트랜잭션이 완료되면 동일한 DB를 보장
    • 고립성, Isolation : 트랜잭션 수행 시, 다른 트랜잭션의 연산 작업이 끼어들지 못함
    • 지속성, Durability : 성공적인 트랜잭션 수행의 커밋은 영원히 반영
  • 읽기 이상 현상

    • Dirty Read : 한 트랜잭션 진행 중, 다른 트랜잭션이 갱신하고 Commit하지 않은 데이터를 읽어 발생
    • Non-Repeatable Read : 한 트랜잭션이 조회한 데이터를 다시 조회할 때 변경된 데이터를 읽어 발생
      • Dirty Read와 다른 점은 다른 트랜잭션에서 Commit 한다는 점
    • Phantom Read : 한 트랜잭션 진행 중, 다른 트랜잭션이 추가하거나 삭제한 데이터를 읽어 발생
  • 격리 수준 (아래로 갈수록, 일관성은 좋다, 성능은 떨어진다.)

    • Read Uncommitted : 다른 트랜잭션에서 커밋하지 않은 데이터를 읽을 수 있다.
      • 데이터의 정확도는 중요치 않으나 트랜잭션의 수행시간이 길 때
    • Read Committed : 다른 트랜잭션에서 커밋한 데이터만을 읽음
    • Repeatable Read : 트랜잭션 진행 중 읽은 데이터를 재차 읽을 때, 다른 트랜잭션이 이를 갱신할 수 없다.
    • Serializable : 동시 진행하는 트랜잭션이 순차적으로 실행한 것과 같은 결과
  • 💖 격리 수준에 따른 이상 현상

    • 다만, RDB의 시스템마다 결과가 다를 수도 있다.

데이터베이스 인덱스

  • 추가적인 쓰기 작업과 저장 공간을 활용하여 DB TABLE의 검색 속도를 향상시키는 자료 구조
  • 장점
    • 테이블을 조회하는 속도, 성능 향상
    • 시스템 부하 감소
  • 단점
    • 인덱스 관리를 위한 데이터베이스의 1/10 가량의 저장공간 필요
    • 추가 작업 필요
    • 잘못 사용할 경우 성능 저하의 역효과 발생
  • 사용하는 경우
    • 규모가 비교적 큰 테이블
    • 삽입, 수정, 삭제가 자주 발생하지 않는 컬럼
    • JOIN, WHERE, ORDER BY에 자주 사용되는 컬럼
    • 데이터의 중복도가 낮은 컬럼
  • 종류 : 해시 테이블, B+Tree 등

Design Pattern


MVC 패턴

  • MVC : 사용자 인터페이스를 효과적으로 데이터 모형에 관련 시키기 위한 디자인 패턴
  • Model
    • 논리적 데이터 기반 구조를 표현
    • 사용자 인터페이스에 대한 어떠한 정보도 갖지 않는다.
  • View
    • 사용자 인터페이스 내 구성요소 표현 (사용자에게 보여지는 화면)
  • Controller
    • Model과 View를 잇는 클래스 (Model과 View의 정보 교환 클래스)

SOLID 패턴

  • 객체 지향에서 지켜야할 5가지 원칙
  • 좋은 설계 : 시스템에 새로운 요구사항/변경사항이 있을 때, 영향을 받는 범위가 적은 구조
  • 1) SRP (Single Resposibility Principle, 단일 책임 원칙)
    • 객체는 단 하나의 책임만 가져야 한다.
    • 응집도를 높게, 결합도를 낮게
    • 🧨응집도
      • 한 프로그램의 요소가 얼마나 뭉쳐있는지, 즉 구성 요소들 사이의 응집력
    • 🧨결합도
      • 프로그램 구성 요소들 사이가 얼마나 의존적인지
  • 2) OCP (Open-Closed Principle, 개방-폐쇄 원칙)
    • 기존의 코드를 변경하지 않고 (closed), 기능을 추가할 수 있도록 (open) 설계되어야 한다.
      • = 확장은 개방, 수정은 폐쇄
    • 캡슐화, 여러 객체에서 사용하는 기능을 인터페이스를 통해 구현
  • 3) LSP (Liskov Substitution Principle, 리스코프 치환 원칙)
    • 자식 클래스는 최소한 자신의 부모 클래스에서 가능한 행위는 수행 가능해야 한다.
    • 자식 클래스는 부모 클래스의 책임을 무시하거나 재정의하지 않고 확장만 수행해야 한다.
      • = 오버라이드는 가급적 피하자.
  • 4) ISP (Interface Segregation Principle, 인터페이스 분리 원칙)
    • 자신이 사용하지 않는 인터페이스는 구현하면 안된다.
    • SRP는 객체의 단일 책임, ISP는 인터페이스의 단일 책임
  • 5) DIP (Dependency Inversion Principle, 의존 역전 원칙)
    • 객체들은 서로 정보를 주고 받을 때 의존 관계가 형성된다. 이 때, 객체들은 나름대로의 원칙을 갖고 정보를 주고 받아야 한다.
    • 나름대로의 원칙?
      • 추상성이 높은 클래스와 의존 관계를 맺어야 한다. (= Interface)

Framework


Framework?

  • 소프트웨어를 형성하기 위한 클래스 프레임인터페이스 프레임의 집합
  • 특정 개념들의 추상화를 제공하는 여러 클래스재사용 가능한 컴포넌트로 구성
  • 중요한 이유
    • 여러 개발자와 여러 프로그램이 생겨 시스템의 통합성, 일관성이 부족해질 가능성을 방지하기 위해 프레임워크가 존재한다.
  • 프레임워크가 가져야 할 특징
    • 가이드라인
    • 정해진 범위
    • 다양한 도구 지원
  • 장/단점
    • 장점 : 개발 시간 단축, 오류 검증
    • 단점 : 너무 프레임워크에 의존하면 개인의 개발 능력이 부족하게 된다.

Spring Framework

  • JAVA를 사용하는 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크
  • 자바로 된 프레임워크로 자바SE로 된 자바 객체(POJO)를 자바EE에 의존적이지 않게 연결해주는 역할 (중량급 프레임워크에 의존적이지 않게)
  • 특징
    • 1) 경량 컨테이너로서 자바 객체를 직접 관리. (Spring bean)
      • 객체의 라이프 사이클을 관리, 스프링으로부터 필요한 객체를 얻어올 수 있다.
    • 2) 스프링은 POJO(Plain Old Java Object) 방식의 프레임워크
    • 3) 제어의 역행(IoC : Inversion of Control)
      • 컨트롤의 제어권이 사용자가 아니라 프레임워크에 있어서 필요에 따라 스프링에서 사용자의 코드를 호출한다.
      • 결합도를 낮춘다.
    • 4)  의존성 주입(DI : Dependency Injection)
      • 각각의 계층이나 서비스들 간에 의존성이 존재할 경우 프레임워크가 서로 연결시켜준다.
    • 5)  관점 지향 프로그래밍(AOP : Aspect-Oriented Programming)
      • 트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능을 분리하여 관리
    • 6) 스프링은 영속성과 관련된 다양한 서비스를 지원
      • 완성도가 높은 데이터베이스 처리 라이브러리와 연결할 수 있는 인터페이스를 제공한다.
    • 7) 스프링은 확장성이 높음.
      • 수많은 라이브러리가 스프링에서 지원되고 스프링에서 사용되는 라이브러리를 별도로 분리하기도 용이

JPA

  • ORM (Object-Relational Mapping)

    • 객체와 관계형 데이터 베이스를 각각 설계한다.
    • ORM이 중간에서 매핑
  • JPA (Java Persistence API)

    • 자바의 ORM 기술 표준, 인터페이스 모음
    • JPA의 대표적인 구현체 : Hibernate
  • 동작

    • 애플리케이션과 JDBC 사이에서 동작 (조회, 저장 등)

  • 🧨사용 이유

    • 1) SQL 중심 개발 → 객체 중심 개발
    • 2) 생산성
      • Java Collection에 데이터를 넣었다 빼는 것처럼 사용할 수 있도록 만들었다.
      • 기본적인 CRUD
      • 쉬운 수정 (객체 변경 시, 알아서 DB에 UPDATE QUERY가 생성)
    • 3) 유지보수
    • 4) Object와 RDB간 패러다임 불일치 해결
    • 5) 성능 최적화
      • 캐싱 : 같은 트랜잭션 안 같은 엔티티 반환
      • 버퍼링 : 생성한 쿼리들을 커밋시 한 번에 실행
      • 지연 로딩 : 객체가 실제 사용될 때 로딩
    • 6) 데이터 접근 추상화와 벤더 독립성
    • 7) 표준

MyBatis

  • 개발자가 지정한 SQL/저장프로시저/고급 매핑 등을 지원하는 Java Persistence Framework.
  • 자바에서 SQL Mapper를 지원해주는 프레임워크
    • = SQL을 직접 작성하여 매핑
    • SQL Mapper?
      • SQL문을 이용하여 RDB에 접근, 데이터를 객체화 시켜준다.
      • 💥즉, RDB에 따라 SQL 문법이 바뀌기 때문에 종속적이다.
  • JPA vs MyBatis
    • JPA
      • 장점
        • 1) RDB에 종속적이지 않아, 코드 재활용 용이
        • 2) 기본 CRUD 제공, 페이징 기능 등 비지니스 로직 집중 가능
        • 3) 엔티티 관리 쉬움
        • 4) 쿼리보다 개발에 더 집중 → 빠른 개발
      • 단점
        • 어려움
    • MyBatis
      • 장점
        • 1) 쉬움
        • 2) SQL의 세부적인 변경이 비교적 간편
        • 3) 동적 쿼리
      • 단점
        • 1) RDB에 종속적
        • 2) JPA보다 많은 설계 및 로직 필요
profile
열심히 해보자9999

0개의 댓글