DO SOPT 1차 세미나 생각 과제

dev-jjun·2024년 1월 29일
0

Server

목록 보기
29/33
post-thumbnail

#Java Generic

Generic Programming이란?

데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입을 가질 수 있는 기술에 중점을 두어 재사용성을 높일 수 있는 프로그래밍 방식

  • 어떤 타입에 대해 알고리즘이 기술되어 있는 것 → 어떤 타입? in terms of types to-be-specified-later(특정되어 있지 않고, 나중에 필요에 따라 결정!)
  • 데이터 타입이 정해지지 않음

*️⃣ Generic한 변수/자료구조

Event ev;   // OneDayEvent oneday; 로 선언한 객체보다 더 제네릭하다! 
Event[] events = new Event[capacity];
Object obj; // Object : Java 내 모든 클래스의 최상위 클래스 -> 모든 타입을 포괄할 수 있음

*️⃣ Generic한 알고리즘(method)

Arrays.sort(shapes, 0, n);

어떤 타입의 배열에 대해서도 똑같이 정렬 기능을 적용할 수 있음 ⇒ 알고리즘을 제네릭하게 구현한 것도 일종의 제네릭 프로그래밍에 포함된다!

*️⃣ Generic 클래스

Generics

클래스 자체를 Generic한 Type으로, Type Indenpendent하게 구현하는 것

→ 클래스를 구현할 때, 멤버변수와 메소드의 타입을 미리 정의하지 않고 실제 그 클래스를 사용할 때(= 실제로 객체를 생성할 때) 타입을 우리가 지정할 수 있도록 작성하는 방식

*C++의 Class Template과 같은 개념

int, double과 같이 하나의 타입으로 특정하지 않고 T라는 가상의 타입을 가정하여 클래스를 구현할 수 있다.

public class Box<T> {
		private T t;
		public void set(T t) { this.t = t; }
		public T get() { return t; }
}

→ T라는 가상의 타입으로 지정해줌으로써, 원하는 경우에 따라 int를 저장하는 용도, Event 객체를 저장하는 용도, 문자열을 저장하는 용도 등 다양하게 활용할 수 있다.

public class Pair<K, V> {
		private K key;
		private V value;
		public void set(K key, V value) { this.key = key; this.value = value; }
		public K getKey() { return key; }
}

→ 원하는 조합의 객체도 자유롭게 만들 수 있다!

class Object VS Generics

public class Box {
		private Object t;
		public void set(Object t) { this.t = t; }
		public Object get() { return t; }
}

public class Box<T> {
		private T t;
		public void set(T t) { this.t = t; }
		public T get() { return t; }
}

모든 클래스의 최상위 클래스인 Object로 선언하고 필요에 따라 타입을 지정해주는 방식이나, 가상의 타입인 T를 사용하여 구현하는 방식이나 모두 같은 기능을 하지만 굳이 T를 사용하는 이유는 ..

Object로 선언할 경우, 부모 클래스의 멤버를 자식 클래스가 참조해야 하는 상황마다 Type casting이 추가적으로 따른다는 단점이 있다. → type casting이 많은 프로그램은 절대 좋은 프로그램일 수 없다!

#자바 제어자와 접근제어자

자바의 제어자(Modifier)

클래스, 변수, 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여

*용도 - 클래스, 멤버변수와 메서드에 대한 Visibility와 Accessibility를 컨트롤하기 위함!

  • 접근 제어자 - public, protected, default, private
  • 그 외 - static, final, abstract, native, transient, synchronized, volatile, strictfp

접근 제어자

접근 제어자설명대상
public접근 제한 無클래스, 메서드, 멤버변수
protected같은 패키지 내 + 다른 패키지의 자손 클래스에서 접근 가능메서드, 멤버변수
default같은 패키지 내에서만 접근 가능클래스, 메서드, 멤버변수
private같은 클래스 내에서만 접근 가능메서드, 멤버변수
  • 지역 변수에는 접근 제어자를 지정하지 않는다
  • 객체지향 개념의 캡슐화에 해당!
💡 생성자의 접근 제어자

private로 지정하여 외부에서의 인스턴스 생성을 제한할 수 있다

→ 이때, public static 메서드를 통해서 이 클래스의 인스턴스를 사용하게끔 할 수 있다

static

인스턴스 생성 없이 바로 접근 가능하도록, 모든 객체가 공유하는 멤버

  • 클래스 당 하나만 생성
  • 클래스 로딩 시에 생성 *non-static은 객체 로딩 시에 생성
  • 메모리 상에서 전역변수와 같은 Data 영역에 할당
