delpho

Java에 대하여 - 4 본문

CS

Java에 대하여 - 4

delpho 2022. 6. 10. 22:53

1. 강한 결합과 느슨한 결합이 무엇인지 설명해주세요.

 

 

# 의존성

  1. 어떤 클래스A가 다른 클래스(B) 또는 B의 인터페이스를 이용할때 A가 B에 의존한다고 한다.
  2. A는 B없이 작동할 수 없음
    • 여기서 A는 dependant / B는 dependency라고 함
    • dependant는 자신의 dependencies들에게 의존
  3. 의존성이 높다는건(강하다는건) A객체를 수정했을때, 그 객체와 결합된 B에서도 코드를 수정해야되는 경우가 생기는 것
  4. 이때, 두 클래스는 결합(coupled)되어 있음.
  5. 두 클래스 사이의 결합은 강할수도, 느슨할 수도 있음
    • 의존성이 강한지 약한지에 따라 달림
  6. 의존성, 결합은 방향이 존재
    • A가 B에게 의존한다고해서 B가 A에 꼭 의존적인것은 아님!

 

 

# 결합도

  • 서로 다른 모듈 간에 상호 의존하는 정도 또는 연관된 관계를 의미

 

 

# 의존도가 낮거나 결합도가 느슨할 경우

  • 요구사항 변화에 자유롭다.
  • 테스트 코드 작성에 유리하다.
  • 코드의 중복을 줄일 수 있다.

 

 

# 강한 결합

  • 어떠한 객체가 다른 객체에 강한 의존성을 가지고 있음
class SamsungTV {
	public void seeing() {
		System.out.println("냠냠");
	}
}

class People {
	SamsungTV c = new SamsungTV();

	public void startSeeing() {
		t.seeing();
	}
}
  1. People 클래스는 SamsungTV 클래스가 없으면 정의 못함
  2. SamsungTV 클래스를 다른 tv으로 바꾸게 되면 or 메소드를 바꾸게 되면 People 클래스의 코드가 대부분 변경됨

--> 유지보수 측면에서 문제

 

 

 

 

# 느슨한 결합

  • 결합되어있는 클래스간의 의존성을 약하게 만듬
  • 다형성, 디자인 패턴(팩토리) 이용
  • 다형성 이용
    • interface 이용 + 상속 (메서드 재정의)
    • 인터페이스를 이용함으로써 모든 TV 클래스가 같은 메소드들을 가질 수 밖에 없도록 강제할 수 있게 된것
    • 이 메인 클래스에서는 TV 인터페이스 타입의 변수로 SamsungTV 객체를 참조한다.
    • 이런 묵시적 형변환 (Promotion)을 이용해서 객체를 참조하게 되면 SamsungTV 를 LgTV 객체로 바꾸고 싶을 때,
      참조하는 객체만 변경하면 되기 때문에 객체를 바꾸는게 아주 쉬워짐
    • 수정이 최소화됨!

 

public interface TV {
	public void powerOn();
}

public class SamsungTV implements TV {

	public SamsungTV() {}

	@Override
	public void powerOn() {
		System.out.println("SamsungTV----전원 켠다.");
	}
}

public class LgTV implements TV {

	public LgTV() {}

	@Override
	public void powerOn() {
		System.out.println("LgTV----전원 켠다.");
}

public class TVuserPolymorphism {

	public static void main(String[] args) {
		TV tv = new SamsungTV();	
        // or TV tv = new LgTV();
		tv.powerOn();

	}
}
  • 디자인 패턴(팩토리) 이용
    • Factory 패턴은 사용할 객체 생성을 캡슐화 해서 TV.java 클래스와 TVuserPolymorphism.java 클래스 사이를 느슨한 결합 상태로 만들어줌
    • Factory 를 사용하면 인터페이스를 사용할 때 보다 결합도도 훨씬 낮아지고
    • TVuserPolymorphism 클래스 내부적으로 코드의 변경이 일어날 필요 없이, Factory를 통해 값을 전달하여 원하는 객체를 받아 사용 가능
public class BeanFactory {
	public BeanFactory() {}
	
