Spring Container

자바 애플리케이션은 애플리케이션 동작을 제공하는 객체들로 이루어져있다.

이때, 객체들은 독립적으로 동작하는 것보다 서로 상호작용하여 동작하는 경우가 많은데

이렇게 상호작용하는 객체를 '객체의 의존성'이라고 표현

 

스프링에서는 스프링 컨테이너가 객체들을 생성하고 객체끼리 의존성을 주입하는 역할을 함.

프링 컨테이너가 생성한 객체들을 '빈'이라고 한다.

즉, 빈은 스프링에서 사용하는 어플리케이션 객체라고 이해할 수 있다.

 

빈의 생성 방법

1. xml 활용

  컴파일 단계에서 스캔하는 xml에 bean을 명시적으로 입력해줌

2. 어노테이션 활용

  xml 통해 빈을 생성하는 건 상당히 번거롭

  @Component 라는 어노테이션을 지정하여 편리하게 빈 생성

  (@Component는 스프링 컴포넌트 클래스를 지정하는 어노테이션)

 

 

의존성 주입

Spring Framework의 3가지 핵심 프로그래밍 모델 중 하나

외부에서 두 객체 간 관계를 정해주는 디자인패턴으로 인터페이스를 사이에 두고 클래스 레벨에서는 의존 관계가 고정되지 않도록 함

런타임시 관계를 동적으로 주입하여 결합도를 낮출 수 있게 하는 기법

 

DI (Dependency Injection)

의존성 주입은 IoC(Invesoin of Control, 의존성 역전) 원칙 하에 객체 간 결합을 약하게 해주고 유지보수가 좋은 코드를 만들어 줌

-> 즉 외부에서 생성된 객체를 이용

 

한 객체가 어떤 객체에 의존할것인지는 별도의 관심사이다.

DI컨테이너를 통해 서로 강하게 결합되어있는 두 클래스를 분리하고,

두 객체간 관계를 결정해줌으로서 결합도를 낮추고 유연성을 확보하고자 한다.

(이때 다른 빈을 주입받으려면 자기자신도 반드시 컨테이너의 빈이여야 한다.)

 

강한 결합

객체 내부에서 다른 객체를 생성하는 것은 강한 결합도를 가지는 구조이다

클래스 간 관계가 맺어질 땐 근본적으로 의존성 주입을 통해 문제를 해결할 수 있음

-> 다형성 필요 (큰 범주의 Interface가 필요하고, 그 범주의 Interface를 구현하는 구현 클래스를 만들면 된다!)

  그 후 상세 클래스에서 외부에서 해당 구현 클래스를 주입받도록 한다

ex) 배터리(의존 객체)를 사용하는 장난감(어떤 객체)에게 배터리를 넣어주는 것을 의존성 주입이라고 생각하면 된다!

애플리케이션 실행시점에 필요한 빈을 생성하여, 의존성이 있는 두 객체를 연결하기위해 한 객체를 다른 객체로 주입시켜줘야 한다.

 

느슨한 결합

객체를 주입받는다는 것은 외부에서 생성된 객체를 인터페이스를 통해 넘겨받는 것

이렇게 하면 런타임시 의존관계가 결정되어 결합도를 낮출 수 있다!

 

스프링의 의존성 주입

만약 Service와 Repository가 둘다 Bean(*스프링 컨테이너 상에서 생성된 객체)으로 등록되어 있다면, Service의 생성자만 만들어주면 스프링 IoC컨테이너가 Repository에 의존성을 알아서 해준다. 

(*컨테이너 : 쉽게말해 bean객체들이 들어있는 통)

 

스프링은 다양한 의존성 주입방법을 제공한다.

@Autowired 어노테이션을 이용하면  Spring에게 의존성을 주입하라 라고 명령하는것과 같은데 생성자, 필드, 세터에 붙일수 있다.

 

1.  생성자 주입 (가장 권장)

생성자에 @Autowired를 붙여 의존성을 주입받을 수 있음

 

생성자주입은 생성자 호출시점에 (해당클래스의 인스턴스생성시) 1회 호출되는 것이 보장

-> 주입받은 객체가 변하지 않거나, 반드시 객체주입이 필요한 경우에 강제하기 위해 사용된다.

 

가장 권장하지만 생성자 주입을 위해 코드를 만드는 부분에서 번거로움 존재

그래서 많이들 사용하는 Lombok에서 @Getter, @Setter 어노테이션처럼 @RequiredArgsConstructor 어노테이션은 클래스에 선언된 final 변수들, 필드들을 매개변수로 하는 생성자를 자동으로 생성해주는 어노테이션이다

 

2. 필드 주입

멤버변수 선언부에 @Autowired을 붙인다.

 

필드주입을 이용하면 코드가 간결해져서 과거에 많이 사용했던 방법이다.

하지만 필드 주입은 외부에서 변경이 불가능하다.

(테스트코드의 중요성이 부각됨에 따라 필드의 필드객체를 수정할 수 없는 필드주입은 거의 사용하지 않게 됨)

또한 필드주입은 반드시 DI 프레임워크가 존재해야 하므로 사용을 지양해야한다!

 

3. Setter주입

Setter메소드에 @Autowired을 붙인다.

 

필드값을 변경하는 Setter를 통해서 의존관계를 주입하는 방법이다.

Setter주입은 생성자 주입과 달리 주입받는 객체가 변경될 가능성이 있는 경우에 사용한다. 

 

 

생성자를 통한 주입을 사용해야 하는 이유

Spring에서 가장 권장하는 방법은 생성자를 통한 주입이다.

 

