Skip to content
ENAN edited this page Aug 11, 2020 · 10 revisions

Day 1

모임날짜: 2020-08-08(토)
참여자: 강인한, 김근욱, 최승연

Contents

  1. 환경 설정
    1.1 과정
    1.2 막혔던 곳
  2. 스프링
    2.1 스프링의 주요 특징
    2.2 의존성 주입
    2.3 스프링의 동작
  3. 어노테이션 정리
  4. 의문점

1. 환경 설정

1.1 과정

참고 서적은 이클립스와 maven을 기준으로 설명하나, 여러 추천에 의해 IntelliJ와 gradle을 사용해 환경을 설정하기로 했다.

환경 설정 과정 1. InteliJ Ultimate로 설치, 학교 메일로 인증
2. Jdk 설치 (Homebrew)
3. Gradle 설치 (Homebrew)
4. 새 프로젝트 gradle로 설치 - java, web 체크
5. build.gradle -dependency 에 아래 추가
compile group: 'org.springframework', name: 'spring-context', version: '5.2.8.RELEASE'
compile group: 'org.springframework', name: 'spring-test', version: '5.2.8.RELEASE'
4. Preference - plugin 에서 lombok 설치후 ide 재시작
5. build.gradle -dependency 에 아래 추가
compile group: 'org.projectlombok', name: 'lombok', version: '1.18.12'
6. Preferences -> Build, Execution,Deployment -> Compiler -> Annotation Processors -> Default에서 Enable annotation processing 체크
7. build.gradle -dependency 에 아래 추가
compile group: 'log4j', name: 'log4j', version: '1.2.17'
8. Src - main - resources 에 log4j.properties 파일 생성 후 아래 내용 작성
log4j.properties
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %-5p %c{1}:%L - %m%n
9. Tomcat 9.0 설치 (Homebrew)
10. Run - Edit Configurations - 왼쪽위 + 버튼 - Tomcat Server - Local 추가
(만약 application server에 아무것도 없다면 tomcat 설치한 폴더 지정 (내기준 /usr/local/Cellar/tomcat/9.0.37/libexec))
11. 아래쪽 Fix버튼 누르고 ok 후 실행되는지 확인 ㄲ 화면에 $end$라고 뜨면 정상!
— [스프링mvc 추가] —
12. build.gradle -dependency 에 아래 추가
compile group: 'org.springframework', name: 'spring-webmvc', version: '5.2.8.RELEASE'
13. webapp 폴더 아래에 WEB-INF 폴더 생성, 그 안에 spring 폴더, 그 안에 appServlet 폴더
webapp
	ㄴWEB-INF
		ㄴspring
			ㄴappServlet
14. Spring 폴더 선택하고 File-New-XML configuration file - Spring Config 눌러서 root-context.xml 추가
15. appServlet폴더 선택하고 File-New-XML configuration file - Spring Config 눌러서 servlet-context.xml 추가
16. File - Project structure - Facets 가서 Spring에 main거 선택해서 아래쪽에 + 누르고 두개 다 체크하고 ok
17. Src-main-java 폴더에 org.zerock.controller 패키지 만들고 거기에 SampleController 클래스 하나 만들어서 아래 내용 추가
package org.zerock.controller;
import lombok.extern.log4j.Log4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
@Log4j
public class SampleController {
    @GetMapping("/doA")
    public void doA(){
        log.info("doA called ...........");
        log.info("----------------------");
    }
}
18. Servlet-context.xml의 beans 태그 안쪽에 아래 추가
<mvc:annotation-driven/>
<context:component-scan base-package="org.zerock.controller"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
</bean>
19. File - Project structure - Facets 에서 web gradle 어쩌고 선택하고 위쪽 + 눌러서 web.xml추가 후 안쪽에 아래 내용 삽입

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

1.2 막혔던 부분

log나 annotation 부분에서 cannot find symbol 에러가 날 때 -> 아래 내용을 build.gradle에 추가해주기

annotationProcessor 'org.projectlombok:lombok:1.18.12'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.12'

2. 스프링

스프링 : 자바 플랫폼을 위한 오픈 소스 경량 애플리케이션 프레임워크

2.1 스프링의 주요 특징

  1. POJO(Plain Old Java Object) 기반

POJO : 별도의 라이브러리에 종속적이지 않고, 일반적인 Java 코드를 이용해 구성된 객체

자세히
  • POJO 방식을 사용하지 않음 -> 특정 환경에 결합도가 높다.
    MessageListener를 이미 상속받았기 때문에 다른 객체에 대한 상속이 제한되고, 다른 리스너로 교체하기도 번거로움)
// POJO 방식을 따르지 않은 예시
public class ExampleListener implements MessageListener {
  public void onMessage(Message message) {
    if (message instanceof TextMessage) {
      try {
        System.out.println(((TextMessage) message).getText());
      }
      catch (JMSException ex) {
        throw new RuntimeException(ex);
      }
    }
    else {
      throw new IllegalArgumentException("Message must be of type TextMessage");
    }
  }
  • POJO 지향적 -> 특정 환경과 결합도가 낮음. 다른 리스너로 교체하고 싶은 경우 코드는 재사용되고 어노테이션만 갈아끼우면 됨)
