11/11

장현진·2022년 11월 11일
0

1. Singleton pattern 이란 무엇이고, 어떤 장점과 단점이 있을까요?

  • 싱글톤 : 객체의 인스턴스가 오직 1개만 생성되는 패턴
    1. 고정된 메모리 영역을 얻으면서 한번의 new로 인스턴스를 사용하기 때문에 메모리 낭비를 방지
    2. 싱글톤으로 만들어진 클래스의 인스턴스는 전역 인스턴스이기 때문에 다른 클래스의 인스턴스들이 데이터를 공유하기 쉽다.
    3. 의존관계상 클라이언트가 구현체에 의존하면서 DIP를 위반하게 된다. DIP를 위반하면 자연스럽게 OCP를 위반할 가능성도 높아진다.
    4. 싱글톤 패턴을 적용하기 위해 구현할 코드양이 많아지면서 비용이 늘어난다.
    5. 테스트가 어려워진다.
      ⇒ 인스턴스를 미리 다 받아서 설정이 끝난 상태이기에 유연한 테스트가 힘들다.
    6. 내부 속성을 변경하거나 초기화가 어렵다.
    7. private생성자로 자식 클래스를 만들기 어렵다.
    8. 유연성이 떨어진다.
    9. 안티패턴으로 불리기도 한다.
  • 주의점
    싱글톤 패턴에서는 객체 인스턴스를 하나만 생성해서 공유하는 방식이기 때문에 여러 클라이언트에서 해당 인스턴스를 공유하게된다. 그렇기 때문에 해당 객체가 상태를 유지하는 stateful 방식의 객체이면 문제가 발생한다.
    그렇기 때문에 상태를 유지하지 않는 stateless 상태로 객체를 설계해야 한다.

상태를 유지하지 않는 객체를 설계하기 위해서는

  • 특정 클라이언트에 의존적인 필드가 있으면 안된다.
  • 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
  • 가급적 읽기만 가능해야 한다.
  • 필드 대신 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal등을 사용해야 한다.
package hello.core.singleton;

public class StatefulService {
    private int price; // 상태를 유지하는 필드

    public void order(String name, int price) {
        System.out.println("name = " + name + " price = " + price);
        this.price = price;
    }

    public int getPrice() {
        return price;
    }
}

2. 싱글턴 코드는 테스트를 어렵게 만드는 문제가 있습니다. 왜 그럴까요? 싱글턴이 좋지 않다는데 왜 스프링 프레임워크 같은 녀석들은 별다른 규칙이 없을 때 기본으로 Singleton bean 을 만들까요?

스프링 싱글톤은 클래스 자체에 의해서가 아니라, 스프링 컨테이너(Bean Factory/Application Context)에 의해 구현된다.

스프링에서는, 컨테이너 내에서 특정 클래스에 대해 @Bean이 정의되면, 스프링 컨테이너는 그 클래스에 대해 딱 한 개의 인스턴스를 만든다. 이 공유 인스턴스는 설정 정보에 의해 관리되고, bean이 호출될 때마다 스프링은 생성된 공유 인스턴스를 리턴 시킨다.

공유인스턴스의 생성시점은 스프링 컨테이너에 따라 달라지는데, 빈팩토리는 최초 호출시점에서 인스턴스를 생성하고(Lazy loading), 애플리케이션 컨텍스트는 미리 모든 공유인스턴스를 다 초기화해 두었다가 호출될때 바로 리턴시켜준다.

bean 관리의 주체인 스프링 컨테이너는 그 어떤 호출에도 단일 공유 인스턴스를 리턴시키므로 thread safety도 자동으로 보장

3. 좋은 Test 라고 평가할 수 있는 가장 중요한 요소

좋은 테스트의 원칙 FIRST 🥇

  • FIRST란 Fast, Isolated, Repeatable, Self-validating, Timely 의 문자를 따서 지어진 이름

https://velog.io/@jooyoung/%EC%A2%8B%EC%9D%80-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80

4. Callback function(또는 Closure) 이 뭔가요? 주의할 점이 있을까요?

다른 함수가 실행을 끝낸 뒤 실행(call back)되는 함수(⇒ 나중에 호출되는 함수)
=> 코드를 통해 명시적으로 호출하는 함수가 아니라, 함수를 등록해 놓은 후 어떤 이벤트가 발생했거나 특정 시점에 도달했을 때 시스템에서 호출하는 함수.
(동적으로 이벤트 정의 ? )

  • 템플릿-콜백 패턴 적용하기
    템플릿-콜백패턴이란 결국 전략패턴의 변형된 형태라고 봐야합니다. 전략패턴의 기본적 구조에 변화되는 부분을 매번 클래스로 만들지 않고, '익명 내부 클래스' 바로 생성