1. 생성자를 사용하면 필수적으로 사용해야 하는 의존성 없이는 인스턴스를 만들지 못하도록 강제 가능

만약 SampleController가 SampleRepository없이는 제대로 동작할 수 없다면 SampleController에서 생성자를 통해 강제로 SampleRepository를 무조건 주입받은 후에야 인스턴스를 생성할 수 있도록 해야할 것이다. 

 

2. 생성자주입을 통해 변경의 가능성을 배제하고 불변성을 보장할 수 있다.

 

3. final 키워드 작성 및 롬복과의 결합

생성자주입을 사용하면 필드객체에 final키워드를 사용할 수 있다. 이는 컴파일 시점에 누락된 의존성을 확인할수 있다.

반면 생성자 주입을 제외한 다른 주입방법들은 객체생성 이후 (생성자호출이후) 에 호출되므로 final키워드를 사용할 수 없다. ( 객체생성 이후에 필드값을 변하게 하는것이니까!)

 

또한 final키워드를 붙임으로서 Lombok과 결합되어 코드를 더 간결하게 작성할 수 있다.

롬복에는 final변수를 위한 생성자를 대신해주는 @RequiredArgsConstructor가 있다.

 

 

@RequiredArgsConstructor

초기화되지 않은 final 필드나 @NotNull이 붙은 필드에 대해 생성자를 생성

주로 의존성 주입 (Dependency Injection) 편의성을 위해 사용

 

스프링 의존성 주입의 특징 중 한가지를 이용하는데 다음과 같다

어떠한 빈(Bean)에 생성자가 오직 하나만 있고, 생성자의 파라미터 타입이 빈으로 등록 가능한 존재라면 이 빈은 @Autowired 어노테이션 없이도 의존성 주입이 가능하다.

즉 새로운 필드를 추가할 때 다시 생성자를 만들어서 관리해야하는 번거로움을 없애줌!

(@Autowired 사용하지 않고 의존성 주입)

  • Spring Framework의 DI(의존성주입) 중 Constructor Injection(생성자 주입)을 임의의 코드 없이 자동으로 설정
  • @RequiredArgsConstructor이 어떻게 구동하는지 정확히 알아야 예상치 못한 오류를 막을 수 있음

 

추가적으로 롬복 어노테이션이(@Getter 혹은 @Setter 등) 사용할땐 편하지만, 단점도 있다.

setter 메서드가 필요없는 필드에 대해서도 setter 메서드를 강제로 생성하게 되니, 필드 값이 변경될 위험이 생긴다.

이런 부분들은 전부 리팩토링의 대상이지만, 롬복을 사용하게될 경우 리팩토링이 힘들어지는 부분도 있으니 너무 무분별하게 사용하는것은 좋지 않다!

 

 

References : https://esoongan.tistory.com/90, https://medium.com/webeveloper/requiredargsconstructor-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%A3%BC%EC%9E%85-dependency-injection-4f1b0ac33561

자바 ORM 표준 JPA 프로그래밍, 하단의 블로그, 김영한의 실전 JPA1을 참고해서 정리한 글입니다!

 

 

[JPA] 엔티티와 매핑. @Entity, @Table, @Id, @Column..

| 엔티티와 매핑 객체와 테이블 매핑 : @Entity, @Table 기본 키 매핑 : @Id 필드와 컬럼 매핑 : @Column 연관관계 매핑 : @ManyToOne, @JoinColumn 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23..

data-make.tistory.com

1. 엔티티

- 테이블과 매핑

- @Entity가 붙은 클래스는 JPA가 관리하는 것으로 엔티티라고 불림

 

* 속성

Name : JPA에서 사용할 엔티티 이름을 지정. 보통 기본값인 클래스 이름 사용

 

* 주의사항

- 기본 생성자는 필수 (JPA가 엔티티 객체 생성 시 기본 생성자 사용)

- final 클래스, enum, interface, inner class에는 사용 불가

- 저장할 필드에 final 사용 불가

 

2. 테이블

- 엔티티와 매핑할 테이블 지정

- 생략시 매핑한 엔티티 이름을 테이블 이름으로 사용

 

* 속성

Name: 매핑할 테이블 이름 (default, 엔티티 이름 사용)

Catalog: catalog 기능이 있는 DB에서 catalog를 매핑 (default, DB명)

Schema: schema 기능이 있는 DB에서 schema를 매핑

uniqueConstraints: DDL 생성 시 유니크 제약 조건을 만듦. 스키마 자동 생성 기능을 사용해서 DDL 만들 때만 사용

 

** 엔티티와 테이블의 차이?

@Entity

- 우선 필수, @Entity만 사용했을 경우 DB와 연결 시 테이블명은 클래스명과 동일하게 설정

  => @Entity 어노테이션을 사용한 상태에서 클래스명이 CrudEntity일 경우 DB에서 CrudEntity 테이블로 연결!

- @Entity(name = "엔티티명")으로 테이블명을 지정해 줄 경우 이후 EntityManager 등을 이용해 쿼리를 사용하는 경우 createQuery("select .. from 엔티티명") 이렇게 사용 가능

 

@Table

- 외부에서 호출하는 용도가 아닌 실제 DB에 붙을 테이블명 어노테이션

- @Entity

@Table(name = "테이블명")

이렇게 지정을 해 놓을 경우 createQuery(select m from 엔티티클래스명) 으로 호출을 해 주면

호출은 엔티티클래스명으로 하지만 실제 DB에는 테이블명의 테이블로 붙게 된다!

 

3. 엔티티 매핑

 