	public Object getBean(String beanName) {
		if (beanName.equals("samsung")) {
			return new SamsungTV();
		} else {
			return new LgTV();
		}
	}
}

public class TVuserFactory {

	public static void main(String[] args) {
		BeanFactory factory = new BeanFactory();
		TV tv = (TV) factory.getBean("samsung");
		tv.powerOn();
	}
}

 

 

 



2. 직렬화와 역직렬화에 대해서 설명해주세요.

 

# 직렬화 역직렬화 필요성

  • 흔히 객체를 직렬화 한다 라는 표현을 사용
    • 즉, 데이터를 쓰거나 읽을 수 있게 지원하는 의미
  • 디스크로의 저장 or 네크워크로의 데이터 전송에서 많이 사용
  • 객체를 디스크에 저장하기 위해서

 

 

 

 

 

# 직렬화 (Serialization)

  • 자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 시스템에서도 사용할 수 있도록 연속적인 바이트 형태로 데이터 변환하는 기술
    • JVM의 메모리에 상주(힙 또는 스택)되어 있는 객체 데이터를 바이트 형태로 변환하는 기술
  • 객체들의 데이터를 연속적인 데이터로 변형하여 Stream을 통해 데이터를 읽도록 해줌
  • 주로 객체들을 통째로 파일로 저장하거나 전송하고 싶을 때 주로 사용

 

# 직렬화 과정

  1. 직렬화가 가능한 클래스에 implements Serializable 하기
    • 여러가지 상황에 따라 직렬 가능한 클래스와 데이터가 결정
      1. Serializable 인터페이스를 implements
      2. Serializable 없는 경우
        • 보통의 경우는 직렬화가 불가능
        • Serializable을 implement한 클래스를 상속받은 경우 직렬화 가능
      3. transient를 이용하여 직렬화 대상에서 제외
        •  보통 클래스의 멤버변수 전부 직렬화 대상에 해당
        • but 멤버변수의 일부를 제외하고 싶다면 transient를 통해 지정
      4. 다른 객체를 멤버변수로 가지고 있는 경우
        • Serializable 인터페이스를 구현한 클래스가 하나라도 없다면 직렬화불가

 

 

 

 

# 역직렬화 (Deserialization)

  • 바이트로 변환된 데이터를 다시 객체로 변환하는 기술
    • 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 기술
  • 직렬화된 파일 등을 역으로 직렬화하여 다시 객체의 형태로 만드는 것
  • 저장된 파일을 읽거나 전송된 스트림 데이터를 읽어 원래 객체의 형태로 복원

 

 

 

 

 

 



3. 자바의 동시성 이슈(공유자원 접근)에 대해 설명해주세요.

 

# 동시성 이슈란

  • 스레드 =  cpu 작업의 한단위
  • 멀티스레드 방식 = 멀티태스킹을 하는 방식 중, 한 코어에서 여러 스레드를 이용해서 작업을 처리하는 방식
  • 멀티 스레드를 이용하면  여러 스레드가 동시에 하나의 자원을 공유하고 있기 때문에 같은 자원을 두고 교착상태(deadlock) 같은 문제가 발생하는 것

 

# 동시서 제어 방법

1. 암시적 Lock (synchronized)

문제가 된 메서드, 변수에 synchronized 키워드 추가

 

2. 명시적 Lock

직접적으로 Lock 객체를 생성하여 사용

class Count {
    private int count = 0;
    private Lock lock = new ReentrantLock();
    public int view() {
            return count++;
    }
    public Lock getLock(){
        return lock;
    };
}

 

3. 스레드 안전한 객체 사용

  1. concurrent 패키지는 각종 스레드 안전한 컬랙션을 제공
  2. 불변 객체 사용

 

 

 

 

 



4. Mutable 객체와 Immutable 객체의 차이점에 대해 설명해주세요.

 

# Mutable 객체

