로그, 로깅이란?

로깅이란 시스템 동작시 시스템의 상태와 작동 정보를 시간에 따라 기록하는 것

그 기록이 로그

 

로깅의 장점

소프트웨어의 디버깅이나 모니터링을 위하여 소프트웨어 동작 상태 정보를 기록해서 볼 수 있다.

-상황에 따라 Level별 메시지 가능

-프로그램의 실행에 대한 흐름과 에러 확인 가능

-자유로운 출력 형식과 위치 가능

-프레임워크를 이용하여 쉽게 설정 가능

 

로깅 프레임워크 3가지 종류들

1. logback(사용 추천)

log4j와 유사하지만 향상된 성능과 필터링 옵션, slf4j, 자동 리로드 기능 지원

 

spring boot 환경의 경우 spring-boot-starter-web > spring-boot-starter-logging에 기본적으로 logback 구현체가 포함!

-> 따로 프레임워크를 지정하지 않는다면 자동으로 logback이 적용된다.

 

공식 메뉴얼 링크

http://logback.qos.ch/manual/index.html

 

Logback Manual

The logback manual The complete logback manual documents the latest version of logback framework. In over 150 pages and dozens of concrete examples, it covers both basic and advanced logback features, including: the overall logback architecture discussion

logback.qos.ch

https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-logging

 

Core Features

Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments. You can use a variety of external configuration sources, include Java properties files, YAML files, environment variables, an

docs.spring.io

2. log4j2

logback 이후에 나온 프레임워크

logback과 유사하나 Multi Thread 환경에서의 비동기 로거(Async Logger) 케이스에 처리량이 더 높고 시간 효율이 좋다.

 

spring boot 환경의 경우 log4j2를 사용하려면 dependency에서 logback 제거 작업 필요

 

3. slf4j

로깅에 대한 추상 레이어

코드를 일정하게 유지하면서 구현체의 전환 (다른 프레임워크로의 전환)을 쉽게 지원

logback, log4j2는 slf4j의 구현체

 

로그 레벨 

TRACE  <  DEBUG  <  INFO  <  WARN  <  ERROR

 

-ERROR : 오류가 발생

-WARN  : 처리 가능한 문제, 향후 에러의 원인이 될 수 있는 경고성 메시지

-INFO  : 상태 변경과 같은 정보성 로그를 표시한다.
-DEBUG : 디버깅하기 위한 정보. 
-TRACE : Debug보다 상세한 정보

 

차후에 스프링 부트에서 logback 설정을 하는 방법도 다뤄볼까 예정 중이다.

 

참고 사이트

https://wildeveloperetrain.tistory.com/36

https://goddaehee.tistory.com/206

최신 스프링 부트 프로젝트에선 (스프링부트 2.2x 이상 버전) Junit으로 JUnit5버전이 들어간다.

Junit4를 사용하고 싶다면 build.gradle dependencies에 아래 코드를 추가하면 된다.

 

testImplementation("org.junit.vintage:junit-vintage-engine") {
 exclude group: "org.hamcrest", module: "hamcrest-core"
}

 

추가적으로 JUnit4에서 @Test는 org.junit.Test를 사용해야한다.

스프링 부트 2.2x 버전 이후부터는 자동적으로 JUnit5가 들어간다.

 

내가 현재 듣고 있는 스프링 부트 강의는 예전 강의라 JUnit4를 사용하고 있는데 Junit5를 써보고 싶었고 현재 진행 중인 스프링 부트 프로젝트도 JUnit5를 쓸 생각이기 때문에 Junit5로 구글링해서 코드를 작성해봤다.

 

작성하면서 발견한 주요 차이점들을 적어보자면 @RunWith(SpringRunner.class)이 Junit5에선 @SpringBootTest에 포함되면서 생략 가능해졌다.

Junit4에서 사용하던 @Test(expected = 클래스명.class)이 사라지면서 

IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> userService.join(user2));
assertEquals("이미 존재하는 회원입니다.", thrown.getMessage());

와 같은 코드를 사용해야했다.

 

UserService 검증 Juni4 코드

package simplebook.simpleshop.service;