// POJO 방식을 따른 예시
@Component
public class ExampleListener {
  @JmsListener(destination = "myDestination")
  public void processOrder(String message) {
    System.out.println(message);
  }
}
  • POJO 지향 프로그래밍의 장점

이해를 돕기 위해 POJO 방식이 아닐 때를 생각해 보면,
1) 특정 기술에 의존적이게 되어 확장성이 매우 떨어지고,
2) 독립적으로 테스트 하기도 힘들고,
3) 코드의 재사용성도 낮아 어떤 API를 교체한다고 했을 때 많은 곳을 수정해야 하며,
4) 가독성도 떨어진다.
그렇기 때문에 POJO 방식을 따르면 생산성에서도 유리하고 테스트가 쉽다.


  1. 의존성 주입을 통한 객체간 관계 구성

2.2에서 자세히 설명

  1. AOP(Aspect Oriented Programming) 지원

(횡단 관심사 : 비즈니스 로직은 아니지만 반드시 처리가 필요한 부분 (대부분의 시스템이 공통으로 가지고 있는 보안이나 로그, 트랜잭션 등의 부분))
AOP란 횡단 관심사를 모듈로 분리하는 프로그래밍 패러다임
개발자가 핵심 비즈니스 로직에만 집중할 수 있게 해주고, 코드 수정 최소화, 유지보수 수월

  1. 편리한 MVC 구조
  2. WAS에 종속적이지 않은 개발 환경

2.2 의존성 주입의 개념

(의존성 : 하나의 객체 A가 다른 객체 B가 없으면 동작 불가능 (A가 B에 의존적이다))
의존성 주입은 스프링이 ‘A는 B가 필요하다’ 라는 것을 미리 알고 B객체에 대한 레퍼런스를 A에게 주입해준다는 것!
위 예시에서 A와 B 같이 스프링이 관리하는 객체들을 'Bean' 이라고 부르고, 스프링에서 이 Bean들을 관리하는 객체를 Application Context 라고 한다.
Application Context는 Bean들을 생성하고 관계를 맺는 역할을 한다.

2.3 스프링의 동작

  • 과정
  1. 스프링 프레임워크가 시작되면 먼저 스프링이 사용하는 메모리 영역(=Context)을 만든다. (= Application Context 라는 이름의 객체)
  2. 스프링은 자신이 생성하고 관리해야 하는 객체들에 대한 설정이 필요한데, 이 설정들이 적힌 파일이 root-context.xml
  3. root-context.xml에 적혀 있는 context:component-scan 태그의 내용을 통해 해당 패키지를 스캔
  4. 스캔한 패키지에 들어있는 클래스 중 @Component 어노테이션이 붙어있는 클래스들의 인스턴스 생성
  5. 이 때 @Autowired 와 같이 어떤 객체가 다른 객체에 의존적이라는 것을 나타내는 어노테이션이 존재한다면, 의존적인 객체에다 필요한 객체의 레퍼런스를 주입해 준다.

(책 예시 기준으로 Restaurant 객체는 Chef 객체가 필요하다는 어노테이션 @Autowired 이 있으므로, 스프링은 Chef객체의 레퍼런스를 Restaurat 객체에 주입)

3. 어노테이션 정리

  • Lombok 관련
    @Setter : setter 메서드를 생성해주는 역할
    @Data : @ToString, @EqulasAndHashCode, @Getter/@Setter, @RequiredArgsConstructor를 모두 결합한 형태로, 해당하는 메서드들을 전부 자동으로 만들어줌
    @Log4j : 로그 객체 생성
  • Spring 관련
    @Component - 스프링에서 객체로 만들어서 관리하는 대상(Bean)임을 명시하는 어노테이션 @Autowired - 의존성을 주입해주라는 어노테이션
  • 테스트 관련 어노테이션
    @RunWith(SpringJUnit4ClassRunner.class) : SpringJUnit4ClassRunner 클래스를 사용해 테스트한다
    @ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml") : 테스트에 필요한 객체들을 빈으로 등록할 수 있도록 설정 파일 지정
    @Test : 유닛 테스트를 진행할 대상 메서드임을 표시

4. 의문점

  • bean과 component는 같은 말인가?

bean : 스프링이 관리하는 객체를 나타내는 말
@Component 어노테이션은 해당 객체를 스프링이 관리하는 객체인 bean으로 등록한다는 뜻
@Bean : 개발자가 직접 제어할 수 없는, 외부에서 만들어진 라이브러리를 bean에 등록할 때 사용하는 어노테이션. @Bean != @Component
@Bean은 외부에서 '만들어진' 객체(예를 들면 외부 API, 라이브러리 등)를 bean으로 등록, @Component는 spring이 객체를 '만들어서' bean에 등록
@Bean은 반환되는 객체를 bean에 등록하고, @Component는 객체를 생성해 bean에 등록한다는 차이점이 있음
@Bean은 메서드에 적용, @Component는 클래스에 적용