참고 WSL에서 SDKMAN을 사용하여 Java와 Maven을 설치 진행
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk list java
sdk install java 11.0.13-open
sdk list maven
sdk install maven 3.8.4
java -version
mvn -v
위의 단계를 따라하면 WSL에서 SDKMAN을 사용하여 Java와 Maven을 설치할 수 있습니다.
GENERATE
버튼을 클릭하여 프로젝트 환경구성 압축 파일을 받아줍니다.참고
WSL에서 프로젝트를 구성하니. 다운받은 파일이 있는 디렉토리를 윈도우 탐색기 창으로 열어 줍니다. 그리고 WSL 터미널을 열고 Drag and Drop으로 터미널에 붙여 넣어주면 경로가 표시됩니다. 이를 리눅스 명령어를 통해서 옮겨주고 압축해제해 줍니다.
└── com
└── example
└── demo
├── DemoApplication.java
├── api
├── dao
├── model
└── service
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() 메서드를 통해 속성 값을 조회할 수 있습니다. 이러한 모델 클래스는 데이터를 표현하고 가공하는 데 사용됩니다.
클래스(Class):
클래스
는 객체
의 구조와 동작
을 직접 정의``하고
구현하는 데 사용되는 반면,
인터페이스`는 클래스가 가져야 할 동작을 정의하고 해당 동작을 구현하는 클래스에서 사용됩니다. 클래스는 상속을 통해 확장하고 재사용할 수 있으며, 인터페이스는 다중 구현을 통해 클래스의 동작을 보장하고 일관성을 유지합니다. 또한, 인터페이스를 사용함으로써 클래스 간의 결합도를 낮추고 유연성을 높일 수 있습니다.
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)는 그대로 사용하거나 구현 클래스에서 오버라이드하여 사용할 수 있습니다.
default
키워드는 자바 8
에서 도입
된 인터페이스의 기능 중 하나입니다. 인터페이스 내에서 default 키워드를 사용하여 메서드에 기본 구현
을 제공할 수 있습니다.
기본적으로 인터페이스는 추상 메서드만
을 포함
하며, 구현체
에서 이러한 메서드를 구현
해야 합니다. 그러나 자바 8부터
는 default
키워드를 사용하여 인터페이스 내에서 메서드에 기본 구현을 제공
할 수 있게 되었습니다. 이는 인터페이스를 구현하는 클래스에서 해당 메서드를 오버라이딩하지 않아도 되는 편의성을 제공
합니다.
인터페이스의 default 메서드는 다음과 같은 특징을 가지고 있습니다:
default 메서드는 인터페이스 내에 구현됩니다. 따라서 인터페이스를 구현하는 클래스에서 이 메서드를 오버라이딩할 필요가 없습니다.
default 메서드는 일반적인 메서드 구문을 사용하여 정의됩니다. 즉, 메서드 시그니처와 본문을 가질 수 있습니다.
default 메서드는 인터페이스 내에서 호출될 수 있으며, 구현체에서도 선택적으로 호출할 수 있습니다.
클래스가 여러 인터페이스를 구현하고 있을 때, 동일한 시그니처를 가진 default 메서드가 여러 인터페이스에 존재하는 경우, 해당 클래스에서 명시적으로 오버라이딩하여 어느 인터페이스의 메서드를 사용할지 지정해야 합니다.
default 메서드는 기본적인 구현을 제공하면서도 인터페이스의 호환성을 유지하고 새로운 기능을 추가하는 데 유용합니다. 이를 통해 인터페이스를 변경하여 기존의 구현체에 영향을 주지 않고 새로운 기능을 추가할 수 있습니다.
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에 추가하는 기능을 제공합니다. 이를 통해 데이터 액세스 서비스를 가짜로 구현하여 테스트나 개발 환경에서 사용할 수 있습니다.
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 어노테이션을 사용하여 스프링에게 해당 클래스가 서비스 역할을 수행하는 빈임을 알려줍니다. 이렇게 분리된 서비스 계층은 컨트롤러와 데이터 액세스 계층 간의 중간 역할을 수행하며, 비즈니스 로직을 캡슐화하여 유지보수와 테스트를 용이하게 합니다.
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를 통해 추가하는 기능을