import simplebook.simpleshop.Domain.User;
import simplebook.simpleshop.Repository.UserRepository;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class UserServiceTest {

 @Autowired
 UserService userService;
 @Autowired
 UserRepository userRepository;
 
 @Test
 public void 회원가입() throws Exception {
  //Given
  User user = new User();
  user.setUserName("bryn");
  //When
  Long saveId = userService.join(user);
  //Then
  assertEquals(user, userRepository.findOne(saveId));
 }
 
 @Test(expected = IllegalStateException.class)
 public void 중복_회원_예외() throws Exception {
 //Given
 User user1 = new User();
 user1.setUserName("bryn");
 User user2 = new User();
 user2.setUserName("bryn");
 //When
 userService.join(user1);
 userService.join(user2); //예외가 발생해야 한다.
 //Then
 fail("예외가 발생해야 한다.");
 }
}

 

UserService 검증 Junit5 코드

package simplebook.simpleshop.service;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import simplebook.simpleshop.Domain.User;
import simplebook.simpleshop.Repository.UserRepository;
import javax.transaction.Transactional;

@ExtendWith(SpringExtension.class)
@SpringBootTest
@Transactional
class UserServiceTest {

    @Autowired
    UserService userService;
    @Autowired
    UserRepository userRepository;

    @Test
    public void 회원가입() throws Exception {
        //Given
        User user = new User();
        user.setUserName("bryn");
        //When
        Long saveId = userService.join(user);
        //Then
        assertEquals(user, userRepository.findOne(saveId));
    }

    @Test
    public void 중복_회원_예외() throws Exception {
        //Given
        User user1 = new User();
        user1.setUserName("bryn");
        User user2 = new User();
        user2.setUserName("bryn");
        //When
        userService.join(user1);
        userService.join(user2); //예외가 발생해야 한다.
        //Then
        IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> userService.join(user2));
        assertEquals("이미 존재하는 회원입니다.", thrown.getMessage());
    }

}

 

+추가)

위에서 쓰인 User domain과 다른 domain임을 참고바랍니다.

 

User 검증 Juni4 코드

import jpabook.simpleshop.domain.User;
import jpabook.simpleshop.repository.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserRepositoryTest {
 @Autowired UserRepository userRepository;
 @Test
 @Transactional
 @Rollback(false)
 public void testUser() {
 
 User user = new User();
 user.setUsername("user1");
 
 Long savedId = userRepository.save(user);
 User findUser = userRepository.find(savedId);
 
 Assertions.assertThat(findUser.getId()).isEqualTo(user.getId());
 Assertions.assertThat(findUser.getUsername()).isEqualTo(user.getUsername());
 }
}

 

User 검증 Junit5 코드

package simplebook.simpleshop.User;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import javax.transaction.Transactional;

@ExtendWith(SpringExtension.class)
@SpringBootTest
class UserRepositoryTest {
    @Autowired UserRepository userRepository;

    @Transactional
    @Test
    public void testUser() throws Exception{
        User user=new User();
        user.setUserName("user1");
        
        Long saveId = userRepository.save(user);
        User findUser = userRepository.find(saveId);
        
        Assertions.assertThat(findUser.getId()).isEqualTo(user.getId());
        Assertions.assertThat(findUser.getUserName()).isEqualTo(user.getUserName());
    }
}

 

Junit5 테스트 코드를 통해 UserRepository가 정상적으로 작동함을 확인했다.

 

JPA와 DB 연결 관련 오류였다.

먼저 DB 연결 설정파일에 관한 부분에 오타가 없는지 확인해야한다.

필자는 datasource 연결 주소에 오타가 있었다. 

 

이후 실행을 했는데도 똑같은 오류가 발생했다.

생각해보니 h2 데이터베이스를 실행 안시켜서 그런가하고 cmd 창에서 h2 폴더에 접근한 후 h2 데이터베이스를 실행시켰더니 제대로 작동했다. 

 

RDS는 데이터베이스 서버를 임대받아서 오는 것이기 때문에 연결 정보만 입력해주면 서버가 항상 돌아가고 따로 실행을 시켜줄 필요가 없었는데 h2 데이터베이스는 로컬 서버로 돌아가는 데이터베이스인지 cmd 창에서 실행을 시켜준 후 스프링 부트를 돌려야 정상적으로 작동했다. RDS에 익숙해서 H2 데이터베이스 쪽에서 알아서 자체 서버를 연결해주나 어렴풋이 생각하고 넘겼었는데 생각해보니 H2 데이터베이스를 까는 것 자체가 로컬에서 작업한거라 로컬 서버로 돌아가는게 맞는 것 같다.

 