  • 객체 생성 이후에도 객체의 속성이 변할 수 있음을 의미
  • 불변객체와 다르게 heap영역에 생성된 객체를 변경 가능
  • 대표적인 가변 객체는 List, ArrayList, HashMap,StringBuilder,StringBuffer 등
  • 가변객체를 multi-thread 환경에서 사용하려면 별도의 동기화 처리를 해줘야함
    • 동기화 처리된 객체중 하나가 StringBuffer
  • Java에선 객체가 참조를 통해 공유되기 때문에 어떤 스레드에서 객체의 값을 변경할지 모름
    • 그렇기 때문에 MUTABLE 객체는 자연스럽게 ‘thread-not-safe’ 

 

 

 

 

# Immutable 객체

  • 객체 생성 이후에 객체의 속성이 변할 수 없음을 의미
  • 힙 영역에 저장된 값을 수정할 수 없다
  • new 연산자로 객체를 생성하면 heap영역에 객체가 생기고 래퍼런스 값을 가지는 변수가 stack에 생길 것이다.
    • 오직 새 객체를 만들어 래퍼런스 값을 주는 재 할당만이 가능
String a = "Star";

a = a.concat("Craft");
  • StarCraft라는 새로운 객체를 만들어서 a에 재할당된 것
  • 대표적으로 String, Boolean, Integer, Float, Long 등이 있다
    • 객체이므로 String을 제외하면 primitive의 래퍼타입

 

 

# class 불변 객체 만들기

  • 클래스를 final로 선언 (클래스 상속 못하도록)
  • 모든 멤버변수를 private, final로 설정
  • setter 메서드를 구현 X
  • 객체 생성을 위해 static 팩토리 메소드 제공 (기본생성자가 아닌 팩토리 메소드를통해 객체 생성 강요)
  • 멤버변수 중 가변객체타입의 field 변수가 있을 경우, 그 가변객체 타입의 field변수에 대해 직접적으로 접근하지 못하도록 copy 객체를 생성하여 새로운 인스턴스를 반환하도록 방어적 복사본 전략을 사용

 

# 불변 객체 장단점

  • 장점
    1. 객체에 대한 신뢰도가 올라간다.
    2. multi-thread 환경에서 동기화 처리 없이 객체를 공유 가능하다.(쓰레드에 안전하다 라고함)
  • 단점
    1. 객체의 값이 할당될 때 마다 새로운 객체가 필요하다. 따라서 메모리 누수와 성능저하를 발생시킬 수 있다.

 

 

 

 

# Mutable vs Immutable

생성된 이후 수정 가능 생성된 이후 수정 불가능
이미 존재하는 객체에 재할당(값 변경) 이미 존재하는 객체이더라도 새로운 객체를 생성하여 재할당
값을 변경할 수 있는 메소드 제공 값을 변경할 수 있는 메소드 제공 x
Mutable class일 경우 Getter와 Setter 존재 Immutable class일 경우 Getter와 Setter 미존재
thread safe하지 않을 수 있음(병렬처리 시 값 보장할 수 없게 됨) thread safe(병렬처리 시 문제 없음)
StringBuffer, StringBuilder, java.util.Date 등이 해당 Legacy classes, Wrapper classes, String class 등이 해당

 

 

 

 



5. 자바에서 null을 안전하게 다루는 방법에 대해 설명해주세요.

 

# null 이란

  • 객체가 없거나 상태가 정의되지 않은 상태

 

# null 참조

  • 특별한 값이 없음을 나타내려고 null을 도입했고 이 값을 사용하려고 할 때 오류를 내도록 설계
  • 두 참조값이 null일 때 두 참조는 동일하다고 판단
  • null은 모든 타입의 멤버가 될 수 있음
    • 참조 변수 사용 시 널을 확인해야 함

 

# null과 관련된 문제

  1. 런타임에 NPE(NullPointerException)라는 예외를 발생시킬 수 있습니다.
  2. NPE 방어를 위해서 들어간 null 체크 로직 때문에 코드 가독성과 유지 보수성이 떨어집니다.

 

 

# null을 안전하게 다루는 방법