객체와 테이블 매핑 : @Entity, @Table
기본 키 매핑 : @Id
필드와 컬럼 매핑 : @Column
연관관계 매핑 : @ManyToOne, @JoinColumn

 

@Entity
// name과 age Column에 unique 제약조건 추가
@Table(name="MEMBER", uniqueConstraints = {@UniqueConstraint(
		name = "NAME_AGE_UNIQUE",        
        columnNames = {"NAME", "AGE"} )})
public class Member {     

	// 기본키 매핑    
    @Id    
    @Column(name = "ID")    
    private String id;     
    
    // not null, varchar(10)    
    @Column(name = "NAME", nullable = false, length = 10)    
    private String username;     
    
    private Integer age;     
    
    // Java의 enum 사용    
    @Enumerated(EnumType.STRING)    
    private RoleType roleType;     
    
    // Java의 날짜 타입    
    @Temporal(TemporalType.TIMESTAMP)    
    private Date createdDate;     
    
    @Temporal(TemporalType.TIMESTAMP)    
    private Date lastModifiedDate;     
    
    // CLOB, BLOC 타입 매핑    
    @Lob    
    private String description;     
    
    @Transient    
    private String temp;      
    
    //Getter, Setter
} 

public enum RoleType {
	ADMIN, USER
}

 

4. 데이터베이스 스키마 자동 생성

- JPA는 데이터베이스 스키마를 자동으로 생성하는 기능 지원

- 클래스의 매핑 정보와 데이터베이스 방언을 사용하여 데이터베이스 스키마 생성 

애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성

 

hibernate.hbm2ddl.auto 속성

create : 기존 테이블을 삭제하고 새로 생성(DROP + CREATE)

create-drop : CREATE 속성에 추가로 애플리케이션을 종료할 때 생성한 DDL을 제거  (DROP + CREATE + DROP)

update : DB 테이블과 엔티티 매핑 정보를 비교해서 변경 사항만 수정

validate : DB 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 남기고 애플리케이션을 실행하지 않음.

DDL을 수행하지 않음

none : 자동 생성 기능을 사용하지 않음

 

주의사항

- 개발 초기 단계는 create 또는 update

- 초기화 상태로 자동화된 테스트를 진행하는 개발자 환경과 CI서버는 create 또는 create-drop

- 테스트 서버는 update 또는 validate

- 스테이징과 운영 서버는 validate 또는 none

 

5. 기본 키 매핑

- 영속성 컨텍스트는 엔티티를 식별자 값으로 구분하므로 엔티티를 영속 상태로 만들기 위해 식별자 값 반드시 필요

 

@GeneratedValue

- 기본 키 생성 전략

  * 직접 할당: 기본 키를 애플리케이션에 직접 할당

  => em.persist()를 호출하기 전 애플리케이션에서 직접 식별자 값을 할당해야 함. 식별자 값이 없을 경우 예러 발생

  * 자동 생성: 대리 키 사용 방식

     1) IDENTITY: 기본 키 생성을 데이터 베이스에 위임 (= AUTO_INCREMENT)

     2) SEQUENCE : 데이터베이스 시퀀스를 사용해서 기본 키를 할당, 데이터베이스 시퀀스에서 식별자 값을 획득한 후 영속성 컨텍스트에 저장함. 유일한 값을 순서대로 생성 (오라클, PostgreSQL, DB2, H2)
    3) TABLE : 키 생성 테이블을 사용키 생성 전용 테이블 하나를 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어

데이터베이스 시퀀스를 흉내내는 전략. 테이블을 사용하므로 모든 데이터베이스에 적용 가능

    4) AUTO : 선택한 데이터베이스 방언에 따라 방식을 자동으로 선택(Default)

  Ex) 오라클 DB 선택 시 SEQUENCE, MySQL DB 선택 시 IDENTITY 사용

 

@Column

- 객체 필드를 테이블 컬럼에 매핑

- 속성 중 name, nullable이 주로 사용되고 나머지는 잘 사용되지 않음

    1) name : 필드와 매핑할 테이블 컬럼 이름 (default. 객체의 필드 이름)

    2) nullable (DDL) : null 값의 허용 여부 설정, false 설정 시 not null (default. true)   @Column 사용 시 nullable = false 로 설정하는 것이 안전

    3) unique (DDL) : @Table 의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 적용

    4) columnDefinition (DDL) : 데이터베이스 컬럼 정보를 직접 줄 수 있음, default 값 설정   (default. 필드의 자바 타입과 방언 정보를 사용해 적절한 컬럼 타입을 생성)

    5) length (DDL) : 문자 길이 제약조건, String 타입에만 사용 (default. 255)

    6) percision, scale (DDL) : BigDecimal, BigInteger 타입에서 사용. 아주 큰 숫자나 정밀한 소수를 다룰 때만 사용(default. precision = 19, scale = 2)

 

@Enumerated

 - 자바의 enum 타입을 매핑할 때 사용

   * value : EnumType.ORDINAL : enum 순서를 데이터베이스에 저장

                 EnumType.STRING : enum 이름을 데이터베이스에 저장 (default.EnumType.ORDINAL)

 

@Temporal

 - 날짜 타입(java.util.Date, java.util.Calendar)을 매핑할 때 사용

   * value : TemporalType.DATE : 날짜, 데이터베이스 data 타입과 매핑 (2020-12-18) 

                  TemporalType.TIME : 시간, 데이터베이스 time 타입과 매핑 (23:36:33)

                  TemporalType.TIMESTAMP : 날짜와 시간, 데이터베이스 timestamp 타입과 매핑 (2020-12-18 23:36:33)

                   (default. TemporalType은 필수로 지정)

 

