ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백엔드 프로젝트[1] - REST API 기초
    Backend & Infra/Backend 2026. 7. 4. 16:35

    안녕하세요 오늘은 REST API 기초에 대해 공부해보겠습니다.

     

    먼저 스프링은 뭘까요?

    스프링은 Java로 서버를 만들때 반복적인 일들을 줄여주기 위한 프레임워크입니다!

    이번 프로젝트에서는 스프링을 사용하여 진행하였습니다!

     

    먼저 https://start.spring.io 에 접속하여 프로젝트를 만들어줬습니다. 

    들어가면 이런 화면이 뜨는데 그냥 기본 설정을 해서 프로젝트를 생성 누르면 파일을 다운받을 수 있고 이 파일을 vscode나 intellij 등을 통해 열어서 사용하시면 됩니다. 저는 다운을 받아서 압축을 풀고 intellij를 통해 진행하였습니다.

     

    다운받은 것을 열면 파일이 생각보다 많아서 너무 무서웠어요.. 근데 저희는 일단 src/main/java, src/test, pom.xml 이거 3개만 알면 어느정도 할 수 있습니다!

     

    src/main/java는 실제 서비스 코드가 있는 곳! 

     

    src/test는 실제 서비스에는 포함되지 않는 테스트 코드가 있는 곳!

     

    pom.xml은 이 프로젝트에 필요한 목록 등을 정리해두는 곳 입니다. 

     

    일단 바로 실행을 해보았는데 바로 종료코드0과 함께 종료되었습니다. 전 사실 서버가 켜질 줄 알았거든요.. 

    이를 위해 pom.xml을 손봐야 했습니다.

    pom.xml의 dependencies 부분인데요 여기에 저 spring-boot-starter-web이라는 것이 없어서 추가해줬습니다.

    위에부터 하나씩 기능을 설명드릴게요.

     

    spring-boot-starter은 기본 스타터 입니다. 웹 기능은 없습니다!

     

    spring-boot-starter-web은 위의 기본 스타터에 tomcat 서버가 포함되는 것입니다. 즉 제가 처음에 원한대로 서버가 켜진채로 유지되는 것이죠. 

     

    sprint-boot-starter-test는 말그대로 테스트용 입니다. 

     

    이렇게 수정을 하고 실행을 하니 서버가 열리는 것을 확인할 수 있었습니다. 

     

    이제 그럼 API를 만들어보겠습니다. API는 움.. 하나의 기능을 만든다고 생각하시면 좋을 것 같습니다!

     

    먼저 com.library.book_api 안에 컨트롤러라는 이름으로 패키지를 생성하고 BookController라는 Java file을 생성해주었습니다. 그럼 여기서 또 궁금하지 않나요? Controller는 무엇인지..얘는 또 어디서 튀어나온 녀석인지.. Controller는 클라이언트의 요청이 오면 "어떤 URL로 들어왔는지 받아서 적절한 곳으로 연결"해주는 역할을 합니다.

     

    방금 생성한 BookController.java 파일을 열면...

     

    package com.library.book_api.controller;

    public class BookController {

    }

    이렇게 되어 있습니다. 근데 파일 이름에 controller가 들어갔다고 진짜 컨트롤러로 인식되는 건 아니겠지요? 그럼 spring이 이것을 controller로 인식하게 하려면 어떻게 해야할까요?

     

    바로 @ 에노테이션을 사용하는데요. Rest API용 컨트롤러는 두 가지가 있습니다.

    @Controller        // 웹 페이지(HTML)를 반환할 때
    @RestController    // JSON 데이터를 반환할 때 

     

    이렇게 두개가 있고 오늘은 JSON 형태의 데이터를 반환하는 것이 목적이니 @RestController를 사용하겠습니다. 

     

    이제는 HTTP API에 대한 예시를 들기 위해 다음과 같은 코드를 작성해볼게요.

    그럼 여기서 저 @GetMapping은 무슨 역할을 하고 그 밑에 있는 건 뭘까요? 이해가 쉽고 빠르게 예시를 들어 설명하겠습니다.

     

    1. 사용자가 웹 브라우저 창에 http://localhost:8080/books를 입력하고 엔터를 칩니다. (GET 요청)

    2. 스프링 부트가 (@RestController) 안을 뒤져서 /books 주소판(@GetMapping("/books"))을 찾습니다.

    3. 그 바로 밑에 있는 getBooks() 함수를 실행합니다.

    4. 브라우저 화면에 최종적으로 "책 목록입니다!" 라는 글자가 짠! 하고 나타납니다.

     

    그럼 현재 코드는 문자열을 반환하는데 실제 API는 JSON형태를 이용합니다. 그리고 이런 JSON 형태로 반환하기 위해서는 자바 객체가 필요하죠. 그렇다면 책이라는 객체를 표현하기 위해서는 어떤 정보가 필요할까요? 바로 id, 책 이름, 작가 등의 정보가 필요할 것입니다. 중요한 것은 id 입니다. 왜냐하면 id가 있어야지 이 객체들을 구분지어 사용할 수 있거든요. 

     

    그렇다면 이제 Book 이라는 클래스를 만들어보겠습니다.

    모델이라는 패키지 안에 Book.java 파일을 생성하였고 다음과 같이 Book 클래스를 완성하였습니다.

    근데 여기서 궁금한 게 생겼습니다. 왜 private으로 하였을까요? public으로 하면 다른 곳에서 바로 사용 가능하니깐 더 좋은 거 아닌가요? 

    결론부터 말하면 아무나 데이터에 접근/수정을 못하게 하여 보호하려는 목적이 있기 때문입니다. 만약 변수들을 public으로 설정한다면 누구나 book.title = "바보"; 와 같이 수정이 가능한것이죠. 따라서 private을 사용하고 이를 캡슐화라고 합니다. 

     

    그렇다면 또 궁금한 게 생기지 않나요? 그렇다면 private으로 설정되어 있는데 데이터에는 어떻게 접근하고 수정할 수 있을까요?

    바로 @Getter과 @Setter를 사용합니다. 이 이노테이션들이 자물쇠 뒤에 안전한 메소드를 통해 데이터에 접근/수정할 수 있게 해주는 것 입니다. 즉, 데이터에 직접 접근이 아닌 메소드를 통한 접근으로 음.. 간접적으로(?) 접근하는 것이죠.

     

    근데 굳이 왜 이렇게까지 하는 걸까요? 메소드를 통해서 접근하면! 간접적으로 접근하면! 괜찮나요? 어쨌든 데이터를 접근/수정하는 건 똑같은데.. 뭐가 다르다고 저렇게 하는걸까요? 쉬운 예시를 들어서 설명드릴게요. 

     

    만약 public인 상태에서 다음과 같은 상황이 있다고 가정하겠습니다. 

    이렇게 되면 책 제목이 없는 상태로 데이터가 저장되는 문제가 생깁니다. 그럼 메소드를 통해 접근하면 이를 방지할 수 있는지 보겠습니다.

     

    이번에는 private + @Setter인 상태의 상황을 보겠습니다.

    위의 코드를 보면 외부에서는 여전히 똑같이 데이터를 바꾸려고 요청하지만, 중간에 메서드가 한 번 필터링을 해주기 때문에 데이터가 오염되는 것을 완벽하게 막을 수 있는 거죠.

     

    하지만 실제로 이런 메소드를 하나하나 다 작성하기에는 조금 번거롭다고 생각하실수도 있습니다. 따라서 Lombok이라는 라이브러리를 씁니다. 그럼 이건 또 어떻게 사용할까요? 간단합니다! Book 클래스 위에 @Getter, @Setter를 적어주시고 pom.xml의 dependencies 안에 다음과 같이 Lombok을 추가하면 됩니다.

    pom.xml Lombok 추가

     

    그럼 이제는 BookController에서 Book 객체를 반환해보겠습니다. 

    책 목록을 반환하기 위해서는 현재 사용하는 string대신 list가 필요합니다. 근데 지금 저희는 db가 없는 상태이죠? 그럼 어디에 저장할까요? 

    이번 프로젝트에서는 List에 저장을 하겠습니다. 사실 위의 코드에는 하나의 문제가 있습니다. 바로 BookController안에 List가 존재한다는 점인데요. 이렇게 되면 서버가 재시작될 때마다 리스트가 새로 시작됩니다. 즉 비워지는 것이죠. 일단 이 점은 그냥 감안하고 이 프로젝트를 진행하겠습니다. 아마 다다음 프로젝트에서 db를 연결하는 것을 목표로 진행하고 있습니다. 

     

    이제 서버를 시작하면 화면에는 [] 이라는 것만 보입니다. 바로 빈 배열이죠. 아직 객체를 추가하지 않았으니 당연한 결과입니다. 그럼 객체를 추가해야겠죠? 그럼 어떻게 추가하는 것이 좋을까요? 저희는 [] 빈 배열과 아까전에 string같은 것들을 Get을 통해 가져왔스빈다. 그럼 데이터는 Post를 사용하여 추가를 하면 되겠죠? 근데 이 Post 어떻게 해야하는걸까요? 저희는 브라우저를 통해 Post로 데이터를 보낼 수 없습니다. 왜냐하면 주소창을 통해 body를 보낼 수가 없기 때문이죠. 그래서 실무에서는 Postman 또는 Insomnia와 같은 test API를 사용합니다. 저는 지금 intellij를 사용하고 있기 때문에 내장되어 있는 HTTP 클라이언트를 사용하여 test를 진행하겠습니다.

    먼저 book을 등록하기 위한 메소드를 위와 같이 만들었습니다. 여기서 중요한 것은 @RequestBody입니다. 이 친구는 아까의 @RestController와 정반대의 역할을 합니다. HTTP 요청의 body에 담긴 JSON을 자바의 객체로 바꾸어주는 역할을 합니다. 

     

    책을 조회하는 메소드와 책을 추가하는 메소드를 만들고 나서는, id에 해당하는 책을 찾는 메소드와 id에 해당하는 책을 지우는 메소드를 다음과 같이 추가했습니다.

    id에 해당하는 책을 찾는 메소드
    id에 해당하는 책을 지우는 메소드

     

    이제는 test를 해봐야겠죠? test.http라는 이름의 파일을 만들고 다음과 같이 test 파일을 작성하였습니다.

     

    실행하고 브라우저에서 정상 작동하는 것을 볼 수 있었고 코드는 깃허브에 올려두었으니 밑의 링크 참조하셔서 실습해보셔도 좋을 것 같습니다. 다음 단계로는 db연결을 하는 프로젝트로 진행해보겠습니다.

     

    https://github.com/jono03/backend-roadmap.git

     

    GitHub - jono03/backend-roadmap: Step-by-step backend engineering journey from REST API to High-Availability Financial System

    Step-by-step backend engineering journey from REST API to High-Availability Financial System - jono03/backend-roadmap

    github.com

     

    'Backend & Infra > Backend' 카테고리의 다른 글

    백엔드 프로젝트[0]  (0) 2026.07.03
Designed by Tistory.