Spring Boot Tutorial for Beginners(Java Framework)

Hyeseong·2023년 5월 18일
0

목차

java 설치

참고 WSL에서 SDKMAN을 사용하여 Java와 Maven을 설치 진행

  1. WSL 설치 :
  • WSL을 사용하기 위해 Windows 10에서 WSL을 설치해야 합니다. 자세한 내용은 Microsoft 공식 문서를 참조.
  1. SDKMAN 설치:
  • WSL 터미널을 열고 다음 명령어를 실행하여 SDKMAN을 설치합니다:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
  1. SDKMAN 설정
  • SDKMAN을 초기화하고 적절한 환경 변수를 설정하기 위해 다음 명령어를 실행합니다:
source "$HOME/.sdkman/bin/sdkman-init.sh"
  1. Java 설치:
  • 다음 명령어를 사용하여 설치 가능한 Java 버전 목록을 확인합니다:
sdk list java
  • 원하는 Java 버전을 선택하고 다음 명령어를 실행하여 설치합니다(예: Java 11 설치):
sdk install java 11.0.13-open
  1. Maven 설치:
  • 다음 명령어를 사용하여 설치 가능한 Maven 버전 목록을 확인합니다:
sdk list maven
  • 원하는 Maven 버전을 선택하고 다음 명령어를 실행하여 설치합니다(예: Maven 3.8.4 설치):
sdk install maven 3.8.4
  1. 설치 확인:
  • Java와 Maven이 정상적으로 설치되었는지 확인하기 위해 다음 명령어를 실행합니다:
java -version
mvn -v

위의 단계를 따라하면 WSL에서 SDKMAN을 사용하여 Java와 Maven을 설치할 수 있습니다.

spring initializr

  • 아래 웹사이트에 접속하여 spring initizlizr를 통하여 프로젝트 구성을 쉽게 할 수 있습니다.
  • https://start.spring.io/

1단계

  • 원하는 사항들을 선택하여 프로젝트를 구성함

2단계

  • 구성 설정을 마무리 하기 위해 화면 하단의 GENERATE 버튼을 클릭하여 프로젝트 환경구성 압축 파일을 받아줍니다.

3단계

참고
WSL에서 프로젝트를 구성하니. 다운받은 파일이 있는 디렉토리를 윈도우 탐색기 창으로 열어 줍니다. 그리고 WSL 터미널을 열고 Drag and Drop으로 터미널에 붙여 넣어주면 경로가 표시됩니다. 이를 리눅스 명령어를 통해서 옮겨주고 압축해제해 줍니다.

  • zip 파일을 압축해제 하여 intellJ를 통하여 압축해제된 디렉토리를 선택하여 프로젝트 개발을 시작합니다.

패키지 생성

└── com
    └── example
        └── demo
            ├── DemoApplication.java
            ├── api
            ├── dao
            ├── model
            └── service

model 생성

package com.example.demo.model;

import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.UUID;

public class Person {
    private final UUID id;
    private final String name;

    public Person(
        @JsonProperty("id") UUID id,
        @JsonProperty("name") String name
    ){
        this.id = id;
        this.name = name;
    }

    public UUID getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

위의 코드는 com.example.demo.model 패키지에 있는 Person 클래스를 정의하는 예시입니다. 해당 클래스는 다음과 같은 멤버 변수와 생성자, 메서드를 가지고 있습니다:

  • private final UUID id: UUID 타입의 변수로, 객체의 고유 식별자를 나타냅니다. final 키워드로 선언되어 값을 변경할 수 없습니다.
    private final String name: 문자열 타입의 변수로, 객체의 이름을 나타냅니다. final 키워드로 선언되어 값을 변경할 수 없습니다.
    클래스에는 다음과 같은 생성자와 메서드가 정의되어 있습니다:

  • 생성자: @JsonProperty 어노테이션을 사용하여 JSON 속성과 클래스의 멤버 변수를 매핑합니다. 생성자의 인자로 id와 name을 받아 초기화합니다. 이를 통해 JSON 데이터를 Person 객체로 역직렬화할 때 속성의 값을 할당할 수 있습니다.

  • getId() 메서드: 객체의 id 값을 반환합니다.

  • getName() 메서드: 객체의 name 값을 반환합니다.

이렇게 정의된 Person 클래스는 UUID와 name 속성을 가지고 있는 데이터 모델을 나타냅니다. @JsonProperty 어노테이션을 사용하여 JSON 데이터와의 매핑을 지정하고, getId()와 getName() 메서드를 통해 속성 값을 조회할 수 있습니다. 이러한 모델 클래스는 데이터를 표현하고 가공하는 데 사용됩니다.

톺아보기 - 1

클래스와 인터페이스 차이