@Temporal 을 생략하면 자바의 Date와 가장 유사한 timestamp로 정의

 

@Lob

 - 데이터베이스 BLOB, CLOB 타입과 매핑

  * 지정 속성이 없음. 대신 매핑하는 필드 타입이 문자면 CLOB, 나머지는 BLOB로 매핑

 

@Transient

 - 이 필드는 매핑하지 않음. 데이터베이스에 저장하지 않고 조회하지도 않음.

 객체에 임시로 어떤 값을 보관하고 싶을 때 사용

 

@Access

 - JPA가 엔티티 데이터에 접근하는 방식 지정

  * 필드 접근 : AccessType.FIELD로 지정, 필드에 직접 접근 (private도 접근 가능)

  * 프로퍼티 접근 : AccessType.PROPERTY로 지정 (접근자 Getter 사용)

 

 

5. 엔티티 설계시 주의점

- 엔티티에는 가급적 Setter 사용 X (Setter가 모두 열려있다 == 변경 포인트가 너무 많아서 유지 보수 어렵다)

 

- 모든 연관 관계는 지연로딩으로 설정! (개중요!!!!!!!! 실제 프로젝트 쓸 때 오류 해결할 때 유용)

  * 즉시로딩(EAGER = 멤버를 조회할 때 연관된 Order 조회를 다 하는 것)는 예측 어렵고 어떤 SQL이 실행될지 추적하기 어렵

  * 실무에서 모든 연관관계는 지연로딩(LAZY)로 설정

  * 문맥상에서 원하는 것만 선택해 가져올 수 있음

  * 연관된 엔티티를 함께 DB에서 조회해야 하면 fetch, join 또는 엔티티 그래프 기능을 사용한다

  * @XToOne 관계는 기본이 즉시로딩이므로 직접 지연로딩으로 설정해야 함

 

- 컬렉션은 필드에서 초기화하자

  * 컬렉션은 필드에서 초기화하는 것이 안전

  * null 문제에서 안전


- 테이블, 컬럼명 생성 전략  (SpringPhysicalNamingStrategy)

  * 스프링부트 신규 설정 (엔티티(필드) -> 테이블(컬럼))

    > 카멜 케이스 => 언더스코어 (memberPoint -> member_point)

    > .(점) => _(언더스코어)

    > 대문자 => 소문자

  * 논리명? => 명시적으로 컬럼, 테이블명을 직접 적지 않으면 ImplicitNamingStrategy 사용

  * 물리명? => 모든 논리명에 적용됨, 실제 테이블에 적용

 

스프링부트 프로젝트의 application.yml을 설정해주었다

datasource의 url로는 db 연결되어있는 주소를 입력하고,

username과 password에는 해당 사용자의 이름, 비밀번호를 입력한다.

 

  • hibernate: ddl-auto : create => 서버 실행할마다 매번 DB를 초기화시킨다는 뜻. 한번 초기화가 이뤄지고 세팅이 완료되면 none으로 바꾸고 실행해주면 된다
  • show_sql: true로 설정하면 개발시에 콘솔에서 로그로 어떤 쿼리가 실행되는지 확인할 수 있어서 유용 (logging을 따로 설정했기에 주석 처리해준다.)
  • format_sql: 로그, 콘솔의 SQL을 좀 더 이쁘게 출력한다 만약 위 설정인 show_sql이 false라면 출력되는 쿼리문이 없으므로, 필요없는 설정이고, 디폴트 값은 false이다

모든 로그 출력은 가급적 로거를 통해 남겨야함

 

Member Entity를 생성한다!

 

MemberRepository도 생성해준다

그리고 ctrl+Shift+T를 눌러서 Test 파일 생성해준다!

@Test는 JUnit4를 사용하면 org.junit.Test를 사용해야함

 

**팁**

tdd를 입력하고 alter+Enter를 누르면 내가 custom한 템플릿을 불러올 수 있다.

설정 > Live templates 에서 custom에 tdd를 추가하면 Template text를 자유롭게 설정할 수 있음!!

 

Ctrl + Alt + V => Extract로 변수 뽑아올 수 있음

 

Test 파일도 설정해주고, application을 실행해주면

 

에러가 난다.

에러 내용을 보면 Transaction에 관한 내용인데,

Entity와 repository에 관한 데이터 전달은 Transaction을 통해 진행되어야 한다.

 

@Transactional annotation 추가해준다!

 

application 실행해주고, 전에 접속했던 h2에 들어가준다 

Member table 생성 확인!

 

Test 파일에 @Transactional 이 들어가있으면 data를 rollback해버린다

@Rollback(false)를 추가해주고 다시 확인해보면

 

table에 data가 추가된 걸 확인할 수 있음! (rollback 안하고 commit)

 

Assertions.assertThat(findMember).isEqualTo(member);

를 test파일에 추가하면, 조회한 멤버와 저장한 멤버가 같을까? => Yes!

 

김영한 실전 스프링부트와 JPA 활용1 수업 듣고 직접 프로젝트 생성하며 작성

개발이나 테스트 용도로 가볍고 편리한 DB이다.

웹 콘솔 화면도 제공해준다.

 

버전 1.4.200을 다운받아준다 !

윈도우 설치 버전: https://h2database.com/h2-setup-2019-10-14.exe

 

설치 후 설치된 경로 폴더 > bin 폴더에 h2.bat을 실행해준다 (맥은 h2.sh)

 

그러면 이렇게 내 ip 주소로 H2 콘솔이 뜬다

JDBC URL에는 연결할 내 프로젝트 파일명로 바꾼다 (test -> jpashop)

 

