오늘 사수님께 공유받은 이직과 관련된 포스팅을 보고 급 반성을 하게 되었다.

아직 신입 꼬리표도 못뗀 주제에 너무 안일하게 시간을 보낸 것 같다는 생각이 들며,

그동안의 나를 되돌아보며 스스로를 질책했다. 

 

우선, 자바 기본책을 다시 정독하기 위해 자바의 정석 3rd edition을 새로 구입하여 두세번 읽어보기로 다짐. 

기본도 정확히 모르는 주제에 무슨 개발을 하겠다고 설쳐댄건지.

 

내가 정확하게 다 알 수 있다고 자신있게 말하려면

최소한 기본책에 나온 어떤 내용에 대한 질문에도 짧고 간결하게 답할 수 있는 정도. (구구절절? -> NO)

그 정도가 되었다는 자신이 생겼다면 지금 사두고 잘 읽지 못하고 있는 '모던 자바 인 액션'을 읽기로 하겠다. 

 

 

Anyway,

지금 어쨌든 회사에서 당장 개발해야 될 것들이 있기 때문에 책이 오기 전까지 Spring이 무엇인지, 그리고 동작원리는 어떻게 되는지 짧게라도 짚고 개발을 해야 죄책감이 아주 조금이라도 덜 것 같기에 내용이 잘 정리된 포스팅을 찾고, 그 내용을 기반으로 내 방식대로 다시 정리해보았다. 아래 나온 모든 내용은 맨 하단에 나온 출처로 부터 나온 내용!

 

 

 

  • 스프링이란?
    • IoC와 AOP를 지원하는 경량의 컨테이너
  • 컨테이너란?
    • 객체의 생성, 관리를 담당하고, 객체를 운용하는 데 필요한 기능을 제공한다. 
  • 스프링에서 컨테이너 역할을 하는 것은 ?
    • BeanFactory
    • ApplicationContext (BeanFactory 상속)
  • 두 컨테이너의 차이점은?
    • BeanFactory 
      • applicationContext.xml (스프링 설정 파일) 에 등록된 bean 객체를 생성 및 관리
      • 클라이언트로부터 요청이 들어올 때만 객체를 생성한다. 
    • ApplicationContext
      • BeanFactory의 객체 생성 및 관리 + 트랜잭션 관리 / 메시지 기반의 다국어처리 지원 
      • 컨테이너가 구동되는 시점에 bean에 등록된 클래스를 객체화 한다. 
      • GenericXmlApplicationContext -> ApplicationContext를 구현한 대표 클래스
  • 스프링의 특징
    • POJO (Plain old java object)
      • 예전에는 자바로 웹애플리케이션을 개발하려면 Servlet클래스를 상속받아 구현해야 했는데 이 Servlet이 POJO가 아니었다. 그런데 스프링을 사용하면 POJO만으로 웹 애플리케이션을 구축할 수 있게 되었다. Servlet클래스를 모두 추상화하여 라이브러리로 들어갔기 때문에. XML이나 다른 설정으로 Servlet을 이요하면 된다.  
    • IoC (Inversion of Control)
      • 객체 생성을 자바 코드로 직접 처리하는 것이 아니라, 컨테이너가 대신 처리한다. 
        • 제어권이 사용자가 아니라 프레임워크에 있다.
      • 객체와 객체 사이의 의존 관계 또한 컨테이너가 대신 처리한다. 
    • DI (Dependency Injection)
      • 의존성
        • A 객체에서 B 객체의 변수나 메소드를 사용해야 할 경우,  A라는 객체 생성자에서 new B();를 해야한다. 이 때 A는 B에 의존한다고 볼 수 있다. 
      • 의존성 주입
        • A라는 객체에서 B를 생성하는 것이 아니라 외부에서 생성된 B를 A에 주입함으로써 의존 관계를 없앤다.
      • 의존성 주입 방법
        • XML 방법
          • 생성자<constructor-arg> 태그 + ref 속성
          • 속성 <property> + name 속성  
        • Annotation 방법
          • @Autowired / @Resource 
    • AOP (Aspect of Programming)
      • 트랜잭션이나 로깅, 보안과 같이 여러 모듈에서 공통적으로 사용하는 기능의 경우, 핵심로직에서 분리하여 관리한다. 
      • AOP 방법
        • XML 방법
        • AOP 방법 
          • @Aspect / @Before
    • 스프링 동작 원리 (출처에 표시된 URL에 가시면 자세한 설명 보실 수 있습니다!!!)

웹어플리케이션 실행 -> WAS가 web.xml 실행 -> ApplicationContext를 생성하는 ContextLoaderListener가 web.xml에 등록된 내용에 따라 생성 -> root-context.xml에 등록된 Spring Container가 구동되며 필요한 객체들 생성 -> client요청 들어옴 -> DipatcherServlet 생성 -> 알맞은 Page Controller에게 전달하고 응답을 어떻게 할지 결정 -> Dispatcher Servlet은 servlet-context.xml을 loading -> 두번째 Spring Container가 구동될 때 첫번째 Container가 구동되며 생성된 DAO, VO, ServiceImple클래스들과 협업하여 작업 처리 