  1. @NonNullApi를 패키지 레벨에 선언
    • 패키지 하위의 class method의 인자 또는 리턴이 null일 경우 IDE에서 Warning으로 알려줌
  2. @NotNull 이나 @Nullable 어노테이션을 사용
    • 메소드가 null safe인지 아닌지를 annotation을 사용하여 표시하는 것이 좋다.
    • 그래야 컴파일러가 여러분이 미처 확인하지 못 한 또는 굳이 확인할 필요가 없는 부분에서 null check를 하도록 도와줄 수 있다.
  3. Optional 클래스 사용
    •  “존재할 수도 있지만 안 할 수도 있는 객체”, 즉, “null이 될 수도 있는 객체”을 감싸고 있는 일종의 래퍼 클래스
      • 직접 다루기에 위험하고 까다로운 null을 담을 수 있는 특수한 그릇
    • Optional 장점
      1. NPE를 유발할 수 있는 null을 직접 다루지 않아도 됩니다.
      2. 수고롭게 null 체크를 직접 하지 않아도 됩니다.
      3. 명시적으로 해당 변수가 null일 수도 있다는 가능성을 표현할 수 있습니다. (따라서 불필요한 방어 로직을 줄일 수 있습니다.)

 

 

 

 


출처

https://velog.io/@huttels/%EC%9D%98%EC%A1%B4%EC%84%B1%EC%9D%B4%EB%9E%80

 

의존성이란

어떤 클래스A가 다른 클래스 또는 인터페이스B를 이용할때 A가 B에 의존한다고 한다.A는 B없이 작동할 수 없고 B를 재사용하지 않으면 A또한 재사용할 수 없다.이러한 상황에서 클래스A를 dependant

velog.io

https://madplay.github.io/post/coupling-and-cohesion-in-software-engineering

 

결합도와 응집도는 무엇일까?

낮은 결합도(Coupling)와 높은 응집도(Cohesion)를 갖도록 설계해야 하는 이유는 무엇일까?

madplay.github.io

https://ecsimsw.tistory.com/entry/%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85%EA%B3%BC-%EB%B3%80%EA%B2%BD%EC%9D%98-%EC%9C%A0%EC%97%B0%ED%95%A8

 

의존성이란

의존성이란 나는 의존성 주입이라는 단어를 스프링을 공부하면서 처음 들었다. '컨테이너에서 관리될 객체를 지정해주고, 주입 받을 위치를 표시해주면 마법같은 일이 일어나 해당 객체가 들어

www.blog.ecsimsw.com

https://velog.io/@damiano1027/Java-%EA%B0%95%ED%95%9C-%EA%B2%B0%ED%95%A9%EA%B3%BC-%EC%95%BD%ED%95%9C-%EA%B2%B0%ED%95%A9

 

[Java] 강한 결합과 약한 결합

객체의 의존 관계에서 강한 결합이란, 어떠한 객체가 다른 객체에 강한 의존성을 가지고 있음을 뜻한다.그렇다면 의존성을 가지고 있다는 것이 무엇인가?의존성이 강하다는 것은 무엇인가?에

velog.io

https://swk3169.tistory.com/185

 

Coupling이란? Tight Coupling vs Loose Coupling 정리

- Coupling의 정의 coupling이란 서로 상호작용하는 시스템들간의 의존성을 의미한다. 의존성은 실질적 의존성과 인위적 의존성으로 나뉠 수 있다. 실질적 의존성은 한 시스템이 소비하는 다른 시스

swk3169.tistory.com

https://flowarc.tistory.com/entry/Java-%EA%B0%9D%EC%B2%B4-%EC%A7%81%EB%A0%AC%ED%99%94Serialization-%EC%99%80-%EC%97%AD%EC%A7%81%EB%A0%AC%ED%99%94Deserialization

 

Java 객체 직렬화(Serialization) 와 역직렬화(Deserialization)

Java의 직렬화와 역직렬화에 대해서 알아봅시다. 정의 Java에서 말하는 직렬화(Serialization)란 과연 뭘까? 말그대로 객체를 직렬화하여 전송 가능한 형태로 만드는 것을 의미한다. 객체들의 데이터

flowarc.tistory.com

https://hanbulkr.tistory.com/14

 

직렬화(Serialization)와 역직렬화(Deserialization)

개요 객체를 디스크에 저장하기 위해서는 반드시 Serialize의 개념을 알고 있어야 한다. 흔히 객체를 직렬화 한다 라는 표현을 사용합니다. 즉, 데이터를 쓰거나 읽을 수 있게 지원하는 의미로 개

hanbulkr.tistory.com

https://steady-coding.tistory.com/576

 

[Java] 직렬화와 역직렬화

java-study에서 스터디를 진행하고 있습니다. 데이터 직렬화와 역직렬화 데이터 직렬화 메모리를 디스크에 저장하거나, 네트워크 통신에 사용하기 위한 형식으로 변환하는 것이다. 데이터 역직렬

steady-coding.tistory.com

https://codevang.tistory.com/164

 

직렬화와 역직렬화 (Serializable)

[ 직렬화 ] 자바의 객체를 외부 데이터로 저장하는 것 객체화된 클래스(인스턴스)의 속성과 데이터를 파일화하여 외부에 저장할 수 있음 [ 역직렬화 ] 직렬화로 저장된 파일을 다시 자바의 객체

codevang.tistory.com

 

https://cantcoding.tistory.com/41

 

Immutable,mutable 객체

자바의 객체의 타입에는 Immutable 타입과 mutable타입이 있다. 객체들은 기본적으로 heap영역에 할당되고 stack영역에 래퍼런스 값을 갖는 참조 변수들로 접근 가능하다. immutable(불변) 객체 이름에서

cantcoding.tistory.com

https://choiblack.tistory.com/47

 

[Java] Mutable과 Immutable

자바의 객체는 기본적으로 힙 영역에 할당되고 스택 영역에 참조값을 갖는 참조 타입 변수를 통해 데이터에 접근한다. 이러한 객체는 Mutable(가변) 객체와 Immutable(불변) 객체로 나눌 수 있다. Immut

choiblack.tistory.com

https://velog.io/@guswlsapdlf/Java%EC%9D%98-Mutable%EA%B3%BC-Immutable

 

Java의 Mutable과 Immutable

정리하면 Mutable은 객체의 수정을 허용하나, Immutable인 경우 객체의 수정을 허용하지 않는다. 수정이 필요할 경우 Mutable 객체는 기존의 객체에 수정사항을 곧바로 반영한다. 하지만 Immutable 객체의

velog.io

https://www.daleseo.com/java8-optional-after/

 

자바8 Optional 2부: null을 대하는 새로운 방법

Engineering Blog by Dale Seo

www.daleseo.com

https://eastglow.github.io/back-end/2020/01/10/Java-%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-null%EC%9D%84-%EC%95%88%EC%A0%84%ED%95%98%EA%B2%8C-%EB%8B%A4%EB%A3%A8%EB%8A%94-%EB%B0%A9%EB%B2%95.html

 

Full of Troves, Blog

초보 개발자의 블로그

eastglow.github.io

https://ncucu.me/192

 

Java 에서 널을 안전하게 다루기

null 과 null 로 인해 발생하는 문제 null pointer 와 null reference 널 포인터(null pointer)는 유효한 객체를 참조하지 않는 포인터를 나타내기 위해 예약된 값을 갖는다. 널 포인터는 널 값과는 다른 의미를

ncucu.me

https://velog.io/@mooh2jj/%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%98-%EB%8F%99%EC%8B%9C%EC%84%B1-%EC%9D%B4%EC%8A%88

 

'CS' 카테고리의 다른 글

DB에 대하여 - 1  (0) 2022.06.19
Spring에 대하여 - 5  (0) 2022.06.19
Java에 대하여 - 3  (0) 2022.06.10
Java에 대하여 - 2  (0) 2022.06.08
Java에 대하여 - 1  (0) 2022.06.08