그러면 jpashop이라는 DB 폴더 생성된 것을 확인할 수 있다!

 

왼쪽 맨 위 빨간색 버튼을 눌러서 연결을 끊고,

그 이후 접속부터는 jdbc:h2:tcp://localhost/~/jpashop 이런식으로 접속해준다!

요즘은 Thymeleaf을 많이 사용하는 추세 

(선택 가능)

Spring에서 Thymeleaf를 미는 중이다

장점으로는 natural templates로 html 내에 마크업을 깨지 않고 그대로 사용할 수 있다.

단점으로는 태그를 완전히 달아줘야함 (ex. <br> </br> 이렇게 마무리 태그 안달아주면 에러난다)

버전 3.0에서는 극복해서 그냥 하나만 달아도 가능

 

이번에는 Thymeleaf로 html 뷰 테스트를 해볼 것이다!

 

우선 기본 Controller 파일을 생성해주고, 코드를 작성한다.

hello라는 uri로 get mapping을 해준다.

 

그리고 templates 하위에 hello.html 파일을 생성한다.

그런 다음 application 실행을 해주고, localhost:8080/hello를 입력하면!

 

Controller에서 받은 data가 hello.html data로 넘겨받고 렌더링된 화면이 보인다!

스프링 부트의 Thymeleaf가 알아서 매핑을 해준다, good... (thymeleaf viewName 매핑)

 

렌더링과 관계없이 정적 페이지에서는 어떻게 설정하고 확인할까?

static > index.html 파일을 추가해준다.

그리고 다시 application 실행을 해주면..!

 

여기서 hello를 클릭해주면 

 

/hello로 바로 이동한다!!

 

**팁**

spring-boot-starterdevtools를 추가하면 매번 코드 수정하고 빌드해야할 필요없이

수정한 파일에 Build > Recompile file 눌러주면 그 부분만 적용돼서 바로 확인 가능!!

 

김영한 실전 스프링부트와 JPA 활용 1 강의 듣고 작성한 글

web 의존성 추가하면 tomcat, mvc도 자동으로 추가된다. => localhost:8080 사용할 때 웹페이지 띄울 수 있도록 해준다

 

스프링 부트 라이브러리

1. spring-boot-starter-web

spring-boot-starter-tomcat: 톰캣 (웹서버)

spring-webmvc: 스프링 웹 MVC

spring-boot-starter-thymeleaf: 타임리프 템플릿 엔진(View)

2. spring-boot-starter-data-jpa

spring-boot-starter-aop

spring-boot-starter-jdbc HikariCP 커넥션 풀 (부트 2.0 기본)

hibernate + JPA: 하이버네이트 + JPA

spring-data-jpa: 스프링 데이터 JPA

3. spring-boot-starter(공통): 스프링 부트 + 스프링 코어 + 로깅

spring-boot spring-core

spring-boot-starter-logging : logback, slf4j

 

테스트 라이브러리

1.spring-boot-starter-test

junit: 테스트 프레임워크

mockito: 목 라이브러리

assertj: 테스트 코드를 좀 더 편하게 작성하게 도와주는 라이브러리

spring-test: 스프링 통합 테스트 지원

 

핵심 라이브러리

스프링 MVC

스프링 ORM

JPA, 하이버네이트

스프링 데이터 JPA

 

기타 라이브러리

H2 데이터베이스 클라이언트 => 다운 받는 H2 데이터베이스 버전이랑 접근하는 클라이언트 버전이랑 안맞으면 충돌 일어날 수 있으니 버전 맞춰줘야함

커넥션 풀: 부트 기본은 HikariCP

WEB(thymeleaf)

로깅 SLF4J & LogBack

테스트