https://asfirstalways.tistory.com/334

 

Spring 의 시작, 프레임워크의 구성요소와 동작원리

Spring Framework의 구성요소와 동작원리 POJO 스프링의 특징을 살펴보면 POJO라는 단어가 등장한다. POJO란 Plain Old Java Object로 직역하자면 평범한 옛날 자바 객체이다. 말 그대로 자바 객체인 것이다. 이..

asfirstalways.tistory.com

 

 

  • 정의
    • 클래스 내부에서 사용할 데이터 타입을 클래스를 인스턴스화 하는 시점에 지정하는 기법
      •  = 내부에서 사용할 데이터 타입을 외부에서 지정
  • 사용하는 이유
    • 코드 재사용성 UP! -> 반복코드 DOWN 
      • 하나의 예를 들면, 데이터 타입이 다르다는 이유로 같은 로직인데도 매개변수 타입별로 코드를 다시 쓰지 않아도 된다. 
    • 타입안정성 
      • 제네릭을 사용하면 런타입에 발생하는 에러를 피하고 컴파일 단계에서 에러를 잡을 수 있다.
      • 의도하지 않은 데이터 타입이 오는 것을 피할 수 있다. (아래 예제에서 보이는 것과 같이 rank를 갖고 있지 않은 경우엔 에러를 뱉어내게 할 수 있으니까)
      • 강제 데이터 타입 변환을 막을 수 있다. 
class EmployeeInfo{
    public int rank;
    EmployeeInfo(int rank){ this.rank = rank; }
}
class Person{
    public Object info;
    Person(Object info){ this.info = info; }
}
public class GenericDemo {
    public static void main(String[] args) {
        Person p1 = new Person("부장");
        EmployeeInfo ei = (EmployeeInfo)p1.info;
        System.out.println(ei.rank);
    }
}

 

컴파일은 잘 되는데 런타임에 에러가 발생한다. 

class EmployeeInfo{
    public int rank;
    EmployeeInfo(int rank){ this.rank = rank; }
}
class Person<T>{
    public T info;
    Person(T info){ this.info = info; }
}
public class GenericDemo {
    public static void main(String[] args) {
         
        Person<String> p = new Person<String>("모디");
        String ei = p.info;
        System.out.println(ei.rank); // 컴파일 실패
    }
}

런타임에 에러가 발생한다. e1에는 rank라는 메소드가 없어서

 

  • 제네릭<T> vs wildcard <?>
    • 와일드 카드는 타입 특성에 맞게 사용할 필요가 없을때, 그 자리에 어떤게 들어와도 상관 없을 경우에 사용한다.

 

예전에 코드 작성할 때 어느 순간 제네릭을 사용해야 되겠다는 느낌이 와서 적용한 기억이 있는데

또 다시 가물가물해져서 정리해보았다. 

 

참고

 

  • for vs advanced for문
    • for에서는 index값을 이용할 수 있고, 배열의 값을 가져와 수정할 수 있다.
    • advanced for문 에서는 index 값을 이용할 수 없고, 배열의 값을 가져와 쓸 수만 있고, 수정할 수 없다. 
  • advanced for의 장단점
    • 장점 
      • 배열의 크기를 알지 못해도 OK
      • 수행속도가 조금 더 빠름 (ArrayList는 제외)
      • 코드가 짧음
    • 단점
      • 배열이나 리스트의 값 변경 혹은 추가 NO
      • 배열 역순 탐색 NO
  • (old school) for 문 vs (modern) foreach
    • 차이
      • old school for문은 외부 iterator, modern forEach는 내부 iterator
    • old school for   vs   modern foreach
      • ArrayList 와 같은 경우엔 일반적인 for루프와 forEach()와 속도 면에서 크~~게는 차이가 없다. 그럼에도 일반적인 for루프 보다는 10~20% 느리다. 
      • 그런데 primitive 타입의 array의 경우엔 일반적인 for루프가 훨씬 더 빠르다.
      • forEach()는 JVM 및 라이브러리에서 훨씬 더 많은 작업을 수행하게 되어 유지 측면에서 비효율적이다. 
    • foreach의 장점이라면?
      • 가독성이 좋아진다. (근데 그게 또 항상 그런 것은 아니다...) 
      • 병렬프로그래밍에 용이
  • Collection.forEach() vs Collection.stream().forEach()
    • Collection.forEach()는 컬렉션의 반복자를 사용한다 (지정된 경우), item의 처리 순서가 정해졌다는 것
      • hasNext(), next(), remove() 사용
    • 반면에 Collecaion.stream().forEach()는 정해지지 않았다.
      • 반복자를 무시하고 목록에서 요소를 하나씩 가져온다. 
    • 컬렉션 수정
      • 반복 중에 element가 추가 혹은 제거 되면 ConcurrentModification 예외가 발생 
        • Collection.forEach는 추가 혹은 제거 되자 마자 에러가 발생되는데 Collection.stream().forEach()의 경우는 나중에 예외를 발생시킨다. 
      • Collecion.forEach()는 element를 수정할 수 있는 반면 Collection.stream().forEach()는 수정하면 안됨
        • 둘 다 수정할 수는 있으나, stream은 병렬로 수행되기에 예기치 않은 문제가 발생할 수 있다. 
    • 결론
      • stream이 필요하지 않고 컬렉션을 반복하려는 경우엔 컬렉션에서 직접 forEach()를 사용한다.
  • 자바 8에서 형변환 하는 방법
    •  

