본문 바로가기

STUDY

(102)
5-6) 제네릭과 가변인수를 함께 쓸 때는 신중하라 제네릭과 가변인수 // 제네릭과 가변인수를 함께 사용하면 컴파일러가 경고를 보낸다 // Type safety: Potential heap pollution via varargs parameter stringList public static void myFunc(List... stringLists) List intList = List.of(1); Object[] objects = stringLists; objects[0] = intList; // 힙 오염 발생 String s = stringLists[0].get(0); // ClassCastException 런타임 에러 발생 } 가변인수와 제네릭은 자바5때 함께 추가되었으나 함께 사용하기에는 까다롭다. 제네릭과 가변인수를 함게 사용하면 컴파일러는 힙 오염..
5-5) 한정적 와일드카드를 사용해 유연성을 높혀라 매개변수화 타입의 불공변성 // Integer 타입은 Number 타입을 상속했기때문에, num = intNum가 가능하다. Number num = 1; Integer intNum = 1; num = intNum; // Integer 타입은 Number 타입을 상속했지만, 매개변수 타입으로 전달되었을때는 그 관계가 유지되지 않는다. // 따라서 numStack = intStack 코드는 컴파일 에러가 발생한다. Stack numStack = new Stack(); Stack intStack = new Stack(); numStack = intStack; 매개변수화 타입은 불공변이다. 불공변이라는 말은 타입의 관계가 같이 변하지 않는다는 것을 말한다. 위의 코드를 보면 Integer 타입은 Number 타..
5-4) 이왕이면 제네릭 타입으로 만들라 Object 기반 Stack public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { this.elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { this.ensureCapacity(); this.elements[this.size++] = e; } public Object pop() { if(this.size == 0) { throw new EmptyStackException(); } Object result = thi..
5-3) 배열보다는 리스트를 사용하라 배열과 제네릭의 차이 // 컴파일 에러가 발생하지 않는다. Object[] objectArray = new String[1]; // 컴파일 에러가 발생한다. List objectList = new ArrayList() 배열에서는 Sub가 Super의 하위 타입이라면 Sub[]는 Super[]의 하위타입이 된다. 리스트에서는 List가 List의 하위타입이 아니다. 따라서 위의 코드를 보면 배열에서는 가능한 코드가 리스트에서는 컴파일 에러가 발생한다. 배열이 더 유연한 코드를 제공하는거 같지만 실제로는 위험한 코드를 허용해주는 것이다. 배열의 저러한 특성때문에 아래의 코드같이 런타임에 문제가 생길 수 있다. // 런타임에서 발생 Object[] objectArray = new String[1]; objec..
5-2) 비검사 경고를 제거하라 비검사 경고 //비검사 형변환 경고 발생 Set nameSet = new HashSet(); //타입 매개변수를 명시하여 비검사 형변환 경고 제거 Set nameSet = new HashSet(); 제네릭을 사용하기 시작하면 많은 컴파일러 경고를 보게 될 것이다. 위의 코드에서는 보면 Set타입의 변수에 HashSet 객체를 넣으려고 하자 비검사 형변환 경고가 발생했다. HashSet에 타입 파라미터가 없으므로 어떤 타입이 들어갈 지 알 수 없으므로, 런타임에 형변환 문제가 발생 할 수 있다는걸 경고한 것이다. 이는 실제로 위험한 코드이기 때문에 타입 파라미터를 명시하여 비검사 형변환 경고를 제거해주어야 한다. @SuppressWarnings @SuppressWarnings("unchecked") pub..
8. 도커 데이터 관리3: 볼륨 관리 읽기 전용 볼륨 > docker run --name feedback-app -p 3000:80 --rm -v ${pwd}:/app:ro -v /app/node_modules -v feedback:/app/feedback -v /app/temp feedback-app 개발상의 편의를 위해 컨테이너와 호스트를 바인드 마운트로 연결할 수 있다. 호스트에서 소스를 편집한 내용이 컨테이너에 바로 반영되므로 개발 속도가 빨라진다. 이 경우에 호스트의 변경내용만 컨테이너로 전달되면 충분하다. 반대로 컨테이너에서 소스가 수정되어 호스트에 반영되는것은 문제가 될 수 있다. 이때 사용할 수 있는게 읽기전용 볼륨이다. -v로 정의한 볼륨 뒤에 :ro를 붙여주면 된다. 그리고 읽기전용으로 정의된 경로 하위에 컨테이너에서 쓰기..
7. 도커 데이터 관리2: 익명 볼륨, 지명된 볼륨, 바인드 마운트 도커 볼륨의 종류 도커 볼륨은 익명볼륨, 지명된 볼륨, 바인드 마운트 볼륨 3가지가 존재한다. 익명 볼륨은 -v {컨테이너 폴더 경로} 옵션으로 컨테이너를 실행하면 만들어진다. 볼륨으로 지정된 컨테이너 경로에 파일이 저장하려고 하면 컨테이너가 아니라 연결된 로컬 파일시스템에 해당 파일이 저장된다. 도커가 컨테이너의 폴더와 로컬 폴더를 연결하기때문에 개발자는 로컬 폴더가 어디인지는 알 수 없다. 또 컨테이너가 사라지면 해당 익명볼륨도 함께 사라진다. 지명된 볼륨은 -v {볼륨 이름}:{컨테이너 폴더 경로} 옵션으로 컨테이너를 실행하면 만들어진다. 익명 볼륨과 마찬가지로 컨테이너의 폴더와 로컬 폴더가 맵핑되고 개발자는 자세한 로컬 폴더의 위치를 알 수 없다. 하지만 컨테이너를 삭제해도 볼륨은 삭제되지않기 때..
6. 도커 데이터 관리1: 데이터 종류와 볼륨 데이터의 종류 서비스를 운영할 때 사용하는 데이터는 3개로 구분할 수 있다. 먼저 어플리케이션 데이터는 어플리케이션의 소스파일이나 실행파일, 실행을 위해 필요한 패키지 파일, 환경 설정 파일 등 어플리케이션 실행에 필요한 데이터를 말한다. 이러한 데이터들은 빌드할 때 도커 이미지에 포함시키는 것이 일반적이다. 그리고 도커 이미지는 읽기전용이므로 빌드된 이후 변경되지 않는다. 즉 어플리케이션 데이터는 이미지에 읽기전용으로 저장된다. 다음으로 임시데이터는 어플리케이션이 실행되는동안만 사용되는 데이터를 말한다. 사용자의 요청을 처리하는 동안 만들어지는 임시 파일을 예로 들 수 있다. 이러한 데이터는 컨테이너의 메모리나 파일시스템에 저장되고 컨테이너가 종료되면 사라진다. 즉 임시데이터는 컨테이너에 저장되고 읽기..