+) 이후 H2 데이터베이스에 대해 좀 알아보니 로컬 환경에서 작업, 테스트 시에 많이 사용하는 데이터베이스라고 한다.

로컬 서버로 운영되는 데이터베이스가 맞나보다. 

테스트 코드를 JUnit5로 처음 작성해보고 돌렸는데 계속 작동을 안해서 코드 문제인줄 알고 몇시간 헤맸는데 알고보니 H2데이터베이스를 실행 안시키고 돌려서 그런거였다. 강의를 들으며 사용한 기술이라 일단 따라쳐보고 시작했는데 새로운 프로그램이나 툴을 쓸때는 잘 알아보고 쓰자!

 

프로젝트를 진행하면서 .properties 파일을 .yml 파일로 변경했다.

기본적인 작성 방식은 다르지만 설정 내용들을 비슷해서 각 문법에 맞게끔 변환만 해주면 된다.

 

아래는 내가 .properties 파일을 .yml 파일로 변경한 일부 예시이다.

변경 이후 설정한 포트 번호로 스프링부트가 잘 작동함을 확인했다.

 

한글로 적힌 부분들은 각자의 환경에 맞게 넣어주시면 됩니다.

 

application.properties 

spring.profiles.include=prod,jwt,oauth,redis,mail

application.yml

spring:
  application:
    name: 9T
  profiles:
    include: jwt,oauth,redis,mail
    active: prod

application-prod.properties

spring.config.activate.on-profile=prod

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://RDS 엔드포인트:3306/데이터베이스 테이블 이름?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
spring.datasource.username=RDS 사용자 이름
spring.datasource.password=RDS 비밀번호
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

server.port=9000

application-prod.yml

server:
  port: 9000

spring:
  application:
    name: prod

  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver # mysql 8버전
    # driver-class-name: com.mysql.jdbc.Driver # mysql 5버전
    url: jdbc:mysql://RDS 엔드포인트:3306/데이터베이스 이름?autoReconnect=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8
    username: RDS 유저이름
    password: RDS 비밀번호

  jpa:
    show-sql: true
    generate-ddl: true
    #database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    hibernate:
      ddl-auto: update
    properties:
      hibernate.enable_lazy_load_no_trans: true
      hibernate.format_sql: true

application-dev.yml

server:
  port: 8080

spring:
  application:
    name: dev

  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver # mysql 8버전
    # driver-class-name: com.mysql.jdbc.Driver # mysql 5버전
    url: jdbc:mysql://RDS 엔드포인트:3306/데이터베이스 이름?autoReconnect=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8
    username: RDS 유저이름
    password: RDS 비밀번호

  jpa:
    show-sql: true
    generate-ddl: true
    #database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    hibernate:
      ddl-auto: update
    properties:
      hibernate.enable_lazy_load_no_trans: true
      hibernate.format_sql: true

 

application-redis.properties

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=비밀번호
spring.redis.lettuce.pool.max-active=10
spring.redis.lettuce.pool.max-idle=10
spring.redis.lettuce.pool.min-idle=2

application-redis.yml

spring:
  redis:
    host: localhost
    port: 6379
    password: 비밀번호
    jedis:
      pool:
        max-active: 10
        max-idle: 10
        min-idle: 2

application-jwt.yml

spring:
  jwt:
    secretKey: 시크릿키

application-oauth.yml

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id:클라이언트아이디
            client-secret: 클라이언트시크릿키
            redirect: 리다이렉트 주소 예시는 https://localhost:9000/googleLogin
            url:
              login: https://accounts.google.com/o/oauth2/v2/auth
              token: https://oauth2.googleapis.com/token
              profile: https://www.googleapis.com/oauth2/v3/userinfo

 

 

참고 사이트

https://blog.naver.com/PostView.nhn?blogId=codingspecialist&logNo=221499365350

https://github.com/SangHyunGil/SpringSecurityJWT-Local-OAuth2-EmailAuth-Redis/blob/main/src/main/resources/application.yml

https://blog.startsomething.dev/2021/05/08/yaml%EC%97%90%EC%84%9C-%EB%94%B0%EC%98%B4%ED%91%9C%EB%A5%BC-%EC%8D%A8%EC%95%BC-%EB%90%A0%EA%B9%8C%EC%9A%94/

