티스토리 뷰

Spring

TO-DO 앱 만들어보기 - POST API 생성

몰라모르겠어요 2022. 8. 15. 17:49

DB 선택 기준

데이터베이스를 연결하기 전에 이전에 면접 본 게 생각나서 db 선택 기준을 알아보았다.

면접에서 왜 이 디비를 선택했나? 이랬는데 솔직히 대답을 제대로 못했다...그냥 안써봐서 써보려구요 이게 내 대답이었다.

그래서 한 번 알아보았다.

 

데이터베이스는 저장되는 데이터의 액세스 특성과 패턴으로 봐야 한다.

데이터는 SQL 스키마와 같은 정형 데이터 또는 각각 형태가 다를 수 있는 JSON 객체와 같은 반정형 데이터일 수 있다.

파일 이름과 파일 콘텐츠 관계처럼 크게 다르지 않은 기-값 페어 또는 전체 텍스트 검색을 위한 텍스트 데이터와 같이 정의된 구조가 없을 수도 있다.

 

관계형 데이터베이스

  • 관계형 데이터베이스는 널리 사용되고 있다.
  • 관계형 데이터베이스는 스스로 정의하는 데이터베이스이다.
  • 개발자는 데이터베이스의 스키마를 정의하고 데이터베이스 내의 행과 테이블 간 관계 및 제약 조건을 정의한다.
  • 개발자는 애플리케이션 코드가 아니라 관계형 데이터베이스의 기능에 의존해 스키마를 적용하고 데이터베이스 내 데이터의 참조 무결성을 보존한다.
  • 일반적 사용 사례에는 웹 및 모바일 애플리케이션, 엔터프라이즈 애플리케이션, 온라인 게임이 포함된다.

 

키-값 및 문서 데이터

  • 키-값 데이터베이스는 고도로 분할 가능하며 다른 유형의 데이터베이스로는 불가능한 수준의 수평 확장이 가능하다.
  • 게임, 광고 기술 및 IoT와 같은 사용 사례는 알려진 키 값의 액세스 패턴에 짧은 지연 시간의 GET/PUT이 요구되는 키-값 데이터 모델에 특히 더 적합하다.
  •  

이외데로 다른 데이터베이스 형태가 있지만, 나는 일단 이 정도만 알아보겠다.

 

나는 여태 RDBMS를 주로 썼고, 나중에 커스터마이징해서 수진이 앱과 연동하려면 현재 그 앱에서 쓰고 있는 로컬 디비가 NoSQL이기 때문에 몽고DB를 써보려고 한다.

근데 뭔가 이 어플리케이션에는 관계형 데이터베이스가 더 적절할 것 같기도...

 

몽고 DB 연결하기

먼저 의존성에 몽고 디비 추가해줬다.

몽고 db를 이용하면서 jpa 쓰겠다.

 

몽고 db와의 연결을 위해서(애플리케이션을 구동했을 때 무조건 커넥션 확인하기 때문에) 설치를 해야 했는데, 직접 설치하지 않고 도커를 이용해 몽고 디비 컨테이너를 풀 받았다.

# mongo db docker container 다운
docker pull mongo

# docker container 실행
# -v ~/data:/data/db는 호스트(컨테이너를 구동하는 로컬 컴퓨터)의 ~/data 디렉터리와 컨테이너의 /data/db 디렉터리를 마운트시킨다. 
# 이렇게 볼륨을 설정하지 않으면 컨테이너를 삭제할 때 컨테이너에 저장되어있는 데이터도 삭제되기 때문에 복구할 수 없다.
# mongo는 디폴트로 27017 포트라서 저렇게 설정했다.
docker run --name mongodb-container -v ~/data:/data/db -d -p 27017:27017 mongo

# 실행
docker exec -it mongodb-container bash

# admin으로 들어감
use admin

# root user 생성, 접속하기 위해서
db.createUser( { user: "myadmin", pwd: "########", roles: ["root"] })