어디에 사용?

멤버변수, 메서드, 초기화 블럭

final

한 번 정해지면 변경 불가능하도록 제한!

  • 클래스 : 상속 불가 ⇒ 확장될 수 없는 클래스
  • 메서드 : 오버라이드로 재정의 불가 ⇒ 반드시 처음 정의된 대로만
  • 멤버변수 : 값을 변경할 수 없는 상수 → public **static final** 변수명 = 값;
어디에 사용?

클래스, 메서드, 멤버변수, 지역변수

abstract

  • 클래스 : 클래스 내에 추상 메서드가 선언되어 있음
  • 메서드 : 선언부만 있고, 구현부가 없는 메서드

extends와 implements가 가진 의미를 혼합한 개념으로, abstract로 정의된 메서드를 하나라도 가지면 추상 클래스라고 한다. 이는 부모의 특징을 연장해서 사용하는 동시에 몇 개는 새롭게 만들어 사용하는 것으로 생각하면 된다.

  • *️⃣ 추상 클래스와 인터페이스의 차이는?
    추상 클래스인터페이스
    사용 키워드abstractinterface
    사용 가능 변수제한 Xstatic final(상수)
    사용 가능 접근 제어자제한 X (public, private, protected, default)public
    사용 가능 메서드제한 Xabstract method, default method, static method, private method
    상속 키워드extendsimplements
    다중상속 가능 여부불가능가능
    - 클래스에 다중 구현
    - 인터페이스끼리 다중 상속
    인터페이스를 극단적인 추상 클래스로 볼 수 있지만, 이를 굳이 구분하는 이유는 다음과 같다.
    1. 사용 의도

      클래스 상속의 기본은 의미있는 연관 관계를 구축하고자 함에 있다. 즉, 구현의 강제화 외에 추상 클래스의 목적에는 클래스 간 명확한 계층 구조를 필요로 한다는 점에서도 찾을 수 있다.

      • IS-A 관계 (”~이다”) ✅ 상속 일반적인 개념 - 구체적인 개념의 관계로, 자식 클래스가 부모 클래스에 종속되는 관계에서만 사용하는 것이 좋다. ex. 사과는 과일이다. 강아지는 동물이다.
      • HAS-A 관계 (”~을 할 수 있는”) 일반적인 포함 개념의 관계로, 다른 클래스의 기능(멤버)을 받아들여 사용한다. ex. 차는 엔진을 가지고 있다.

      인터페이스는 상속에 구애 받지 않는 상속이 가능하다는 특징이 있다. 타입끼리 묶이는 것이 자유로워 서로 논리적이지 않고 관련이 적은 클래스끼리 부모-자식의 관계가 아닌, 형제 관계처럼 묶을 수 있다. 즉, 인터페이스를 사용하는 이유는 자유로운 타임 묶음을 통한 추상화를 이루는 것에 있다!

    2. 공통 기능 사용 여부

      모든 클래스가 인터페이스로만 구현이 가능하다면, 같은 기능을 하는 여러 클래스에 똑같은 코드를 반복해서 작성하는 번거로움이 따를 것이다. 공통된 기능을 가진 메서드나 멤버가 있는 경우에는 추상 클래스를 이용하여 일반 메서드로 구현한 후, 구현의 의무를 부여할 메서드만 abstract로 선언해주면 된다.

      *참고 자료 - https://inpa.tistory.com/entry/JAVA-☕-인터페이스-vs-추상클래스-차이점-완벽-이해하기

제어자의 조합

  • 메서드
    • static과 abstract를 함께 사용할 수 없다 → static 메서드는 몸통이 있는 메서드에만 가능
    • private과 final을 같이 사용할 필요는 없다 (둘 다 어차피 오버라이딩은 못하기 때문)
    • abstract 메서드의 접근 제어자가 private일 수 없다
  • 클래스
    • final과 abstract를 동시에 사용할 수 없다
      • abstract는 상속을 통해 완성 ↔ final은 상속을 제한 (모순적)

*참고 자료 - https://velog.io/@kongsub/Modifier

#싱글톤(Singleton)

클래스의 인스턴스가 딱 한 개만 생성되는 것을 보장하는 디자인 패턴

public class Sopt {
		
		private static Sopt instance = new Sopt();
		
		private Sopt() {
				// 생성자의 접근 제어를 private으로 지정하여 외부에서의 객체 생성을 막는다
		}