https://velog.io/@code12/spring-boot-OAuth%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%B4-%EC%86%8C%EC%85%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-myBatis%EA%B5%AC%EA%B8%80-%EB%A1%9C%EA%B7%B8%EC%9D%B8

https://velog.io/@seho100/Spring-boot%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-JWT-%EA%B5%AC%ED%98%84

application.properties와 applicaiton.yml 파일 모두 외부 설정 값 등을 관리하는 파일

스프링부트가 자동으로 로딩하는 설정 파일들

maven이 gradle로 넘어가고 있듯이 xml, properties 파일에서 yml로 넘어가는 트렌드

 

applicaion.properties

STS 진행시 자동 생성

파일 포맷 name=vaule

 

application.yml

인텔리제이에서  진행시 자동 생성

가독성이 좋다

.xml 파일과 거의 유사

계층 구조 형식으로 값 지정 가능

.yml 파일을 이용하기 위해선 SnakeYAML 라이브러리가 필요한데 이는 보통 spring-boot-starter의 의존성이 기본 제공

 

참고사이트

https://sillutt.tistory.com/entry/IntelliJ-applicationproperties-%EA%B3%BC-applicationyml%EC%9D%98-%EC%B0%A8%EC%9D%B4?category=365562

https://velog.io/@tjswlsdl135/application.properties-vs-application.yml

https://goddaehee.tistory.com/213

 

 

1. 오픈소스로 github에서 msi 파일 다운로드 

깃허브 링크

https://github.com/microsoftarchive/redis/releases

2.msi 파일 실행하여 설치

기본 포트는 6379로 설정돼있다.

다운로드 받은 파일 경로를 기억해두자.

3. Redis 서버 작동 확인 

cmd 창에서 netstat -an | findstr 6379 명령어로 확인 가능

정상 작동 상태

4. redis-cli.exe 실행

다운로드 받은 파일 경로로 들어간다.

 

서비스가 자동 등록 돼있고 재부팅시 서버 실행이 자동적으로 되므로 따로 시작을 안해줘도 되지만

따로 시작을 해야하는 상황이라면 redis-server.exe를 실행해야한다.

필자는 자동으로 실행되므로 따로 실행안했다.

 

redis-cli.exe 파일을 실행한다.

 

사진과 같이 ping을 쳤을 때 pong이 돌아오면 정상적으로 작동한다는 걸 확인할 수 있다.

 

5. 비밀번호 설정

다음과 같은 명령어 수행

CONFIG SET requirepass "비밀번호"

AUTH "비밀번호"

 

 

참고 사이트

https://velog.io/@dabeen-jung/Redis-%EC%9C%88%EB%8F%84%EC%9A%B010%EC%97%90%EC%84%9C-%EC%84%A4%EC%B9%98

 

 

 

캐시란?

데이터를 읽을 때 임의의 공간에 저장하여 다음에 읽을 때는 더 빨리 읽을 수 있도록 도와주는 공간

클라이언트가 웹 서버에 요청을 보내면 DB로 가기 전에 캐시 서버에 데이터가 있는지 확인한다.

이때, 캐시 서버에 데이터가 존재한다면 DB에 데이터 요청하지 않고도 바로 클라이언트에 캐시에 존재하는 데이터를 반환해준다. (cache hit)

존재하지 않는다면(cache miss) DB에 해당 데이터를 요청한다.

 

Redis란?

캐시 시스템

키-값 기반 인메모리 데이터베이스

다양한 자료 구조 지원

싱글스레드로 한 번에 하나의 명령어만 처리 가능

 

Redis가 지원하는 다양한 자료 구조

Strings

redis의 가장 기본적인 타입

Vinary-safe한 key-value 구조

Lists

Strings element의 모음

Linked List와 유사한 구조

Sets 

정렬되지 않은 strinf collection

Sorted sets

Sets 자료구조에 score라는 값을 추가로 두어 해당 값을 기준으로 순서를 매김

Hahses

내부에 key-value 구조를 하나더 가지는 Reids 자료구조

value로 또다른 key-value 매핑

Bit arrays(bitMaps)

bit array를 다루는 자료구조

HyperLogLogs

확률적 자료구조로 unique한 항목들의 카운팅하는데 사용

 

 

 