스프링 부트 스타터(https://start.spring.io/) 홈페이지에서 프로젝트에 필요한  라이브러리를 추가하고 생성할 수 있다.

 

최근 Spring Boot & JPA로 웹/앱 애플리케이션을 만들 때 보통 Gradle Project로 사용한다.

언어는 자바, 버전은 2.6.12로 설정해주었다!

버전 같은 경우 높을 수록 인텔리제이에서 호환이 안될 수 있어서 프로젝트 생성 기준 젤 낮은 거로 생성해주자.

Project Metadata에서는 Artifact는 jpashop, Name은 jpabook으로 설정해주고, 자바 버전은 11로 해준다.

 

추가한 dependency 목록

Spring Web, Lombok, Thymeleaf, H2 Database, Spring Data JPA, Validation을 추가해줬다.

 

- Spring Web: Web MVC를 사용하여 웹 어플리케이션을 만드는 데 필요한 스프링부트의 기본적인 요소를 가진다. 내장형 컨테이너로 톰캣을 기본으로 탑재하고 있다! Rest API 서버를 만든다면 필수적인 모듈
- Lombok: 클래스의 Getter/Setter 등을 자동으로 생성해주는 어노테이션들을 제공한다. 자바 특유의 장황한 클래스를 줄여주는 좋은 툴

- Thymeleaf: 뷰 템플릿 엔진으로 컨트롤러가 전달하는 데이터를 이용하여 동적으로 화면을 구성할 수 있게 해준다. html 태그를 기반으로 하여 동적인 View를 제공한다.

- H2 Database: 메모리를 데이터베이스로 사용하는, 즉각 설치되는 데이터베이스이다. 의존성에 추가하는 것만으로도 데이터베이스 설정을 전혀 할 필요 없이 바로 사용 가능! 그러나 개발 전용이기에 어플리케이션이 종료될 때 내부 데이터가 모두 사라진다.

- Spring Data JPA: JPA (Java Persistence API)라고 하며 자바 ORM 기술의 토대를 이루는 기술 명세. Hibernate를 사용하고 있으며 Spring에서는 DB를 다루는 거의 표준 기술. Class Entity를 마치 DB처럼 사용할 수 있는 매우 유용한 도구이지만 학습량이 만만한 도구는 아니다.

- Validation: 프로그래밍에 있어서 가장 필요한 부분으로 특히 java에서는 null 값에 대해서 접근하려고 할 때 NPE가 발생함으로, 이런 부분을 방지하기 위해서 미리 검증을 하는 과정

 

generate 버튼을 클릭하면 zip파일로 다운로드된다. zip파일을 압축해제해주고, 인텔리제이에서 import해준다.

 

 

다음과 같이 프로젝트 목록이 뜨게 된다.

 

build.gradle 파일이다

처음 plugins를 보면 스프링부트 버전, 의존성, 자바 언어를 사용하고 있다고 나와있다! (initializer에서 설정한 값 그대로)

plugin에서 라이브러리에대한 dependency 버전 관리도 가능하다

configurations는 lombok으로 생성된 설정값

repositories에서는 mavenCentral에서 라이브러리를 따오겠다는 의미다

initializer에서 추가한 의존성 목록 확인

 

 

 

Gradle 실행

(왼쪽에서 네번째 로고 클릭)

 

~~Application.java 에 들어가서 실행해준다

 

Tomcat started on 8080~이라는 문구가 뜬다.

로컬에 localhost:8080을 입력해주자!

 

화이트라벨 에러페이지가 뜨면 성공이다

아무것도 설정을 안했기에...!

 

test에서 똑같이 실행해준다. 프로젝트 세팅 완료!

 

External Library에 추가된게 엄청 많은데,

build.gradle에서 추가한 dependency에 보면, 하나의 목록마다 관련된 거 여러개씩 추가된다

 

설정메뉴 > 플러그인 에서 Lombok 설치해준다. (나는 이미 설치되어 있었음)

그리고 설정메뉴 > 빌드, 실행, 배포 > 컴파일러 > 어노테이션 프로세서에서 

어노테이션 처리 활성화 버튼 눌러준다

이러면 프로젝트 설정 끝끝끝이고

 

lombok이 잘 돌아가는지 확인하기 위해 Hello클래스를 작성해주었다

 

main문에 작성을 해주고 실행하면

 

콘솔에서 바로 값 확인 가능!

이렇게 스프링부트 프로젝트 기본 설정 및 출력 확인 완료~!

사진 출처 :  https://velog.io/@courage331/Spring-%EA%B3%BC-Spring-Boot-%EC%B0%A8%EC%9D%B4

Spring

스프링 프레임워크는 자바 플랫폼을 위한 오픈소스 애플리케이션 프레임워크로서 간단히 스프링이라고 불린다.

동적 웹사이트 개발하기 위해 여러 서비스를 제공한다.

 

대표적인 특징

1. DI ( Dependency Injection)
-> 개발자가 Spring 프레임워크에 의존성을 주입하면서 객체 간 결합을 느슨하게 한다.
객체 간 결합이 느슨해지면 코드의 재사용성이 증가하고, 단위 테스트가 용이해짐!

2. IoC ( Inversion of Control )
-> 컨트롤의 제어권이 개발자에게 있는 것이 아닌 프레임워크가 대신해서 해주는 것
Servlet이나 Bean 같은 코드를 개발자가 직접 작성하지 않고, 프레임워크가 대신 수행!
기존에는 자바 코드를 작성할 때 객체의 생성, 의존관계 설정 등을 개발자가 해줘야 했지만,
프레임워크가 대신해준다는 의미이다. (제어의 역전)

3. AOP ( Aspect Oriented Programming )
-> 핵심 기능 제외한 부수적 기능을 프레임워크가 제공해준다.
ex) Spring 프로젝트에 security 적용하거나 logging 등을 추가..
기존 비즈니스 로직 건들지 않고 AOP로 추가 가능

4. 중복 코드 제거
JDBC와 같은 템플릿 사용시 중복되는 코드도 많고 복잡하다. 이를 모두 제거한다!

5. 다른 프레임워크와의 통합
JUnit, Mockito와 같은 유닛 테스트 프레임워크와 통합이 간단하다. => 개발하는 프로그램 품질 향상

 

Spring과 Spring Boot의 차이점

스프링 부트는 단독적이고 상용화 수준의 스픠링 기반 애플리케이션을 단지 실행할 수 있을 정도로 쉽게 만들었다
Spring, Spring Boot Framework 차이점

1. Dependency
Spring의 경우 dependency를 설정해줄 때 설정 파일이 매우 길고, 
모든 dependency에 대해 버전 관리도 하나하나 해줘야 한다

ex) Spring dependency 추가 코드
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.3.5</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.5</version>
</dependency>
(출처 https://www.baeldung.com/spring-vs-spring-boot)

Spring Boot는 보다 더 쉽게 설정하고, 버전 관리도 자동으로 해준다.
ex) Spring Boot web dependency 추가 코드
implementation 'org.springframework.boot:spring-boot-starter-web'

2. Configuration
Spring의 경우 Configuration 설정 매우 길고, 모든 어노테이션 및 빈 등록을 설정해줘야 한다.
Spring Boot의 경우 application.properties 파일이나 application.yml 파일에 설정하면 된다.

