2021 04 12
2021-04-12¶
체스 최종 피드백¶
- 동시에 게임을 진행하는 것? - ex. 게임 1은 player A/B가, 게임 2는 player C/D가 진행한다고 생각하자 - 우선 프론트에서 새로운 방 만들기 버튼을 누르겠지? - 그러면 기존 DB를 참조해서 현재 game_id에 +1 한 숫자를 반환하겠지? - 해당 game_id + 1을 통해 url로 /1 같이 표시를 나타내 주자 - 그러면 동시에 게임 1과 게임 2에서 move 명령을 준다고 하면, - ChessGameDAO에서 move를 처리하자 - 각각 고유의 체스게임을 불러오고 move를 처리하기에 문제가 없을듯? - 각자 thread에 스택이 쌓이고 거기에서 move를 처리하니까?
- 웨지와 함께한 웹 얘기
> 웹 서버(Apache)와 웹 애플리케이션 서버(tomcat)에 대해 책에서 언급하는데 아직 웹 애플리케이션 서버에 대해 감이 잘 안잡혀요.
웹 서버는 HTTP 요청을 받아 정적 자원을 반환하는 것에 집중하고,
웹 애플리케이션은 동적인 페이지 생성을 위한 DB 연동등의 작업을 수행한다고 읽었어요.
하지만 웹 애플리케이션 서버와 웹 프레임워크의 차이를 아직은 잘 모르겠고요. 레벨 2에서 차차 공부해 나가면 될 것 같아요!- 웹 프레임워크: HTTP 요청을 해석(웹 서버 역할) + 자바 코드와 연결(WAS의 역할) 을 제공하는 웹 애플리케이션을 만들 수 있도록 도와주는 라이브러리 - 웹 애플리케이션 서버: 자바 코드와의 연결 및 다양한 기능을 분리하여 아예 프로그램으로 만든 것 (tomcat 등)
- 체스 코드들 중 스파크 코드를 제외하고 "WAR" 이라는 압축파일로 만들어서,
WAS 내부 디렉토리에 넣어주고 실행하면,
웹 서버가 주는 요청을 받아 WAR 코드를 해석하여 html 파일로 만들어 웹 서버에 반환.- WAR - Web Archive의 약자로, 웹 앱 압축/배포 할 때 사용. - WAR는 자바 클래스, 자바 서버 페이지, XML, JS, 정적 웹 페이지등의 자원을 모아 웹 앱의 배포를 가능케 함 - web.xml이라는 배포 서술자를 통해 경로를 지정해줘야 웹 애플리케이션 서버가 WAR를 실행할 수 있음
테코톡 복습¶
- SPA - MPA(Multi-Page Application) && SSR(Server-Side Rendering) - 장점: 검색엔진 최적화에 유리함 / 빠른 초기 로딩 속도 - 단점: 불편한 UX / 서버 부하가 큼 - SPA(Single-Page Application) && CSR(Client-Side Rendering) - 장점: 빠른 속도 / 서버 부하 줄어 듦 - 단점: 검색 엔진 최적화에 불리 / 느린 초기 로딩 속도
- Singleton과 정적 클래스
- Singleton: 클래스의 인스턴스를 하나만 생성하고, 어디서든 그 인스턴스를 참조하도록 하는 패턴
- 장점
- 고정된 메모리 영역을 가지기에 메모리 낭비 X
- Singleton Class의 instance는 전역이기에 다른 클래스의 instance들과 데이터 공유가 쉽다
- DBCP(DataBase Connection Pool)처럼 공통된 객체를 여러개 생성해야 하는 상황에 많이 사용
- 생성 방법
1. Eager initialization
- private static Class instance = new Class();
- 클라이언트에서 사용하지 않더라도 인스턴스 항시 생성... 굳이 메모리 차지
- 예외 처리 할 수 있는 방법 X
- Static block 안에서 해주자 -> Static block initialization
2. Lazy initialization
- getInstance() 호출 외에는 인스턴스 생성 X
- Object.isNull -> 새로이 생성
- Eager init 단점 보완
- thread safe X
3. Thread safe initialization
- synchronized 예약어를 통해 하나의 예약어만 쓰자
4. Double-Checked Locking
- Object.isNull 일때 synchronized를 실행
5. Bill Pugh Solution
public class BillPughSingleton { private BillPughSingleton() { } private static class SingletonHelper { private static final BillPughSingleton INSTANCE = new BillPughSingleton(); } public static BillPughSingleton getInstance() { return SingletonHelper.INSTANCE; } }- Lazy Loading 가능 - Thread Safe- 정적 클래스: 모든 메소드가 static인 클래스 - 장점 - 상태 안가지고, global access 제공시 유용 - Static은 컴파일 때 static binding으로 싱글턴 보다 조금 더 빠름 - Static variable - 메모리에 고정적으로 할당되어, 프로그램이 종료될 때 해제되는 변수 - Static method - 객체 생성 없이 메서드 호출 바로 가능 - 객체 생성 없이 접근하는 메서드라, static이 아닌 변수 사용 X - Inner Class - 외부 클래스는 내부 클래스를 멤버 변수처럼 사용 - 내부 클래스는 외부 클래스의 자원 사용가능 - 내/외부 클래스 간의 강한 결합 - 내부 클래스 역할 끝나도 GC가 못지워 - Static class - 외부 클래스의 자원 중 static이 붙은 것만 사용이 가능하다!
public class OuterClass { private static String croffle = "Croffle"; private String waffle = "Waffle"; static class Inner { public void printName() { System.out.println(croffle); //정상 동작 System.out.println(waffle); //오류! } } }- 싱글턴은 OOP인가? - 상태를 가진다면, 어려 쓰레드에서 접근하여 상태를 바꾸면 큰일남 - 상태 없는 객체나, 설계상 유일해야 하는 시스템 컴포넌트를 싱글턴으로 구현하자
- Stream
- 정의
- 모던 자바: Data 처리 연산을 지원하도록 소스에서 추출된 연속된 값 요소
- 이것이자바다: Collection 요소를 하나씩 참조해 Lambda 식으로 처리할 수 있는 반복자
- 장점
- How 중심의 코드를 What 중심의 코드로 변경
- 연산에 필요한 매개변수 X
- 내부 반복 --> 외부 반복
- 자료구조가 포함하는 모든 값을 메서드에 포함하는 컬렉션과 다르게, 스트림은 요청할 때만 요소를 계산하는 고정된 자료구조를 가진다
- 스트림은 여러 개의 조건이 중첩된 상황에서 값이 결정나면 불필요한 연산을 진행하지 않고, 조건문을 빠져나와 실행 속도를 높인다
- 사용법
- 스트림 생성 --> 중간 연산 --> 최종 연산
- flatMap
- Collection이 중첩된 경우 사용
List<Fish> manyFish = fishes.stream() .map(Net::getFishes) .flatMap(List::stream) .collect(Collectors.toList());- reduce - 요소를 하나씩 가져와서 람다식 처리 - 스트림의 요소는 소모된다!
Optional¶
- 참고 1: https://www.daleseo.com/java8-optional-after/
- 참고 2: https://www.daleseo.com/java8-optional-effective/
- 정의 - "존재할 수도 있지만, 안할 수도 있는 객체" - "null이 될 수도 있는 객체"를 감싸고 있는 일종의 래퍼 클래스 - 원소가 없거나, 최대 하나밖에 없는 Collection이나 Stream
- Optional 객체 생성 - Optional.empty() - null을 담고 있는 Optional 객체 - 비어있는 Optional 객체를 생성 - Optional.of(value) - null이 아닌 객체를 담고 있는 Optional 객체 - null오면 NPE 던짐 - Optional.ofNullable(value) - null인지 아닌지 확인할 수 없는 객체 생성
- Optional 객체 접근하기 - get() - orElse(T other) - orElseGet(Supplier<? extends T> other) - orElseThrow(Supplier<? extends X> exceptionSupplier) - 기존에 조건문으로 null을 대하던 생각을 "함수형 사고"로 바꿀 것
- Optional 적용하기
- null-safe한 코드 작성
public String getCityOfMemberFromOrder(Order order) { return Optional.ofNullable(order) .map(Order::getMember) .map(Member::getAddress) .map(Address::getCity) .orElse("Seoul"); }Map<Integer, String> cities = new HashMap<>(); cities.put(1, "Seoul"); cities.put(2, "Busan"); cities.put(3, "Daejeon"); String city = cities.get(4); // returns null int length = city == null ? 0 : city.length(); // null check System.out.println(length); Optional<String> maybeCity = Optional.ofNullable(cities.get(4)); // Optional int length = maybeCity.map(String::length).orElse(0); // null-safe System.out.println("length: " + length);