		public static Sopt getInstance() {
				return instance;
		}

		public void 메서드() {
					// Sopt.getInstance().메서드()로 이 클래스의 멤버함수 호출 가능!
		}
}

Spring의 특징 중 제어의 역전(IoC)을 가능하게 한다!

스프링이 모든 의존성 객체에 대해 실행 시에 만들어주고 필요한 곳에 주입시켜줌으로써, 기본적으로 싱글톤 패턴으로 동작하는 Bean들의 작업이 스프링에 의해 처리될 수 있다.

✨ benefit

  • 메모리 측면의 효율 최초 한번의 new 로 객체를 생성하여 고정된 메모리 영역을 사용 ⇒ 이후부터 해당 객체에 접근할 때 메모리 낭비를 방지할 수 있음
  • 데이터 공유가 쉬움 전역으로 사용되어, 다른 클래스 인스턴스들이 접근하여 사용 가능

🚨 problem

  • 많은 양의 코드가 필요 → 멀티스레딩 환경에서의 객체 생성 중 발생할 수 있는 동시성 문제를 해결할 수 있어야 함
  • 테스트가 어려움 격리된 환경에서 테스트를 수행하려면, 매번 인스턴스의 상태를 초기화시켜야 하는 번거로움이 따름
  • 클라이언트가 구체 클래스에 의존하는 형태 SOLID 중 DIP와 OCP를 위반할 가능성이 높음

→ 이들 간의 trade-off 관계를 잘 따져가며, 싱글톤 패턴의 적용 여부를 결정해야 한다.

#Spring의 각각의 의존성 주입 방법 특징 및 생성자 주입 방식의 장점

1️⃣ 생성자 주입

public class Server {

    private Leader partLeader;

		public Server(Leader leader) {
				this.partLeader = leader;
		}
}
장점은?!
  • 의존관계의 내용을 외부로 노출시켜야 함 ⇒ 컴파일 타임에 오류를 잡아낼 수 있다 → final 키워드로
  • 객체의 불변성 확보 → 객체 생성 시 1회만 호출됨이 보장 (setter 주입의 단점 해결)
  • 테스트 코드 작성의 편리함
    • null을 주입하지 않는 한 NullPointerException 발생 X
  • 순환 참조 에서 방지 → 컴파일 시점에 발견 가능
  • @Autowired 로 의존성 주입을 남발하여 발생하는 의존성, 결합에 대한 문제 방지 (필드 주입의 단점 해결)

2️⃣ setter 주입 (수정자 주입)

public void setPartLeader(Leader leader) {
		this.partLeader = leader;
}

이와 같은 방식을 사용하면, 한 클래스를 수정할 때 다른 클래스까지 수정하지 않아도 된다는 장점이 있다. 즉, 의존성을 주입하지 않았을 때보다 코드의 수정이 용이하다.

3️⃣ 필드 주입 - @Autowired ✅ Spring 사용

→ 변수, 생성자, setter 메서드, 일반 메서드 등에 적용 가능

스프링에서 Bean 인스턴스가 생성된 이후, @Autowired로 설정된 메서드가 자동으로 호출되고, 인스턴스가 자동으로 주입된다. 즉, 스프링이 관리하는 Bean을 해당 변수와 메서드에 자동으로 매핑해주는 역할을 한다.

#JAR, WAR 차이

*JAR ⊃ WAR

JAR(Java Archive)

#Spring boot에서 가이드하는 표준

Java 어플리케이션이 동작할 수 있도록 자바 프로젝트를 압축한 파일

  • Class(리소스, 속성 파일), 라이브러리 파일을 포함
  • JRE(Java Runtime Environment)만 있어도 실행 가능!

WAR(Web Application Archive)

Servlet/JSP 컨테이너에 배치할 수 있는 웹 어플리케이션 전체를 패키징 하기 위한 압축파일 포맷

  • 웹 관련 자원을 포함 - JSP, Servlet, JAR, Class, XML, HTML, Javascript
  • 사전 정의된 구조를 사용 - WEB-INF, META-INF
  • 별도의 웹 서버 or 웹 컨테이너 필요
💡 결론

어플리케이션 리소스를 패키징 하는 방법에 차이가 있을 뿐, 모두 java -jar 프로젝트명.jar 을 통해 쉽게 배포하고 동작시킬 수 있다

*참고 자료 - https://velog.io/@mooh2jj/JAR-vs-WAR-배포의-차이

profile
서버 개발자를 꿈꾸며 성장하는 쭌입니다 😽

0개의 댓글