참고 사이트

https://velog.io/@dabeen-jung/Redis-%EC%9C%88%EB%8F%84%EC%9A%B010%EC%97%90%EC%84%9C-%EC%84%A4%EC%B9%98

https://brunch.co.kr/@jehovah/20

https://devlog-wjdrbs96.tistory.com/374

 

재귀 함수

함수 안에서 자기 자신을 다시 호출하는 함수

 

재귀 함수 장점

복잡한 알고리즘을 가독성있게 표현할 수 있다.

재귀 함수 단점

함수 호출 오버헤드가 크다

 

재귀 함수 주의점

무한 루프에 빠지지 않기 위해 종료 조건을 잘 처리해야한다.

 

재귀 vs 반복문

모든 재귀 호출은 반복문으로 표현 가능하고

모든 반복문은 재귀 호출로 표현 가능하다.

 

재귀 코드

long long recursive(int n) {
	if (n < 1) 
		return 1;
	else 
		return n * recursiveFactorial(n - 1);
}

반복문 코드

long long nonRecursive(int n) {
	long long f = 1;
	while (n) 
		f = f * n--;
	return f;
}

 

 

참고 사이트

https://ansohxxn.github.io/algorithm%20lesson%201/chapter1-1/

 

토비의 스프링 3.1 책을 읽으며 일부분을 정리한 내용입니다. 
개념 이해를 위한 내용들 중 일부분을 정리했으므로 이해를 돕기위한 예시 코드들 및 자세한 전체적인 내용은 책을 통해 확인하시길 바랍니다.
포스팅 내용이 저작권의 문제가 발생할 경우 게시물은 바로 삭제/비공개 처리됩니다.

애플리케이션 컨텍스트가 생성하고 관리하는 객체

스프링이 제어권을 가지고 직접 만들과 관계를 부여하는 오브젝트

오브젝트 단위의 애플리케이션 컴포넌트이자 스프링 컨테이너가 생성, 관계설정,사용 등을 제어해주는 제어의 역전 개념이 사용된 오브젝트

 

빈 팩토리

스프링의 IoC를 담당하는 핵심 컨테이너

빈의 생성과 관계설정과 같은 제어를 담당하는 IOC 오브젝트

빈 팩토리보다는 확장된 애플리케이션 컨택스트를 주로 사용하긴 하는데 두 용어를 혼용해서 사용하기도 한다.

 

애플리케이션

애플리케이션의 컨택스트와 그 설정 정보를 따라서 만들어지고 구성된다.

 

애플리케이션 컨텍스트=IoC 컨테이너=스프링 컨테이너{=빈 팩토리}

빈 팩토리를 확장한 IoC 컨테이너

빈을 등록,관리하는 기본적인 기능은 빈 팩토리와 동일하나 스프링이 제공하는 각종 부가 서비스를 추가로 제공해준다.

애플리케이션에서 IoC를 적용해서 관리할 모든 오브젝트에 대한 생성과 관계설정 담당

별도의 정보를 참고해서 빈의 생성, 관계설정 등의 제어 작업 총괄

직접 정보들을 담고 있지는 않지만 별도로 설정 정보를 담고 있는 무엇인가(ex xml..)를 가져와 이를 활용하는 범용적인 IOC 엔진같은 것

 

@Configuration

빈 팩토리를 위한 오브젝트 설정을 담당하는 클래스라고 인식하도록하는 애노테이션

 

@Bean

오브젝트를 만들어주는 메소드라고 인식하도록하는 애노테이션

 

@Configuration
public class DaoFactory {
	
	@Bean
	public UserDao userDao() {
		return new UserDao(connectionMaker());
	}
	
	@Bean
	public ConnectionMaker connectionMaker() {
		return new DConnectionMaker();
	}
	
}

 위에서 만든 다오팩토리를 설정정보로 사용하는 애플리케이션 컨텍스트의 코드는 아래와 같다.

public class UserDaoTest {

	public static void main(String[] args) throws ClassNotFoundException, SQLException{
		
		ApplicationContext context =
				new AnnotationConfigApplicationContext(DaoFactory.class);
		
		UserDao dao = context.getBean("userDao", UserDao.class);
		
	}
}

 

getBean() 함수

애플리케이션 컨텍스트에 등록된 빈의 이름을 파라미터로 받는다.

