전체 글 361

Java 8 - Stream이란? (+ ParallelStream)

Stream 자바 8에서 추가된 스트림(Streams)은 컬렉션, 배열 등에 저장된 요소들을 하나씩 참조하면서 코드를 실행할 수 있는 기능입니다. Stream을 사용하면, 불필요한 for문을 사용하지 않을 수 있고, 람다식을 활용할 수 있어서 코드를 직관적이게 처리할 수 있습니다. [참고] Stream은 아래와 같은 특징들이 있습니다. Stream은 데이터를 담는 저장소는 아니다. Stream은 데이터를 변경하지 않는다. Stream은 재사용할 수 없다. Stream은 각 요소가 1번씩 처리된다. Stream은 무제한일 수도 있다. (실시간으로 계속 들어올 수 있음) Stream API 사용법 Stream API는 데이터.Stream생성().중개연산()...종료연산(); 구조로 사용합니다. Stream..

Language/Java 2022.03.11

Java 8 - 인터페이스의 default method, static method 사용!

자바8 버전부터는 인터페이스에서 Default method와 Static method를 사용할 수 있습니다. 개인적으로는 클래스랑 인터페이스의 경계가 조금 허물어지는게 아닌가.. 하고 조금 의아하기도 했습니다. 하나씩 살펴봅시다. Default method 기본 메소드(default method)는 interface에서 메서드 내용을 정의하고, 그대로 재사용할 수 있게 해줍니다. public interface Printer { String getName(); default void printNameUpperCase() { System.out.println(getName().toUpperCase()); } } public class HoneyPrinter implements Printer { @Overri..

Language/Java 2022.03.09

Java - 람다(Lambda)의 멀티 쓰레드(multi-thread) [외부 변수를 final만 허용하는 이유]

람다와 final ? 아래의 코드는 람다식을 사용한 코드입니다. public static void main(String[] args) { int num = 10; Runnable printNum = () -> System.out.println(num); } 위코드는 문제 없이 실행됩니다. 그런데 아래 코드를 보시면 num++; 한 줄 추가했을 뿐인데, 컴파일 에러가 납니다. 에러가 나는 이유는 Java8 람다에는 외부 지역 변수가 final이어야 한다는 조건이 있기 때문입니다. Q. 엥? 그런데 첫 번째 코드에서는 final이 없는데 에러가 왜 안났지? -> 이유는 num변수는 현재 effectively final이기 때문입니다. 변수가 초기화되고 값의 변화가 한 번도 없다면, 컴파일러에서는 해당 변수를..

Language/Java 2022.03.09

Java 8 - 함수형 인터페이스를 사용하는 방법!

함수형 인터페이스 함수형 인터페이스는 1개의 추상 메소드를 갖는 인터페이스를 말합니다. 함수형 인터페이스는 함수형 프로그래밍에 주로 사용하고, 꼭 함수형 프로그래밍이 아니더라도 적용할 수 있습니다. Q. 함수형 인터페이스를 왜 사용할까? A. 자료뿐만 아니라 행위(함수)도 하나의 값으로 취급하기 위함입니다. 함수를 하나의 값으로 취급해서, 함수들을 조립하고 배치하면서 개발하기 위해 함수형 인터페이스를 사용합니다. 구현 An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface as defined by the Java Language Specif..

Language/Java 2022.03.05

메일 서비스 작동 원리 (with 구글, 네이버 등)

메일 작동 원리메일을 전송하고 전송 받을 때 사용하는 프로토콜은 크게 3가지로 나눌 수 있습니다.SMTP: 메일을 송신할 때 사용하는 프로토콜TCP/IP 호스트 사이의 메일을 전달할 때 사용됨POP3: 메일을 전송받을 때 사용하는 프로토콜POP3는 로컬에서 수정, 삭제를 해도 메일 서버에는 변화가 없음.메일을 수신할 때는 주로 POP3, IMAP을 사용.IMAP: 메일을 전송받을 때 사용되는 또 하나의 프로토콜IMAP은 POP3의 단점의 비동기성을 보완하기 위한 방식각 로컬마다 데이터가 다르지 않고 어떤 디바이스에서 메일을 열든 동일하게 동기화하는 방식복잡하다는 단점이 있음.기본 메일 서버의 동작 구조는 아래와 같습니다. abc@abc.com 사용자가 메일서버에게 MUA(Mail user agent ex..

Operation/Network 2022.03.05

Java - 참조(reference) 객체가 아닌 값(value) 객체 사용하는 방법

Reference Object vs Value Object 기본적으로 객체는 참조 객체(Reference Object)를 많이 사용합니다. 하지만 값 객체(Value Object)를 사용하면 해결할 수 있는 문제도 많고, 적합한 경우도 아주 많습니다. 그래서, 참조 객체와 값 객체를 사용하는 기준과 사용하는 방법에 대해 다루겠습니다. 선택 기준 가장 중요한 기준은 mutable(가변) vs immutable(불변) 입니다. 내부에 있는 값을 바꾸면서 사용해야 하고, 변경된 값을 여러 곳에서 사용해야 한다면 Reference Object를 사용하고 그렇지 않은 경우 Value Object입니다. 두 번째 기준은 객체의 고유성을 어떻게 판단할 지 입니다. 이해가 어려우실 것 같아 코드로 가져왔습니다. cla..

Language/Java 2022.03.05

Docker Apache에 HTTPS(SSL) 적용하기 [+HTTP, HTTPS 간 쿠키 전송안될 때]

상황 로컬(Docker)에 올린 기존 시스템에서 다른 API(다른 도메인)로 Request 시 withCredential을 true로 설정해줘야 함 이후, 요청은 성공을 했지만 Cookie(세션 정보)가 전달이 안되는 현상이 발생했음. 로컬에 올린 시스템은 HTTP고 요청을 받는 API는 HTTPS이기 때문에 발생 -> 규정 변경으로 HTTP, HTTPS 간 통신은 쿠키를 전송할 수 없음 (원래는 HTTPS -> HTTP만 안됬음) 따라서, 로컬의 Apache에 인증서를 설치해줘야 했음. 소개 이번 포스팅에서 사용하는 방법은 자가 서명된 인증서를 발급해서 사용하기 때문에 도메인으로 등록하지 않아도 상관없고, 로컬(개발) 환경이어도 상관없습니다. 컨테이너를 생성할 때도 포트를 HTTP, HTTPS 두 개 ..

Operation/Network 2022.03.02

Jest - 테스트 코드간 충돌, 간섭 막는 방법 (매번 테스트 결과가 다를 때 해결 방법!)

테스트 코드 충돌 (간섭) 사내에서 jest + supertest를 이용해서 테스트 코드를 작성하고 있었습니다. 그런데, 자꾸 테스트를 돌릴 때마다 한 번씩 테스트가 깨지는 현상이 발생했습니다. 알고보니 테스트 코드 파일 A가 다른 테스트 코드 파일 B랑 비동기로 실행되다 보니까 서로 간섭하는 현상이 생기는 것이었습니다. 상황 충돌을 일으킨 테스트 2가지는 아래와 같습니다. 카테고리 MVC 테스트 상품 MVC 테스트 프로젝트 구조가 상품 등록 API를 테스트할 때는 먼저 카테고리를 생성한 후에 상품 등록 API에 요청을 보내는 구조였습니다. 상품 등록 API는 등록할 카테고리의 id를 받아서, 해당 카테고리가 없으면 예외가 발생하기 때문에 그렇게 설계했습니다. 카테고리 MVC 테스트는 각 테스트가 실행될..

Server/Node.js 2022.02.28

리팩토링 - Switch문을 다형성으로 바꾸기

조건문을 다형성으로 바꾸기 (Replace conditional with polymorphism) 모든 조건문을 다형성으로 바꿔야 좋은 것은 아닙니다. 여러 타입에 따라 각기 다른 로직으로 처리해야 할 경우에 조건문을 다형성으로 만들 수 있습니다. 공통으로 사용되는 로직은 상위클래스에 두고, 코드 변경의 여지가 있는 달라지는 부분만 하위 클래스에 둠으로써 가독성과 유지보수성을 얻는 것입니다 ! 예제 아래의 코드를 보면, printerMode라는 멤버 변수의 값에 따라 switch문에서 각기 다른 로직을 적용하게 됩니다. 각 조건마다 적지 않은 코드가 실행되고, 메서드 호출도 있고, 각각의 하위 메서드도 하나의 클래스에 전부 있는 상태입니다. public class Printer { private int ..

리팩토링 - 반복문 분리 (split loop)

반복문 분리 레거시 코드를 보면 하나의 반복문에서 여러 다른 작업을 수행하는 코드를 쉽게 찾을 수 있습니다. 하지만, 그렇게 되면 반복문 안의 하나의 작업을 수정하는 데도 다른 작업까지 고려해야 하는 상황이 발생합니다. 반복문을 작업별로 분리하면 쉽게 이해하고 유지보수할 수 있습니다. 예시 아래의 예제는 두 가지 작업을 하고 있습니다. 그럼에도 이렇게 짜는 이유는 우리는 반복문의 범위가 동일하다면 굳이 분리하지 않기 때문입니다. Date firstCreatedAt = null; Participant first = null; for (Comment comment: comments) { Participant participant = findParticipant(comment.getUserName(), par..