class MyClass {
    void myMethod(PrintB printB) {
        a();

        printB.b();

        c();
    }

    void a() {
        System.out.println("A");
    }

    void c() {
        System.out.println("C");
    }
}

interface PrintB {
    void b();
}

public class Main {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();

        myClass.myMethod(()-> System.out.println("B1"));
        myClass.myMethod(()-> System.out.println("B2"));
    }
}

https://wwlee94.github.io/category/study/toby-spring/template-callback/

  • 주의점
    • 스프링 프레임워크에서 DI를 사용하지 않게 되면 싱글톤 객체가 되지 않는다.
    • 인터페이스를 사용하지만, 실제 사용할 클래스를 직접 선언하므로 결합도가 증가한다.

5. Mutable, Immutable 이란 뭔가요? 각각은 어떤 특징이 있을까요?

Mutable한 객체는 생성된 이후에 상태가 변경될 수 있는 객체이고, Immutable한 객체는 생성된 이후에 상태가 변경되지 않는 객체

  • immutable한 클래스
    String, Boolean, Integer, Float, Long 등
  • immutable한 클래스를 만들기
    immutable은 값을 변경할 수 없는 클래스를 뜻한다. 즉 set 메소드가 없다!
    또한 final 키워드를 사용해 변수 초기화 이후 바뀌지 않도록 막는다.
public class ImmutableTest {
     
    private final String userName;
     
    ImmutableTest(String userName){
        this.userName = userName;
    }
     
    @Override
    public String toString(){
        return this.userName;
    }
 
}

결과 값은 immutable로 만들었던 userName(홍길동)은 변하지 않고, 새로운 객체 둘리가 userName에 할당된다.

  • Immutable 장점

    • 데이터(객체)에 대한 신뢰성이 높아진다.
    • 방어적 대응을 고려하지 않아도 됩니다.
    • 멀티 스레드에서 동기화 처리 없이 객체를 공유.
  • Immutable 단점

    • 메모리 누수 가능성이 많아질 수 있다.
    • 메모리 사용이 많아진다.

6. Acceptance, Smoke, End-to-End, Integration, Unit test 같은 용어들을 본인만의 방법으로 구분짓는 기준이 있습니까?

7. 메소드의 파라미터로 전달한 객체를 메소드 내에서 마음대로 바꾸지 못 하게 하려면 어떻게 코딩하는게 좋을까요? 왜 메소드가 파라미터를 조작하는 것이 문제가 될까요? 문제가 아닐 수도 있지 않을까요?

객체의 값을 다른 메소드에서 변경하게 되면 코드를 예상을 빗나가는 코드가 된다.
또한 외부에서 값을 변경함으로 인해 변경에 취약해지고 OCP를 어기게 된다. 이를 막기 위해 모든 객체의 상태값 변경은 private으로 정의 하고 객체 내부에서 메소드 콜을 이용하여 이루어 져야 한다.

8. 음료수 자판기에 탑재한 소프트웨어를 제작했다고 가정해 보겠습니다. 작성하신 소프트웨어의 통합 테스트 시나리오를 어떻게 작성하시겠습니까? 생각나는대로 말씀해 주세요.

  1. 돈을 넣는다
    1-1. 돈을 인식한다.
    1-2. 돈을 받는다.
    1-3. 받은 돈만큼 코스트를 올린다.

  2. 버튼을 누른다.
    2-1. 버튼에 맞는 음료수가 있는지 확인한다.

  3. 버튼에 맞는 음료수를 반환한다.
    3-1. 음료수를 반환한다.
    3-2. 음료수를 다시 채운다.

  4. 음료수 재고를 변경한다.

  5. 3~4 반복

  6. 잔돈 반환을 누른다.
    6-1. 잔돈을 확인한다.
    6-2. 남은 금액을 반환한다.

  • 통합테스트 : 점진적으로 통합하며 테스트


https://junspapa-itdev.tistory.com/44

9. 현재 다루시는 플랫폼에서의 테스트 자동화를 어떻게 구축 하시겠습니까?

Spring REST Docs의 가장 큰 장점은 테스트가 성공해야 문서을 작성할 수 있기 때문에, 테스트를 강제한다.
https://tecoble.techcourse.co.kr/post/2020-08-18-spring-rest-docs/