@Bean 애노테이션이 붙은 메소드의 이름이 빈의 이름이 된다.

 

오브젝트 팩토리를 직접 사용 대신 애플리케이션 컨텍스트 사용시 장점

-클라이언트가 구체적인 팩토리 클래스를 알 필요가 없다.

애플리케이션 컨텍스트를 사용하면 오브젝트 팩토리가 아무리 많아져도 이를 알거나 직접 사용할 필요없다.

-종합 IoC 서비스를 제공해준다.

오브젝트에 대한 후처리, 정보의 조합 등 오브젝트를 효과적으로 사용할 수 있는 다양한 기능 제공

-빈을 검색하는 다양한 방법을 제공해준다.

ex.getBean() 함수

 

설정정보/설정 메타정보

애플리케이션 컨텍스트 또는 빈 팩토리가 IoC를 적용하기 위해 사용하는 메타정보

IoC 컨테이너에 의해 관리되는 애플리케이션 오브젝트를 생성하고 구성할 때 사용

 

컨테이너/IoC 컨테이너

애플리케이션 컨텍스트보다 추상적인 표현

애플리케이션 컨텍스트 오브젝트 여러 개를 통틀어서 스프링 컨테이너라고 부를 수 있다.

 

스프링 프레임워크(=스프링)

스프링이 제공하는 모든 기능(애플리케이션 컨텍스트 등)을 통틀어 말할 때 주로 사용

토비의 스프링 3.1 책을 읽으며 일부분을 정리한 내용입니다. 
개념 이해를 위한 내용들 중 일부분을 정리했으므로 이해를 돕기위한 예시 코드들 및 자세한 전체적인 내용은 책을 통해 확인하시길 바랍니다.
포스팅 내용이 저작권의 문제가 발생할 경우 게시물은 바로 삭제/비공개 처리됩니다.

오브젝트 팩토리

객체의 생성 방법을 정하고 그렇게 정해진 오브젝트를 돌려주는 클래스

오브젝트를 생성하는 역할과 오브젝트를 사용하는 역할을 분리하기 위해 사용

애플리케이션에서 어떤 오브젝트가 어떤 오브젝트를 사용하는지를 정의해놓은 설계도 같은 역할

->애플리케이션의 구조를 결정하는 오브젝트

 

오브젝트 팩토리의 활용 예시

public class DaoFactory {

	public UserDao userDao() {
		return new UserDao(connectionMaker());
	}
	
	public AccountDao accountDao() {
		return new UserDao(connectionMaker());
	}
	
	public MessageDao messageDao() {
		return new UserDao(connectionMaker());
	}
	
	public ConnectionMaker connectionMaker() {
		return new DConnectionMaker();
	}
	
}

오브젝트를 만드는 코드를 별도의 메소드로 뽑아내서 중복을 제거했다.

 

제어의 역전

프로그램의 제어 흐름 구조를 바꾸는 것

일반적으로는 모든 오브젝트가 능동적으로 자신이 사용할 클래스를 결정하고 언제 어떻게 그 오브젝트를 만들지를 스스로 제어하는 구조

그러나 제어의 역전은 오브젝트가 자신이 사용할 오브젝트를 스스로 선택 및 제어하지 않는다.

모든 제어 권한을 다른 대상에게 위임

프레임 워크도 제어의 역전 개념이 적용된 대표적인 기술

개발자가 만든 애플리케이션 코드가 프레임 워크에 의해 사용된다.

<->라이브러리: 코드가 애플리케이션의 흐름을 제어

서블릿도 제어의 역전 개념이 적용된 대표적인 기술

서블릿 컨테이너에 의해 생성/관리된다.

프레임워크 또는 컨테이너와 같이 애플리케이션 컴포넌트의 생성, 관계설정, 사용, 생명주기, 관리 등을 제어하는 존재가 필요하다.

 

 

jdk 설치용 exe 파일을 오라클에서 다운받아 실행하려고 하는데 아무리 클릭을 해도 실행이 안되는 오류가 발생했다.

열심히 구글링을 하다가 아래 사이트를 참고해서 알약을 종료하고 다시 클릭했더니 정상적으로 실행됐다.

실행 중인 백신이 있다면 끄고 시도해보길 바란다.

 

참고 사이트

https://www.java.com/ko/download/help/troubleshoot_java_ko.html

 

+ Recent posts