핵심 비즈니스 로직을 가지는 도메인 객체들을 domain 패키지에, UI와 관련된 객체들을 view 패키지에 구현했다.
MVC 패턴 기반으로 view 패키지의 객체가 domain 패키지 객체에 의존할 수 있지만,
domain 패키지의 객체는 view 패키지 객체에 의존하지 않도록 구현했다.
Q.
"view 패키지의 객체가 domain 패키지 객체에 의존할 수 있지만,
domain 패키지의 객체는 view 패키지 객체에 의존하지 않도록 구현했다."
라고 했는데, 왜 그렇게 했나요?
A. 미션 프로그래밍 요구사항이었습니다. view와 domain의 의존성을 완전히 분리하기 위해 중간에 Controller를 두고, DTO로 데이터를 주고 받습니다. 해당 미션을 진행할 때 아직 DTO에 대해 잘 몰라서 적용하지 못했습니다. 하지만 DTO에 대해 학습한 이후의 미션들에는 DTO를 사용해 view와 domain의 의존성을 완전히 분리했습니다.
Q. 일급 컬렉션에 대해 설명해 주세요.
A. 일급 컬렉션은 클래스에 필드가 하나만 있고, 해당 필드가 컬렉션을 참조하는 것을 말합니다.
즉, 하나의 컬렉션을 클래스로 감싸는 것 인데요.
이렇게 하면 해당 컬렉션에 이름을 부여할 수 있습니다.
또한, 캡슐화가 적용되어 비즈니스 로직이 적용된 자료구조로 만들 수 있습니다.
일급 컬렉션 클래스에 컬렉션의 값을 변경할 수 있는 메소드가 없도록 하면, 불변 컬렉션으로 만들 수 있습니다.
요즘과 같이 소프트웨어 규모가 커지고 있는 상황에서 불변 객체는 아주 중요합니다.
각각의 객체들의 값이 바뀔일이 없다는게 보장되면, 그만큼 코드를 이해하고 수정하는데 사이드 이펙트가 최소화되기 때문입니다.
Q. Enum이 뭔가요? 어떤 방식으로 생성되고 사용되나요?
A. Java에서 특정 값들을 모아 하나의 타입으로 선언할 수 있습니다. 이 타입을 "Enum 타입" 이라고 합니다.
예를 들어 한 주의 요일들의 값, MONDAY 부터 SUNDAY 까지를 하나의 Enum 타입으로 선언할 수 있습니다.
이때, 각 요일들의 값을 Enum 상수 라고 합니다.
각 Enum 상수에 해당되는 Week Enum 객체가 Heap 영역에 생성됩니다.
그리고 각 Enum 상수들은 자신의 Week Enum 객체를 Method 영역에서 참조합니다.
Enum 타입의 참조변수로 특정 Week Enum 객체를 참조할 수 있습니다.
참조 변수는 Stack 영역에 저장되고, Method 영역에 있는 MONDAY 객체의 주소값을 그대로 복사해서 참조합니다. 즉, 참조되는 모든 Week Enum 타입의 MONDAY 객체는 단 하나의 동일한 객체입니다.
Q. Map의 "computeIfPresent()"는 어떤 API인가요?
A. 첫 번째 인자로 key 값을 받습니다. 해당 key 값이 Map의 key 값으로 존재하면, 두 번째 인자로 전달된 람다 함수가 호출됩니다. 존재하지 않을경우에는 호출되지 않습니다.
두 번째 인자로 전달된 람다 함수는 두 개의 매개변수 (key, value)를 가질 수 있습니다.
수익률 소수점 계산에서 BigDecimal API 사용이 필요했다.
사용법을 제대로 숙지하지 않은 채 사용해, 소수점 셋 째 자리에서 반올림이 되지 않는 버그가 발생했다.
BigDecimal API 문서 와 구글링을 참고하고, 학습 테스트 를 통해 정확한 API 사용법을 익혀 버그를 고쳤다.
맨 처음 구현할 때, 구글링을 통해 찾은 잘못된 자료 를 참고해서 코드를 작성했다. 사용법이 애매할 때는 학습 테스트 로 제대로 익힌 뒤에 사용해야 겠다.
Q. BigDecimal을 왜 사용했나요?
A. 로또 수익률 계산에서 double 타입을 사용했을 때, 부동소수점 방식 때문에 오차가 발생했습니다. 이 오차를 없애고자 BigDecimal을 사용했습니다.
딜러가 몇 장의 카드를 반환할지 결정하는 데에 전략패턴을 사용했다.
전략패턴을 적용하면 최소한의 코드 수정으로 전략을 다르게 가져갈 수 있고, 확장에도 자유로움을 알 수 있었다.
Q. 전략 패턴이 무엇이고, 왜 사용했는지 설명해주세요.
A. 전략 패턴은, 외부에서 전략 객체를 주입해 전략에 따라 객체의 로직을 다르게 가져갈 수 있는 설계 방식입니다.
전략들을 하나의 인터페이스로 추상화 합니다. 그리고 이 인터페이스를 구현하는 각 전략 구현체들은 각자의 전략에 맞도록 함수를 구현합니다.
전략을 사용하는 객체는 전략 세팅 메소드를 통해 외부로부터 전략들을 주입받습니다.
인터페이스의 다형성을 통해 전략 세팅 메소드의 매개변수로 다양한 전략 구현체들을 받을 수 있습니다.
페어 멍토의 제안으로, 애플리케이션 전체에서 공유되는 카드 뭉치 객체에 싱글톤 패턴을 적용했다.
애플리케이션 전체에서 공유되는 객체에 대해서는 static 적용만 해왔는데, 싱글톤 패턴 적용에 대해 새롭게 배웠다.
Q. 싱글톤 패턴이 무엇이고, 왜 사용했는지 설명해주세요.
A. 객체의 인스턴스를 단 하나만 생성하는 패턴을 싱글톤 패턴이라고 합니다. 블랙잭 미션의 애플리케이션은 한 번 실행 할 때 마다 한 번의 게임만 진행합니다. 따라서 애플리케이션에서 단 하나의 카드 뭉치 객체만 필요해 싱글톤 패턴을 적용했습니다.
싱글턴 패턴은 멀티쓰레드 환경의 동시성 문제를 고려해서 설계해야 합니다.
이를 고려하지 않으면, 싱글톤의 목적과 달리 두 개의 인스턴스가 생성될 수도 있습니다.
가장 많이 사용되는 방식은 LazyHoder 방식 입니다.
volatile
이나 synchronized
키워드 없이도 동시성 문제를 해결하기 때문에 성능이 뛰어납니다.
특정 메서드를 호출할 때, Inner static 클래스의 클래스 인스턴스가 초기화 됩니다.
별도의 키워드 없이 동시성 문제와 사전 초기화로 인한 메모리 낭비 문제를 모두 해결할 수 있어, 가장 많이 사용됩니다.
Q. 정적 팩토리 메서드가 무엇이고, 왜 사용했는지 설명해주세요.
A. 정적 팩토리 메서드는 객체 생성 역할을 하는 static 메서드 입니다. new 키워드는 단순한 객체 생성만 할 수 있습니다. 하지만 정적 팩토리 메서드는 객체 생성 로직에 이름을 부여할 수 있고, 객체 생성에 특정 로직을 적용할 수 있습니다. 캐싱을 했을 경우, 캐싱되어있는 객체를 반환할 수 있습니다. 메서드 내부 로직을 통해 하위 자료형 객체를 반환할 수 있습니다.
단점은 정적 팩토리 메서드의 구체적인 내부 구현 방식을 모르는 사람이 사용할 때, 어떤 로직이 적용되었는지를 파악하기 위해 메서드 내부를 확인해야 한다는 점 입니다.
#Spring, #MVC, #Exception
Q. @ControllerAdvice 어노테이션이 무엇이고, @RestControllerAdvice 어노테이션과의 차이는 뭔가요?
A. @ControllerAdvice는 많은 Controller에서 발생하는 예외를 한 번에 잡아 처리해주는 어노테이션 입니다.
@ExceptionHandler 와 함께 쓰입니다.
@ControllerAdvice 에서 적용할 Controller의 범위를 지정할 수 있고, @ExceptionHandler 에서 잡을 예외를 지정할 수 있습니다.
별도의 지정 없이 사용하면, 모든 컨트롤러에서 발생하는 예외를 처리하게 됩니다.
@RestControllerAdvice 는 @ControllerAdvice 와 동일한 역할을 합니다. 차이점은, @ControllerAdvice 에 @ResponseBody 가 추가된 어노테이션이라는 점 입니다.
#HTTP, #REST, #API
Q. REST, REST API, RESTful이 각각 무엇이고, 차이점은 뭔가요?
A. REST는 HTTP URI(Uniform Resource Identifier)를 통해 자원(Resource)을 명시하고, HTTP Method(POST, GET, PUT, DELETE)를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것을 의미합니다. REST API는 REST를 기반으로 만들어진 API 입니다. RESTful은 REST API를 제공하는 웹 서비스를 지칭하는 말 입니다.
REST는 표준이 아니다.
RESTful한 API를 구현하는 근본적인 목적은 일관적인 컨벤션을 통한 API의 이해도 및 호환성을 높이는 것이다.
참조 : https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html
#HTTP, #Cookie
Q. 쿠키의 구체적인 동작 방식과, 세션과의 차이점을 말씀해 주세요.
A. 쿠키는 클라이언트 브라우저에 키와 값의 형태로 저장되는 데이터 입니다. 서버에서 응답 헤더에 쿠키 값을 설정하여 발급할 수 있습니다. 그러면, 해당 쿠키가 만료되기 전 까지 이후 요청 헤더에 자동으로 쿠키를 담아 전송합니다.
쿠키는 HTTP의 특징이자 약점인 connectionless, stateless의 약점을 보완하기 위해 사용됩니다.
세션은 쿠키를 기반하고 있습니다.
쿠키는 데이터를 클라이언트 브라우저에 저장하지만, 세션은 데이터를 서버에 저장하고, 쿠키에 세션 id를 담아 응답으로 보냅니다.
즉, 세션은 쿠키를 통해 세션id만 주고받습니다. 서버는 요청 쿠키에 있는 세션id로 서버 내에 저장되어있는 데이터를 찾아 비즈니스 로직을 처리합니다. 쿠키는 데이터를 브라우저에 저장하지만, 세션은 데이터를 서버 내에 저장하기 때문에 보안 면에서 세션이 쿠키보다 우수합니다. 하지만, 사용자가 많아질수록 서버 메모리를 많이 차지한다는 단점이 있습니다.
세션은 브라우저를 종료하면 만료기간에 상관없이 바로 삭제되지만, 쿠키는 브라우저를 종료하더라도 만료기간이 남아있으면 유지됩니다.
#보안, #Hash 암호화
Q. 암호화 방식들 중에 Hash 암호화를 사용한 이유가 뭔가요? 암호화의 방식과 장단점에 대해 말해주세요.
A. Hash는 단방향 암호화 기법입니다. 서비스에서 사용자 인증은 보안의 이유로 비밀번호 원문을 알 수 없도록 Hash 함수 같은 단방향 암호화 기법을 사용합니다.
Hash 암호화 기법은 비밀번호 원문을 해시 알고리즘을 이용해 고정된 길이의 암호화된 문자열로 바꾸는 방식입니다. 이 특징을 사용해 "인증" 과 "데이터 무결성 체크" 에 많이 사용됩니다.
단방향 암호화 방식이기 때문에, 복호화 할 수 없습니다.
Hash 알고리즘은 원문이 같으면 Hash 값도 같습니다.
하지만 Hash 값의 길이 조건이 제한되어있다면, 이 제약사항 때문에 다른 원문에 같은 Hash값이 나올 수 있습니다. 이 Hash값 충돌이 적게 나타날 수록 좋은 Hash 함수 입니다.
사용 권장되고있는 SHA-256
Hash 알고리즘을 사용했습니다.
서로 다른 원문이 SHA-256
알고리즘을 통해 같은 Hash값을 반환할 확률(Hash 충돌이 발생할 확률)은
1초 뒤에 행성 충돌로 지구가 멸망할 확률보다 45배 적습니다. 그만큼 충돌 저항성이 높습니다. 이에 따라 보안이 중요한 수많은 곳(블록체인, 금융권 등)에서 사용하고 있어, 저도 사용했습니다.