10. test code 를 작성하는 본인만의 기준이 있습니까? test 실행 속도를 높이려면 어떤 방법이 좋을까요?

  • 각 테스트 class마다 같은 부모 class를 상속함에도 한번 띄운 서버를 재사용하지 않고 계속 서버를 새로 띄울수 있음
    • SpringBootTest는 context caching을 한다는 것이었다. 따라서 context에 변경이 없는 한 한번 띄운 서버를 재사용하는 것이 기본
    • @MockBean을 사용할 경우 기존에 선언된 Bean을 mocking된 객체로 변경시켜야 하기 때문에 context에 변경이 생겼다고 인식하고 새로운 서버를 띄운다.
  • DataJpaTest, SpringBootTest를 사용할경우 2개의 Application Context가 만들어 질수 있다. -> Configuration을 통일 필요

https://cobbybb.tistory.com/16
https://jojoldu.tistory.com/226
https://tw-you.tistory.com/5
https://www.hyojae.info/7d876a64-c2a8-4e88-b007-a28e18a82f4f

11. blackbox testing, whitebox testing 의 차이에 대해 설명해주세요. 어떤 상황에서 어떤 테스트 방법을 사용하시겠습니까?

화이트박스 테스트의 종류

  • 기초 경로 검사(Base Path Testing)

    • 테스트 케이스의 설계자가 코드의 복잡성을 측정할 수 있게 해주는 테스트 기법
  • 제어 구조 검사

    • (Control Structure Testing) 논리적 조건, 반복구조, 데이터의 흐름을 테스트 한다.
    • 조건 검사 (Condition Testing) : 프로그램 모듈내에 논리적 조건을 테스트 하는 테스트 케이스 설계기법
    • 반복 검사(Loop Testing) : 반복구조에 초점을 맞춰 실시하는 테스트 설계기법
    • 데이터 흐름 검사 (Data Flow Testing) : 실제 사용자들이 입력하는 갑들을 변수에 넣을때 변수 정의와 변수 사용 위치를 어떻게 했는지 초점을 맞춰서 테스트하는 설계 기법

화이트 박스 테스트의 검증 기준

  • 문장 검증 기준
    (Statement Coverage) 소스 코드의 모든 구문을 한 번 이상 수행 되도록 항목 설계
  • 분기 검증 기준
    (Branch Coverage) 소스 코드의 모든 조건문을 한 번 이상 수행되도록 항목 설계
  • 조건 검증 기준
    (Condition Coverage) 소스 코드의 모든 조건문의 참, 거짓을 각 한번 이상 수행되도록 항 목 설계
  • 분기/조건 기준
    (Branch/Condition Coverage) 소스 코드의 모든 조건문과 각 조건문에 포함된 개별 조건식의 결과가 참, 거짓인 경우 각각을 한 번 이상 수행되도록 항목 설계

블랙박스 테스트의 종류

  • 동치분할 테스트
    (=동치 클래스 분해)
    (Equivalence Partitioning Testing) 정상적인 입력자료와 비정상 적인 입력자료의 개수를 균등하게 해서 테스트 케이스를 정하고 해당 입력 자료에 맞는 결과가 출력되는지 확인하는 기법
    동등 분할 기법이라고도 한다.
    ex)어떤 값이 입력되었을때 예상되는 결과값을 테스트케이스로 잡고 실제로 테스트 했을때 예상되는 결과값이 나오는지 확인하는것
  • 경계값 분석
    (Boundry Value Analysis) 입력 조건의 중간값 보다 경계값에서 오류발생 확률이 높기 때문에 경계값을 테스트 케이스로 선정하여 검사하는 기법
  • 원인-효과 그래프 검사
    (Cause-Effect Graphing Testing) 여러 입출력 데이터를 분석해서 영향을 미치는 상황을 체계적으로 분석한 다음 효율성이 높은 테스트 케이스를 선정하는 기법
  • 오류 예측 검사
    (Error Guessing) 과거의 경험이나 확인자의 감각으로 테스트
  • 비교 검사
    (Comparison Testing) 동일한 테스트 케이스를 여러 버전의 프로그램에 적용하여 동일한 결과가 출력되는지 비교하는 테스팅 기법

12. 상속의 이점 중 "코드의 중복을 줄여준다" 는 말이 있습니다. 그런데 코드 중복을 줄이기 위해서 상속을 쓰는 것은 매우 좋지 않은 코딩 방식이라고 저희는 생각합니다. 이에 대한 후보자님의 의견을 듣고 싶습니다.

상속은 자식과 부모클래스의 결합도를 높이게 된다. 이로인해 중복을 위한 상속은 자식 클래스가 변경에 취약해지고 OCP를 위반하게 됩니다.

상속은 대표적으로 다음과 같은 단점을 가지고 있다.

  • 캡슐화가 깨지고 결합도가 높아짐( super )
  • 유연성 및 확장성이 떨어짐
  • 다중상속에 의한 문제가 발생할 수 있음
  • 클래스 폭팔 문제가 발생할 수 있음