old school for 문

     public List<Fruit> appleToFruit(String name){
		List<String> appleNames = Arrays.asList(name.split(","));
		List<Fruit> fruitList = new ArrayList<>();
		for(int i=0; i<appleNames.size(); i++) {
			fruitList.add(new Fruit(appleNames.get(i)));
		}
		return fruitList;
	}
    
    
public static List<Fruit> appleToFruit(String apple){
	List<String> appleNames = Arrays.asList(apple.split(","));
	return appleNames.stream().map(v -> new Car(v)).collect(Collectors.toList());
}

 

참고

불러오는 중입니다...

https://webfirewood.tistory.com/41?category=698497

https://webfirewood.tistory.com/38?category=698497

 

서블릿(Servlet)의 동작구조

웹 서버의 주된 기능은 웹 페이지를 클라이언트로 전달하는 것입니다. 주로 그림, CSS, 자바스크립트를 포함한 HTML 문서가 클라이언트로 전달됩니다. 하지만 이런 웹 서버의 경우 이미 존재하는 즉, 정적인 페이..

webfirewood.tistory.com

 

서블릿(servlet) 생명주기(lifecycle)

우선 지난 시간에 배웠던 Servlet의 동작 순서를 다시한 번 복습 하겠습니다. 여기서 컨테이너는 매핑된 서블릿을 찾아서 service() 메소드를 호출한다고 했습니다. 그런데 어떤 클래스의 메소드를 호출하려면..

webfirewood.tistory.com

 

ParentId id1 = new ParentId();
id1.setId1("myId1");
id1.setId2("myId2");

ParentId id2 = new ParentId();
id2.setId1("myId1");
id2.setId2("myId2");

id1.equals(id2) ??????

id1.equals(id2) 의 결과값은 false이다.

왜냐하면 자바의 모든 클래스는 기본으로 Object 클래스를 상속받는데, 이 클래스가 제공하는 기본 equals()는 인스턴스 참조 값 비교인 ==비교(동일성비교)를 하기 때문이다. 

 

영속성 컨테스트는 엔티티의 식별자를 키로 사용해서 엔티티를 관리한다. 

그리고 식별자를 비교할 때 equals() 와 hashcode()를 사용한다. 

따라서, 식별자 객체의 동등성(equals)이 지켜지지 않으면 예상과 다른 엔티티가 조회되거나 엔티티를 찾을 수 없는 등 영속성 컨텍스트가 엔티티를 관리하는 데 문제가 발생한다. 

 

따라서 복합 키는 equals()와 hashCode()를 필수로 구현해야 한다. 

 

 

* 응용 프로그램은 세션 당 단일 스레드를 고수하는 한 비즈니스 오브젝트에서 동기화 할 필요가 없습니다. 세션 내에서 응용 프로그램은 ==를 사용하여 객체를 안전하게 비교할 수 있습니다.

 

* equals와 hashcode를 어떨 때  사용하는가 ?  -> 가장 이해하기 좋았던 사이트 

https://jojoldu.tistory.com/134

 

equals와 hashCode 사용하기 ( +lombok)

안녕하세요? 이번 시간엔 equasl & hashcode를 어떤 곳에서 사용할 수 있는지를 확인해보려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. (공부한 내용을 정리하는 G..

jojoldu.tistory.com

해당 인스턴스들이 갖고 있는 값들이 같을 경우 같은 인스턴스로 봐야할 때 equals를 오버라이딩

equals와 hashcode는 모두 VO(value object)에서만 사용하길, 값 나타내는 것 이외에 기능을 갖는 인스턴스에서 오버라이딩을 하면 문제가 발생할 수 있음. 롬복 사용시  @EqualsAndHashCode(exclude = {"id", "paymentMethod", "price"}) 와 같은 형태로 클래스 명 위에 입력해주면 된다. 

 

* 참고

-Book. 자바 ORM 표준 JPA 프로그래밍

-https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/persistent-classes-equalshashcode.html

 

4.3. Implementing equals() and hashCode()

4.3. Implementing equals() and hashCode() You have to override the equals() and hashCode() methods if you intend to put instances of persistent classes in a Set (the recommended way to represent many-valued associations) and intend to use reattachment of d

docs.jboss.org

https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/transactions.html#transactions-basics-identity

+ Recent posts