# 루트 유저로 접속하기 위해 나온다.
exit

# 루트 유저로 접속
mongo admin -u myadmin -p ########

# 일반 유저도 만들어봄
db.createUser( { user: "myuser", pwd: "########", roles: ["dbOwner"] })

# 접속하기 위해서 테스트 디비를 만들어야 한다.(스프링부트 접속 거부 안나도록, 구동하려고)
# 몽고 디비는 신기하게 바로 유즈하면 만들어지더라고...어렵다..
use test

db 설정을 다했으면 application.yml을 생성해 디비에 접속할 수 있도록 설정 정보를 입력한다.(비밀번호는 알아서..)

spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      authentication-database: admin
      username: myadmin
      password: ########
      database: test

위처럼 해놓으면 어플리케이션 구동이 잘되는 것을 확인할 수 있다.

authentication-database: admin을 하지 않으면 접속이 안돼서 추가해줬다.

 

이렇게 하면 config 파일 필요없이 mongo db 접속이 돼서 어플리케이션 구동이 되고, jpa 이용할 수 있도록 리파지토리 인터페이스를 생성하면 jpa post와 get이 된다.

 

  • ToDoItemRepository
public interface ToDoItemRepository extends MongoRepository<ToDoItem, String> {
}

 

  • ToDoItemService
@Service
public class ToDoItemService {

    @Autowired
    private ToDoItemRepository toDoItemRepository;

    public ToDoItem get(final String id){

//        //디비 없을 때 억지로 만든 것
//        return ToDoItem.builder()
//                .title("아직 디비가 없는 걸")
//                .build();

        return toDoItemRepository.findById(id).orElse(null);
    }

    public ToDoItem create(final ToDoItem toDoItem){
        if(toDoItem == null){
            throw new NullPointerException("To Do Item can not be null!");
        }

        return toDoItemRepository.insert(toDoItem);
    }

    public List<ToDoItem> getAll(){
        return toDoItemRepository.findAll();
    }
}

 

  • ToDoItemController
@RestController
@RequestMapping("/todo")
public class ToDoItemController {

    @Autowired
    private ToDoItemService toDoItemService;

    @RequestMapping(method = RequestMethod.GET, value = "/{id}")
    @ResponseBody
    public ToDoItemResponse get(@PathVariable(value = "id") String id){
        List<String> errors = new ArrayList<>();
        ToDoItem toDoItem = null;

        try{
            toDoItem = toDoItemService.get(id);
        }catch(final Exception e){
            errors.add(e.getMessage());
        }

        return ToDoItemAdapter.toDoItemResponse(toDoItem, errors);
    }

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public List<ToDoItemResponse> getAll(){
        List<String> errors = new ArrayList<>();
        List<ToDoItem> toDoItems = toDoItemService.getAll();
        List<ToDoItemResponse> toDoItemResponses = new ArrayList<>();

        toDoItems.stream().forEach(toDoItem -> {
            toDoItemResponses.add(ToDoItemAdapter.toDoItemResponse(toDoItem, errors));
        });

        return toDoItemResponses;
    }

    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public ToDoItemResponse create(@RequestBody final ToDoItemRequest toDoItemRequest){
        List<String> errors = new ArrayList<>();
        ToDoItem toDoItem = ToDoItemAdapter.toToItem(toDoItemRequest);

        try{
            toDoItem = toDoItemService.create(toDoItem);
        }catch (final Exception e){
            errors.add(e.getMessage());
        }

        return ToDoItemAdapter.toDoItemResponse(toDoItem, errors);
    }
}

POST를 할 수 있도록 서비스와 컨트롤러 코드도 추가해주었다.

 

 

위 프로젝트는 참고 사이트를 따라해보며 개발 중이다. 그러나 버전이나 방식을 조금씩 나에게 맞춰서 바꿔가며 따라하고 있다.

https://imasoftwareengineer.tistory.com/37?category=772561

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함