ex) Spring Thymeleaft 사용 예시 코드
@Configuration
@EnableWebMvc
public class MvcWebConfig implements WebMvcConfigurer {

    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver templateResolver = 
          new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(applicationContext);
        templateResolver.setPrefix("/WEB-INF/views/");
        templateResolver.setSuffix(".html");
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        templateEngine.setEnableSpringELCompiler(true);
        return templateEngine;
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine());
        registry.viewResolver(resolver);
    }
}
(출처 https://www.baeldung.com/spring-vs-spring-boot)

ex) Spring Boot Thymeleaft 추가 코드
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf

3. AutoConfiguration
Spring Boot로 실행할 수 있는 애플리케이션을 만들기 시작하면 클래스에 @SpringBootApplication이라는 어노테이션을 확인할 수 있다.
이 어노테이션을 제거하고 프로그램을 실행하면, 일반적인 자바 프로그램과 동일하게 실행되며
해당 어노테이션 덕분에 많은 외부 라이브러리, 내장 톰캣 서버 등이 실행될 수 있다!

@Annotation: 주석, 추후 특정 어노테이션을 처리하는 컴파일러가 어노테이션을 읽으면 알맞은 처리 진행
기능이 포함된 건 아니고 프로그램 곳곳에 분산된 기능을 한 곳에 모아서 처리하고 싶을 때 사용

4. 편리한 배포
Spring로 개발한 애플리케이션의 경우, war파일을 Web Application Server에 담아 배포
Spring Boot의 경우, Tomcat, Jetty 같은 내장 WAS를 가지고 있기 때문에 jar 파일로 간편하게 배포 가능
Spring으로 WAS를 정하고, 모든 설정을 마쳐 배포를 하는 것보다 훨씬 간단한 배포 방법이다!

 

결론

Spring은 기존에 EJB (Enterprise Java Bean) 를 대신해 자바 애플리케이션을 더 쉽게 만들 수 있게 해주고,

Spring Boot는 Spring보다 개발자가 개발에만 더욱 더 집중할 수 있도록 도와주는 프레임워크다!

Spring Boot 짱

오늘은 기존 컴퓨터 운영체제 (Window)에 맞는 Apache, Php, Mysql 각각 설치하는 과정을 글로 담아보려 한다. 

 

우선 Apache, Php, Mysql 이란?

Apache: 웹 서버

Php: 프로그래밍 언어

Mysql: 데이터베이스

 

‼️ 설치 먼저 ‼️

 

1) Visual C++ 재배포 가능 패키지 설치

https://www.microsoft.com/ko-KR/download/details.aspx?id=48145

 

Download Visual Studio 2015용 Visual C++ 재배포 가능 패키지 from Official Microsoft Download Center

중요! 아래에서 언어를 선택하면 전체 페이지 내용이 해당 언어로 신속하게 변경됩니다. 독일어러시아어스페인어영어이탈리아어일본어중국어(간체)중국어(번체)체코어터키어포르투갈어(브라

www.microsoft.com

요 페이지에서 다운 가능!

 

2) Apache 설치하기

https://www.apachelounge.com/download/

 

Apache VS16 binaries and modules download

 

www.apachelounge.com

요 페이지에서 각자 컴퓨터 사양 맞게 설치하기!

3) Php 설치하기

https://windows.php.net/download/

 

PHP For Windows: Binaries and sources Releases

PHP 8.1 (8.1.10) Download source code [25.35MB] Download tests package (phpt) [15.12MB] VS16 x64 Non Thread Safe (2022-Aug-30 18:46:44) Zip [29.24MB] sha256: 7cd98bd52d14415fe893c5a92165a1919a478e9edc08d9606426ddc0c7cbd3a0 Debug Pack [23.83MB] sha256: 54ec

windows.php.net

여기서 php 버전 7 다운로드해야 함.

22.09.16 기준 최신 버전 8로 다운하니까 나중에 연결할 때 호환이 안돼서 ,,,, 애먹음

버전 7로 꼭!

 

1. 우선 C 드라이브에 압축해제 해준다

Apache는 Apache24 폴더에,

Php는 php 폴더에,

Mysql은 mysql-8.0.30-win64에 압축 해제 해주었다

 

2. Apache24\conf 폴더에서 httpd.conf 파일을 수정해준다

 

# line 37
자신에게 맞는 설치 경로로 변경
ex) Define SRVROOT "C:/Apache24"

# line 59
웹 서버는 12.34.56.78와 같은 주소를 갖고 있다. 
뒤에 80이 포트번호로, 웹문서를 주고 받기 위한 규약이 80!
Listen 80으로 변경해준다.
ex) Listen 80

# line 218
웹서버를 관리하는 관리자의 이메일 주소를 자신의 이메일로 수정
ex) ServerAdmin asdf@naver.com

# line 227
서버 도메인이 없기에 임시로 localhost로 대체
ex) ServerName localhost:80

 

3. 명령 프롬프트를 **관리자 권한**으로 실행해준다!

실행한 다음, 다음과 같은 명령어 내려준다.

cd /Apache24
cd bin
httpd -k install

 

4. 작업관리자 > 서비스에서 Apache 2.4를 실행하고 localhost를 입력해주면!

(실행하고 실행 중이라 떠야 구동 가능)

 

Apache 실행 완료!

참고로 It Works!가 쓰여져 있는 파일은 Apache24 폴더 내 htdocs 안에 index.html이다

 

5. 압축 받은 Php를 원하는 드라이브에 압축 해제한다.

그리고 파일들 중 php.ini-development 파일을 php.ini로 변경해서 수정!

이때 확장자명 제대로 확인해야 함.

php.ini.txt 이렇게 텍스트로 저장될 수 있어서.. 

계속 이랬어서 오류 났다