  • 자바에서 클래스와 인터페이스는 둘 다 객체 지향 프로그래밍에서 중요한 개념이지만, 목적과 구조에서 차이가 있습니다.

클래스

클래스(Class):

  • 클래스는 객체를 생성하기 위한 템플릿 또는 청사진(blueprint) 역할을 합니다.
  • 객체의 속성을 나타내는 필드(Field)와 객체의 동작을 나타내는 메서드(Method)를 포함할 수 있습니다.
  • 인스턴스화(Instantiation)하여 객체를 생성하고 해당 객체의 상태와 동작을 정의할 수 있습니다.
  • 단일 클래스나 클래스 계층 구조로 구성되어 있으며, 다중 상속을 지원하지 않습니다.
  • 클래스는 다른 클래스를 상속받아 기능을 확장하고 재사용할 수 있습니다.
  • 클래스의 인스턴스는 클래스의 타입으로 사용될 수 있습니다.

인터페이스(Interface)

  • 인터페이스는 클래스가 구현해야 하는 동작의 명세(specification)를 정의하는 역할을 합니다.
  • 클래스가 인터페이스를 구현(Implement)함으로써 해당 인터페이스의 동작을 갖는 것을 보장합니다.
  • 인터페이스는 추상 메서드(Abstract Method)와 상수(Constant)로 구성됩니다. (Java 8부터는 디폴트 메서드(Default Method)와 정적 메서드(Static Method)도 포함할 수 있습니다.)
  • 클래스는 다중 인터페이스를 구현할 수 있으며, 이를 통해 다중 상속의 일부 기능을 대체할 수 있습니다.
  • 인터페이스는 동작의 일관성을 유지하고 클래스 간의 결합도를 낮추는 역할을 합니다.
  • 인터페이스의 인스턴스는 인터페이스의 타입으로 사용될 수 있습니다. (다형성)

클래스객체구조와 동작을 직접 정의``하고 구현하는 데 사용되는 반면, 인터페이스`는 클래스가 가져야 할 동작을 정의하고 해당 동작을 구현하는 클래스에서 사용됩니다. 클래스는 상속을 통해 확장하고 재사용할 수 있으며, 인터페이스는 다중 구현을 통해 클래스의 동작을 보장하고 일관성을 유지합니다. 또한, 인터페이스를 사용함으로써 클래스 간의 결합도를 낮추고 유연성을 높일 수 있습니다.

PersonDao 인터페이스 정의

package com.example.demo.dao;

import com.example.demo.model.Person;

import java.util.UUID;

public interface PersonDao {
    int insertPerson(UUID id, Person person);
    default int insertPerson(Person person){
        UUID id = UUID.randomUUID();
        return insertPerson(id, person);
    }
}
  • 인터페이스는 PersonDao 이름으로 선언되었으며, com.example.demo.dao 패키지에 위치합니다.

  • 인터페이스에는 두 개의 메서드가 포함되어 있습니다:

    • insertPerson(UUID id, Person person): 이 메서드는 UUID 타입의 id와 Person 객체를 매개변수로 받고 정수를 반환합니다. 이 메서드는 주어진 id와 person 데이터를 데이터 저장소에 삽입하는 역할을 합니다. 이 메서드의 구현은 이 인터페이스를 구현하는 클래스에서 제공되어야 합니다.

    • default int insertPerson(Person person): 이는 인터페이스에 정의된 디폴트 메서드입니다. 이 메서드는 Person 객체 하나만 매개변수로 받습니다. 메서드 내에서는 UUID.randomUUID()를 사용하여 랜덤한 UUID를 생성하고, 생성된 id와 제공된 person 객체를 가지고 insertPerson(UUID id, Person person) 메서드(첫 번째 메서드)를 호출합니다. 이 메서드의 디폴트 구현은 내부적으로 고유한 UUID를 생성하여 사람을 삽입하는 편리한 방법을 제공합니다.

이 인터페이스를 사용하면 요구사항에 맞게 PersonDao 인터페이스를 구현하는 다른 클래스의 구현을 정의할 수 있습니다. 각각의 구현은 데이터 저장소에 사람을 삽입하는 자체 로직을 제공할 수 있습니다. 디폴트 메서드 insertPerson(Person person)는 그대로 사용하거나 구현 클래스에서 오버라이드하여 사용할 수 있습니다.

톺아보기-2

interface의 default 키워드?

default 키워드는 자바 8에서 도입된 인터페이스의 기능 중 하나입니다. 인터페이스 내에서 default 키워드를 사용하여 메서드에 기본 구현을 제공할 수 있습니다.

기본적으로 인터페이스는 추상 메서드만포함하며, 구현체에서 이러한 메서드를 구현해야 합니다. 그러나 자바 8부터default 키워드를 사용하여 인터페이스 내에서 메서드에 기본 구현을 제공할 수 있게 되었습니다. 이는 인터페이스를 구현하는 클래스에서 해당 메서드를 오버라이딩하지 않아도 되는 편의성을 제공합니다.

인터페이스의 default 메서드는 다음과 같은 특징을 가지고 있습니다:

  1. default 메서드는 인터페이스 내에 구현됩니다. 따라서 인터페이스를 구현하는 클래스에서 이 메서드를 오버라이딩할 필요가 없습니다.

  2. default 메서드는 일반적인 메서드 구문을 사용하여 정의됩니다. 즉, 메서드 시그니처와 본문을 가질 수 있습니다.

  3. default 메서드는 인터페이스 내에서 호출될 수 있으며, 구현체에서도 선택적으로 호출할 수 있습니다.

  4. 클래스가 여러 인터페이스를 구현하고 있을 때, 동일한 시그니처를 가진 default 메서드가 여러 인터페이스에 존재하는 경우, 해당 클래스에서 명시적으로 오버라이딩하여 어느 인터페이스의 메서드를 사용할지 지정해야 합니다.

default 메서드는 기본적인 구현을 제공하면서도 인터페이스의 호환성을 유지하고 새로운 기능을 추가하는 데 유용합니다. 이를 통해 인터페이스를 변경하여 기존의 구현체에 영향을 주지 않고 새로운 기능을 추가할 수 있습니다.

FakePersonDataAccessService dao 정의

package com.example.demo.dao;

import com.example.demo.model.Person;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class FakePersonDataAccessService implements PersonDao{
    private static List<Person> DB = new ArrayList<>();

    @Override
    public int insertPerson(UUID id, Person person){
        DB.add(new Person(id, person.getName()));
        return 1;
    }
}

위의 코드는 com.example.demo.dao 패키지에 FakePersonDataAccessService 클래스를 정의하는 예시입니다. 해당 클래스는 PersonDao 인터페이스를 구현하고 있습니다. 코드를 간단히 설명하면 다음과 같습니다:

  • import com.example.demo.model.Person;: com.example.demo.model.Person 클래스를 사용하기 위해 해당 패키지를 import하고 있습니다.

  • import java.util.ArrayList;: java.util.ArrayList 클래스를 사용하기 위해 해당 패키지를 import하고 있습니다.

  • import java.util.List;: java.util.List 인터페이스를 사용하기 위해 해당 패키지를 import하고 있습니다.

  • import java.util.UUID;: java.util.UUID 클래스를 사용하기 위해 해당 패키지를 import하고 있습니다.

  • public class FakePersonDataAccessService implements PersonDao: FakePersonDataAccessService 클래스가 PersonDao 인터페이스를 구현하고 있음을 선언하고 있습니다.

  • private static List DB = new ArrayList<>();: List 타입의 DB라는 이름의 private 정적 변수를 선언하고, ArrayList 객체를 생성하여 초기화하고 있습니다.

  • @Override: insertPerson 메서드가 PersonDao 인터페이스의 추상 메서드를 오버라이딩함을 표시하고 있습니다.

  • public int insertPerson(UUID id, Person person): UUID와 Person 객체를 매개변수로 받아서 Person 객체를 DB에 추가하는 메서드를 정의하고 있습니다. @Override 키워드를 사용하여 PersonDao 인터페이스의 insertPerson 메서드를 구현하고 있습니다.

  • DB.add(new Person(id, person.getName()));: DB에 새로운 Person 객체를 생성하여 추가하는 코드입니다. 생성된 Person 객체는 매개변수로 전달받은 id와 person 객체의 이름으로 초기화됩니다.

  • return 1;: 메서드가 성공적으로 실행되었음을 나타내기 위해 1을 반환합니다.

위의 코드는 FakePersonDataAccessService 클래스가 PersonDao 인터페이스를 구현하여 insertPerson 메서드를 재정의하고, 해당 메서드를 사용하여 Person 객체를 DB에 추가하는 기능을 제공합니다. 이를 통해 데이터 액세스 서비스를 가짜로 구현하여 테스트나 개발 환경에서 사용할 수 있습니다.

Service 정의

package com.example.demo.service;

import com.example.demo.dao.PersonDao;
import com.example.demo.model.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class PersonService {

    private final PersonDao personDao;

    @Autowired
    public PersonService(@Qualifier("fakeDao") PersonDao personDao) {
        this.personDao = personDao;
    }

    public int addPerson(Person person){
        return personDao.insertPerson(person);
    }
}

위의 코드는 com.example.demo.service 패키지에 있는 PersonService 클래스를 정의하는 예시입니다. 해당 클래스는 다음과 같은 멤버 변수와 생성자, 메서드를 가지고 있습니다:

  • private final PersonDao personDao: PersonDao 인터페이스를 구현한 객체를 저장하기 위한 변수입니다.

  • @Autowired 어노테이션을 사용한 생성자: PersonDao 구현체를 주입받습니다. @Qualifier 어노테이션을 사용하여 PersonDao의 구현체 중 "fake"로 지정된 빈을 주입받습니다. 이렇게 주입받은 PersonDao 객체는 personDao 멤버 변수에 저장됩니다.

  • addPerson(Person person) 메서드: Person 객체를 인자로 받아 personDao.insertPerson() 메서드를 호출하여 해당 객체를 저장합니다. 저장한 결과를 반환합니다.

PersonService 클래스는 비즈니스 로직을 담당하는 서비스 클래스입니다. PersonDao 인터페이스를 주입받아 데이터 저장에 사용하고, addPerson(Person person) 메서드를 통해 Person 객체를 저장하는 기능을 제공합니다. @Service 어노테이션을 사용하여 스프링에게 해당 클래스가 서비스 역할을 수행하는 빈임을 알려줍니다. 이렇게 분리된 서비스 계층은 컨트롤러와 데이터 액세스 계층 간의 중간 역할을 수행하며, 비즈니스 로직을 캡슐화하여 유지보수와 테스트를 용이하게 합니다.


Controller 정의

package com.example.demo.api;

import com.example.demo.model.Person;
import com.example.demo.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/api/v1/persion")
@RestController
public class PersonController {
    private final PersonService personService;

    @Autowired
    public PersonController(PersonService personService) {
        this.personService = personService;
    }

    @PostMapping
    public void addPerson(
            @RequestBody Person person){
        personService.addPerson(person);
    }
}

설명

임포트

  • com.example.demo.api 패키지에 PersonController 클래스가 속해 있음을 나타냅니다.

  • com.example.demo.model.Person과 com.example.demo.service.PersonService를 import 하고 있습니다. 이는 해당 클래스들을 사용하기 위해 필요한 import 문입니다.

  • @RestController 어노테이션은 해당 클래스가 REST 컨트롤러임을 나타냅니다. 이 어노테이션은 Spring MVC에서 제공하는 @Controller와 @ResponseBody 어노테이션의 결합입니다.

  • @RequestMapping("/api/v1/person") 어노테이션은 해당 컨트롤러의 엔드포인트 경로를 /api/v1/person으로 설정합니다. 이는 클라이언트가 해당 경로로 HTTP 요청을 보낼 때 이 컨트롤러에서 처리할 수 있음을 의미합니다.

  • PersonService를 주입받기 위해 생성자 인젝션을 사용합니다. @Autowired 어노테이션은 Spring에게 PersonService의 인스턴스를 주입하도록 지시합니다.

  • @PostMapping 어노테이션은 해당 메서드가 POST 요청을 처리함을 나타냅니다. 클라이언트가 POST 요청을 /api/v1/person 엔드포인트로 보낼 때 이 메서드가 호출됩니다.

  • @RequestBody 어노테이션은 요청 본문에 포함된 데이터를 Person 객체로 매핑합니다. 이는 클라이언트가 POST 요청 본문에 JSON 형식으로 Person 객체를 전송할 수 있도록 합니다.

  • addPerson 메서드는 PersonService의 addPerson 메서드를 호출하여 Person 객체를 추가합니다. 이는 비즈니스 로직을 PersonService에서 처리하도록 위임하는 역할을 합니다.

위의 코드는 클라이언트가 POST 요청을 /api/v1/person 엔드포인트로 보내면 요청 본문에 포함된 Person 객체를 PersonService를 통해 추가하는 기능을

profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글