LSP(Liskov Substitution Principle - 리스코프 치환 원칙) 서브타입은 언제나 자신이 기반타입 (base type) (상위 타입) 으로 교체할 수 있어야 한다. S-O-L-I-D로 유명한 다섯가지 객체지향 설계 원칙중에서 LSP는 '상속'에 관한 지침을 이야기 합니다. 오리와 오리장난감 LSP를 설명하는 유명한 예제로 오리와 오리장난감이 있습니다. 오리와 오리장난감이 유사한 점이 있다고 오리장난감이 오리를 상속받게 되면 LSP를 위반하게 된다는 예제입니다. 왜냐하면 오리장난감은 배터리가 있어야 제대로된 동작을 하기 떄문입니다. 만약 오리를 기대하던 클라이언트(사용자)에게 오리 대신 오리장난감을 쥐어준다면, 클라이언트는 자신이 원하는 행동을 기대하기 어렵습니다. 오리장난감은 기반타..
방법1. 특정 컨트롤러나 요청에 대해서 Cross Origin 허용하기 @CrossOrigin 애노테이션 사용하기 @RestController @CrossOrigin(origins = "http://localhost:63342") //해당 origin 승인하기 @RequestMapping("/api/books") public class VocaTestApiController { ... } 방법2. 전역설정을 통해서 Cross Origin 허용하기 WebMvcConfigurer의 addCorsMappings 메소드 활용하기 import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.con..
※이 포스팅은 https://www.baeldung.com/spring-graphql 을 번역하고, 예제 코드와 내용을 각색한 포스팅입니다. 1. 개요 GraphQL은 REST API의 대안으로 Facebook에서 제시한 새로운 Web API 컨셉입니다. 이 포스팅에서는 스프링 부트(Spring Boot)를 사용하여 웹 애플리케이션에 GraphQL서버를 구축하는 방법을 소개하겠습니다. (개인적으로 사용한 예제는 스프링 부트 2.1.8버전, 자바 8버전, JPA를 사용하였습니다.) 2. GraphQL이 뭐지? 기존 REST API는 다양한 HTTP Method가 서버에 존재하는 리소스(Resource)와 대응되어서 동작합니다. 이는 클라이언트의 요청사항과 리소스(Resource)가 잘 들어맞지 않는다면 (..
EnumSet을 사용하는 방법 EnumSet은 다른 컬렉션들과 다르게 new 연산자 사용이 불가능합니다. EnumSet은 아래와 같은 방법으로 사용합니다. //DayOfWeek라는 Enum을 다루는 Set으로 비어있는 Set을 반환 EnumSet enumSet1 = EnumSet.noneOf(DayOfWeek.class); //모든 DayOfWeek Enum의 값을 담고있는 Set을 반환 EnumSet enumSet2 = EnumSet.allOf(DayOfWeek.class); 정적 팩토리 메소드(static factory method)만으로 EnumSet의 구현 객체를 반환받을 수 있습니다. 왜 이렇게 만든 걸까요? EnumSet 내부를 살펴보자 (아래 코드는 설명을 위해서 간소화한 코드입니다.) pu..
SQL 출력문을 반드시 확인하자. JPA에 익숙하지 않을때는 아무래도 구현하는 것에 더 집중하면서 실제 SQL 쿼리문이 어떤식으로 나오게 되는지 유심히 보지 못한 것이 사실이다. 이번 프로젝트에는 꼼꼼히 볼려고 노력해봤는데 SQL문을 확인해면 크게 2가지 문제가 있었다. 문제 1. 불필요한 Outer Join (optional 속성을 반드시 명시하자) 관계를 맞는 엔티티간의 관계가 반드시 존재하는지, 혹은 선택적인지에 따라 실제 두 테이블(도메인)을 조인하는 전략이 달라지는데, 만약 관계가 반드시 존재한다면 (= 테이블상의 FK가 반드시 존재한다면), optional 속성을 통해서 이를 명시해야한다. 그렇지 않다면 null인 경우도 대비해야 하기 떄문에 outer join이 발생한다. (+ 추가적으로 @..
Undefined? (null이랑 같은건가?) 자바스크립트에서는 (자바 같은 언어와 달리) 변수의 자료형을 별도로 표기하지 않고, 변수에 담기게 되는 값에 따라 자료형이 결정되게 됩니다. 이러한 특징때문에 undefined라는 상태를 다루게 되는데, 'undefined'라는 키워드는 해당 변수의 자료형이 정해지지 않았음을 나타냅니다. undefiend : 변수는 존재하나, 어떠한 값으로도 할당되지 않아 자료형이 정해지지(undefined) 않은 상태입니다. null : 변수는 존재하나, null 로 (값이) 할당된 상태. 즉 null은 자료형이 정해진(defined) 상태입니다. var var1; //undefined (어떤 값도 할당되지 않아서 자료형을 알 수 없음) var var2 = null; //..
동기(sync) vs 비동기(async), 블로킹 vs 논블로킹 사전적 의미는 일단 치워두고, 대조되는 개념들을 어떤 관점으로 봐야하는지 짧게 설명해보겠습니다. 동기 vs 비동기 : 처리해야 할 작업들을 어떠한 '흐름'으로 처리 할 것인가에 대한 관점 블로킹 vs 논블로킹 : 처리되어야 하는 (하나의) 작업이, 전체적인 작업 '흐름'을 막느냐 안막느냐에 대한 관점 이제 동기 vs 비동기, 블로킹 vs 논블로킹을 예제로 쉽게 설명해보겠습니다. 등장인물 개발팀장 : 개발팀 작업의 흐름을 조율하고, 개발팀 사원들에게 업무를 지시한다. 사원1, 사원2, 사원3 : 개발팀장이 지시한 일을 성실하게 수행한다. 시나리오1 (비동기 + 논블로킹) 개발팀장이 사원1에게 업무A를, 사원2에게 업무B를, 사원3에게 업무C를..
스프링 프레임워크에서 하나의 인터페이스 (혹은 상위 클래스)를 구현(상속)한 여러개의 빈이 존재하고, 그 빈들을 모두 다뤄야 하는 경우에 예제를 보겠습니다. 예제로 사용할 빈들은 다음과 같습니다. public interface Music { void playing(); } @Component public class Music1 implements Music{ @Override public void playing() { System.out.println("뮤직1의 흥겨운 노래"); } } @Component public class Music2 implements Music{ @Override public void playing() { System.out.println("뮤직2의 즐거운 노래"); } } @..