# line 752
ex) extension_dir = "C:/php/ext"
로 수정

 

6. httpd.conf 수정

C:/apache24/conf의 httpd.conf 열고 다음과 같이 수정한다.

# line 288
DirectoryIndex 다음에 index.php 추가

# 파일 맨 마지막
PHPIniDir “C:/APM/php”
LoadModule php7_module “C:/APM/php/php7apache2_4.dll”
AddType application/x-httpd-php .html .php
AddHandler application/x-httpd-php .php

 

7. 저장 후 Apache 서비스 재시작

명령프롬프트 관리자 권한으로 실행 후 apache 서버 재시작한다.

명령은 httpd -k restart

 

8. php 실행 테스트

php 인터프리터가 제대로 동작하는지 확인하기 위해 웹문서 공간에 php 파일을 작성한다

# 웹문서 저장공간 주소 => C:/Apache24/htdocs에 php파일 작성
<?php
	phpinfo();
?>

 

완료!

 

9. Mysql 구축

Path 환경변수 추가해준다

실행 (Win키 + r) -> SystemPropertiesAdvanced -> 환경변수 (N)

시스템 변수 -> Path 아래 줄에 추가

C:\mysql-8.0.30-winx64/bin

 

 

10. 메모장으로 C:\mysql-8.0.30-winx64\ (Mysql 루트 디렉토리)에 my.ini 파일 생성

파일 생성 후 아래 내용 작성하기

[mysqld]

# set basedir to your installation path
basedir=C:/APM/mysql

#set datadir to the location of your data directory
datadir=C:/APM/mysql/data

port=3306

 

11. C:\mysql-8.0.30-winx64 (Mysql 루트 디렉토리)에 data 디렉토리 생성

 

12. Mysql 구동을 위해 System DB 생성하기

명령 프롬프트 관리자 권한으로 실행한다

mysqld --initialize

 

13. 자동 생성된 임시 root 비밀번호 취득한다

1) C:\mysql-8.0.30-winx64\data에 생성된 (어쩌구).err 파일 열기

2) '[Note] A temporary password is generated for root@localhost: '다음에 나온 비밀번호가 root 비밀번호'

 

14. Mysql 서비스 등록

mysqld.exe를 실행하는데 이번에는 절대경로를 적어서 실행해야한다.

1) 관리자 권한 명령프롬프트 -> C:\mysql-8.0.30-winx64\bin\mysqld.exe --install

2) net start mysql 실행

3) services.msc 실행, MySQL 서비스 '실행 중' 상태면 성공이다!

 

15. Mysql 로그인해 root 비밀번호 변경

1) mysql -u root -p 실행

2) 위에서 얻은 root 비밀번호 입력

3) 다음 쿼리문 실행 (밑줄은 바꾸고자 하는 root 비밀번호 입려)

ALTER USER 'root'@'localhost' IDENTIFIED BY '비밀번호';

 

15. Mysql 테스트

1. 현재 DB 확인
show databases;

2. 새로운 DB 생성
create database seolki;

3. 생성된 DB 확인
show databases;

 

DB 테이블 생성 확인!

 

16. php.ini에서 mysql 관련 extension dll 사용 활성화

1. C:/php/php.ini 수정

2. Dynamic Extensions 항목 찾기

3. 다음 항목을 찾아 주석 해제 후 저장
;extension = mysqli
;extension = pdo_mysql

4. 관리자 권한 명령프롬프트 -> httpd -k start

 

17. APM 전체 연동 테스트

1)  document root (C:/Apache24/htdocs)에 아래와 같이 mysqltest.php 작성

<?php
    echo "Mysql connection test<br />";
    $db = mysqli_connect("localhost", "root", "<password>", "test");
    if($db) {
        echo "connect success<br />";
    } else {
        echo "connect failed<br />";
    }
    $result = mysqli_query($db, 'SELECT VERSION() as VERSION');
    $data = mysqli_fetch_assoc($result);
    echo $data['VERSION'];
?>

2) 웹브라우저 주소창에 localhost/mysqltest.php 입력하여 접속

위와 같이 나온다면 정상 작동하는 것이다!

'server' 카테고리의 다른 글

ssh 비밀번호 없이 key로 로그인하기  (0) 2023.02.01

1. heroku [remote rejected] master -> master (pre-receive hook declined) 에러

git push heroku master

 (나같은 경우는 git push heroku main) 명령어 치는데 계속 저 에러가 떴다

원인은 브랜치 생성할 때 main 브랜치가 Protected branches로 설정돼서 Developer는 push할 수 없다는 거였다..

그래서 중요도에 따라 Maintainer가 처리하거나 Developer가 직접 처리할 수 있도록 권한 설정할 수 있다 

바로 gitlab에서!

 

GitLab의 Project에서 Settings -> Protected branches로 들어가면 권한을 변경하거나 사용하지 않도록 변경할 수 있다.

이렇게!

근데 난 이렇게 해도 안됐다..

 

2. Node.js application not detected by Heroku 

해도해도 안돼서 에러 내용 구글링하니..

 

Node.js application not detected by Heroku

I created a small site in Visual Studio and used Node.js and Express. I can access it via Visual Studio and with Heroku local web. However, when trying to push it to Heroku, I get the error: Appli...

stackoverflow.com

루트 디렉토리... error에서 이미 방향 제시를 해줬건만 난 이미 루트 디렉토리에 package.json 위치 맞는 줄 알고 계속 나둠

알고보니 node 코드들 있는 폴더 상단에 두라는 거였구먼

이거덕에 해결했다!

 

+ Recent posts