https://mangkyu.tistory.com/199
oop 320p

  • 상속을 사용해야 하는 경우
    • 타입 계층을 구현하는 것
      • 부모와 자식 클래스가 Is-A 관계인 경우
      • 행동 호환성이 만족하는 경우
  • 상속의 단점을 피하면서도 코드를 재사용할 수 있는 더 좋은 방법 : 합성

13. Java 의 Marker interface (아무 메소드도 없이 타입만 있는) 에 대해 어떻게 생각하시나요?

자바의 대표적인 마커 인터페이스로는 위에서 언급한 Serializable, Cloneable 이 있다
컴파일러와 JVM은 이 마커 인터페이스를 통해 객체에 대한 추가적인 정보를 얻을 수 있게 함이 목적 => 단순한 타입 체크를 하기 위해 사용한다. 클래스에 타입을 부여하기 위한 쉬운 방법중 하나

     **자바에서 직렬화는 JVM 메모리에서만 상주되어있는 객체 데이터를 그대로 영속화가 필요할 때 사용
  • 마커 인터페이스의 장점

    • 마커 인터페이스는 이를 구현한 클래스의 인스턴스들을 구분하는 타입으로 쓸 수 있으나, 마커 어노테이션은 그렇지 않다.
    • 마커 인터페이스는 어엿한 타입이므로, 마커 어노테이션을 사용했다면 런타임 때 발견될 오류를 컴파일 타임에 잡을 수 있다.
    • ObjectOutputStream.writeObject 메서드는 이 점을 살리지 못했기 때문에 실제로 런타임에 오류가 발생한다.
    • 마커 인터페이스는 적용 대상을 더 정밀하게 지정할 수 있다.
    • 적용대상(@Target)을 ElementType.TYPE으로 선언한 어노테이션은 모든 타입(클래스, 인터페이스 , Enum, 어노테이션)에 달 수 있다. -> 부착할 수 있는 타입을 더 세밀하게 제한하지 못한다.
    • 특정 인터페이스를 구현한 클래스에만 적용하고 싶은 마커가 있다고 가정하고, 이 마커를 인터페이스로 정의했다면 그냥 마킹하고 싶은 클래스에서만 그 인터페이스를 Impl(구현/확장)하면 된다.
  • 마커 인터페이스의 단점

    • 마커 어노테이션은 거대한 어노테이션의 시스템의 지원을 받는다. (즉, 마커 인터페이스는 어 노테이션의 장점을 살리지 못함)
    • 어노테이션을 주로 쓰는 프레임워크라면 마커 어노테이션을 통한 기능/활용이 마커 인터페이스를 사용하는 것보다 용이하다.

    https://xonmin.tistory.com/24

14. 코드 응집성(cohesion)이란 말을 어떻게 설명하실 수 있습니까? 응집도가 낮은 코드와 높은 코드를 예를 들어 설명해 주세요.

  • 응집도(Cohesion)란?
    • 하나의 모듈이 하나의 기능을 수행하는 요소들간의 연관성 척도
    • 독립적인 모듈이 되기 위해서는 응집도가 강해야 한다.
  • 응집도가 낮은 코드
public void setValue(String name, int value) {
    if ("height".equals(name)) {
        height = value;
    }
    if ("width".equals(name)) {
        width = value;
    }
}

height 세팅시에는 아래 코드가 필요없는 코드가 된다.

  • 응집도가 높은 코드
private void setHeight(int height) { 
	this.height = height; 
}
private void setWidth(int width) { 
	this.width = width; 
}
  • 응집도가 낮은 클래스의 문제점
    • 이해하기 어려움
    • 재사용하기 힘듦
    • 다른 클래스의 변화에 민감함

15. NodeJS 로 실행하는 서버와 통신하는 Spring 또는 Python 서버를 구현할 때, 어떻게 하시겠습니까? HTTP 외의 방법을 쓰고 싶다면 어떻게 해야 할까요?

rest api 통신 http를 쓸수 없다면 소켓 통신을 이용한다.

16. 네이버 같은 서비스에서 IP 주소가 바뀔 경우 접속 경고 등의 오류를 발생시킨다. 어떻게 구현하시겠습니까?

17. 서비스의 memory leak 을 어떻게 판단하고, 해결하시겠습니까?

GC 로그를 통해 FULL GC빈도수와 메모리 변경 사항 확인.

18. 우리 서비스가 대 성공해서 이용자가 4000만이 되었다고 가정합니다. 이용자 4천만 돌파 기념으로 선착순으로 접속한 사용자에게 보너스 포인트를 주는 이벤트를 운영하려 합니다. 모든 이용자들에게 공평하게, 플랫폼이 제공하는 Push 를 보내려 하는데요. 이 경우, 어떤 점들을 고려해야 할까요?

0개의 댓글