Sam Park Blog.

Sam의 워드프레스 블로그

Sam Park Blog.

Sam의 워드프레스 블로그

미분류

코딩자율학습 스프링부트3 자바 백엔드 개발 입문 1주차 학습 후기


이전에는 자바 학습에 이어 스프링 부트 1주차 학습 후기를 공유하고자 합니다. 스프링부트까지 학습한후 자바를 이용한 웹서비스를 만들어 볼수 있도록 마지막 4주차 까지 열심히 달려보겠습니다.




1일차 : 스프링 부트 시작하기

스프링 부트의 개념, 개발 환경 설정 방법, 그리고 웹 서비스의 동작 원리에 대해 기본적인 내용들을 학습하였습니다.




  • 스프링 부트란?: 스프링 프레임워크를 보다 쉽고 빠르게 개발할 수 있도록 지원하는 도구입니다. 복잡한 설정을 간소화하여 개발에 집중할 수 있게 해준다는 점에서 매우 유용하다고 생각합니다.
  • 개발 환경 설정: JDK, IntelliJ IDEA와 같은 통합 개발 환경(IDE) 설정부터 자바 버전 관리까지, 초기 환경 설정까지 스프링 부트 개발에 필요한 것들을 완료했습니다.
  • 웹 서비스 동작 원리: 클라이언트-서버, 요청-응답과 같은 웹의 기본적인 흐름을 정리하였습니다.




2일차 : MVC 패턴 이해와 실습

뷰 템플릿과 MVC 패턴의 개념을 익히고, 이를 활용하여 페이지를 직접 구현해 보았습니다.


  • 뷰 템플릿과 MVC 패턴: 화면을 담당하는 뷰(View), 데이터를 처리하는 모델(Model), 그리고 이 둘을 연결하는 컨트롤러(Controller)로 역할이 분리되어 코드가 훨씬 구조적이고 이해하기 쉬웠습니다.
  • MVC 활용 뷰 템플릿 페이지 만들기: 직접 코드를 작성하여 페이지를 구현해 보니, MVC가 실제로 동작하는 것을 확인하여 이해할 수 있었습니다.
  • MVC의 역할과 실행 흐름: 요청이 들어왔을 때 컨트롤러가 이를 받아 모델을 처리하고, 뷰로 전달하는 전체 흐름을 파악하여 웹 개발의 큰 그림을 그릴 수 있었습니다.
  • 레이아웃 적용: 페이지에 레이아웃을 적용하여 보다 완성도 높은 형태를 갖출 수 있었습니다.


<!doctype html>
<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <title>Hello, world!</title>
</head>
<body>
<!-- navigation -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="#">Home</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">Link</a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                        Dropdown
                    </a>
                    <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <li><a class="dropdown-item" href="#">Action</a></li>
                        <li><a class="dropdown-item" href="#">Another action</a></li>
                        <li><hr class="dropdown-divider"></li>
                        <li><a class="dropdown-item" href="#">Something else here</a></li>
                    </ul>
                </li>
                <li class="nav-item">
                    <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
                </li>
            </ul>
            <form class="d-flex">
                <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
                <button class="btn btn-outline-success" type="submit">Search</button>
            </form>
        </div>
    </div>
</nav><!doctype html>
<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <title>Hello, world!</title>
</head>
<body>
<!-- navigation -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container-fluid">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="#">Home</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="#">Link</a>
                </li>
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                        Dropdown
                    </a>
                    <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                        <li><a class="dropdown-item" href="#">Action</a></li>
                        <li><a class="dropdown-item" href="#">Another action</a></li>
                        <li><hr class="dropdown-divider"></li>
                        <li><a class="dropdown-item" href="#">Something else here</a></li>
                    </ul>
                </li>
                <li class="nav-item">
                    <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
                </li>
            </ul>
            <form class="d-flex">
                <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
                <button class="btn btn-outline-success" type="submit">Search</button>
            </form>
        </div>
    </div>
</nav>

/layouts/header.mustache


<!-- site info -->
<div class="mb-5 container-fluid">
    <hr>
    <p>ⓒ CloudString | <a href="#">Privacy</a> | <a href="#">Terms</a></p>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>


</body>
</html>

/layouts/footer.mustache


{{>layouts/header}}
    <div class="bg-dark text-white p5">
        <h1>{{username}}님, 반갑습니다!</h1>
    </div>
{{>layouts/footer}}

/greetings.mustache


{{>layouts/header}}
    <div class="bg-dark text-white p5">
        <h1>{{nickname}}님, 다음에 또 만나요!</h1>
    </div>
{{>layouts/footer}}

/goodbye.mustache




3일차 : 게시판 만들기: 새 글 작성하기 (Create)

실제 게시판 구현의 첫 단계인 새 글 작성(Create) 기능을 학습하였습니다.


  • 폼 데이터란? 웹 페이지에서 사용자로부터 입력받는 데이터를 의미합니다.
  • 폼 데이터를 DTO로 받기: DTO(Data Transfer Object)를 사용하여 데이터를 효율적으로 묶어 관리하는 방법을 익혔습니다.
  • DTO를 데이터베이스에 저장하기: 작성된 DTO 데이터를 데이터베이스에 저장하는 과정을 실습했습니다.


package com.example.firstproject.dto;

import com.example.firstproject.entity.Article;

public class ArticleForm {
    private String title;   // 제목을 받을 필드
    private String content; // 내용을 받을 필드

    // 전송받은 제목과 내용을 필드에 저장하는 생성자 추가
    public ArticleForm(String title, String content) {
        this.title = title;
        this.content = content;
    }

    // 데이터를 잘 받았는지 확인할 toString() 메서드 추가
    @Override
    public String toString() {
        return "ArticleForm{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }

    public Article toEntity() {
        return new Article(null, title, content);
    }
}

/dto/ArticleForm


package com.example.firstproject.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

@Entity
public class Article {
    @Id
    @GeneratedValue
    private Long id;
    @Column
    private String title;
    @Column
    private String content;

    // Article 생성자 추가
    public Article(Long id, String title, String content) {
        this.id = id;
        this.title = title;
        this.content = content;
    }

    // toString() 메서드 추가
    @Override
    public String toString() {
        return "Article{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}

/entry/Article


package com.example.firstproject.controller;

import com.example.firstproject.dto.ArticleForm;
import com.example.firstproject.entity.Article;
import com.example.firstproject.repository.ArticleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class ArticleController {
    @Autowired
    private ArticleRepository articleRepository;

    @GetMapping("/articles/new")
    public String newArticleForm() {
        return "articles/new";
    }

    @PostMapping("/articles/create")
    public String createArticle(ArticleForm form) {
        System.out.println(form.toString());    // DTO에 폼 데이터가 잘 담겼는지 확인
        // 1. DTO를 엔티티로 변환
        Article article = form.toEntity();
        System.out.println(article.toString());     // DTO가 엔티티로 잘 변환되는지 확인 출력
        // 2. 리파지터리로 엔티티를 DB에 저장
        Article saved = articleRepository.save(article);
        System.out.println(saved.toString());       // article이 DB에 잘 저장되는지 확인 출력
        return "";
    }
}

/ArticleController




4일차 : 게시판 만들기 : DB 데이터 조회

데이터베이스에 저장된 데이터를 조회하는 방법을 학습했습니다.



  • DB 데이터 조회하기: 데이터베이스와 상호작용하며 쿼리문(SQL)을 통해 원하는 데이터를 가져오는 연습을 하였습니다.
  • 롬복이란? getter, setter 등 반복적인 코드를 어노테이션을 통해 자동으로 생성해주는 라이브러리입니다. 롬복(Lookbok)은 개발 생산성을 크게 향상시키는 매우 유용한 도구인 것 같습니다.
  • 목복을 활용한 리팩터링하기: 롬복을 적용하여 기존 코드를 더욱 간결하고 가독성 높게 개선했습니다. 코드가 깔끔해지면서 유지보수 측면에서도 이점이 많다는 것을 알 수 있었습니다.


package com.example.firstproject.controller;

import com.example.firstproject.dto.ArticleForm;
import com.example.firstproject.entity.Article;
import com.example.firstproject.repository.ArticleRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Slf4j  // 로깅 기능을 위한 언노테이션 추가
@Controller
public class ArticleController {
    @Autowired
    private ArticleRepository articleRepository;

    @GetMapping("/articles/new")
    public String newArticleForm() {
        return "articles/new";
    }

    @PostMapping("/articles/create")
    public String createArticle(ArticleForm form) {
        log.info(form.toString());
//        System.out.println(form.toString());    // DTO에 폼 데이터가 잘 담겼는지 확인
        // 1. DTO를 엔티티로 변환
        Article article = form.toEntity();
        log.info(article.toString());
//        System.out.println(article.toString());     // DTO가 엔티티로 잘 변환되는지 확인 출력
        // 2. 리파지터리로 엔티티를 DB에 저장
        Article saved = articleRepository.save(article);
        log.info(saved.toString());
//        System.out.println(saved.toString());       // article이 DB에 잘 저장되는지 확인 출력
        return "";
    }
}




5일차: 게시글 읽기(Read)

H2 DB를 이용하여 게시글 읽기(Read) 기능을 학습했습니다.


  • 데이터 조회 과정: 데이터를 데이터베이스에서 가져와 화면에 표시하기까지의 전반적인 과정을 학습했습니다.
  • 단일 데이터 조회: 특정 게시글 하나를 선택하여 상세 내용을 표시하는 방법을 학습했습니다.
  • 데이터 목록 조회하기: 게시판에 존재하는 여러 게시글들을 목록 형태로 보여주는 방법을 익혔습니다. 이를 통해 기본적인 게시판 기능을 구현할 수 있게 되었습니다.


    @GetMapping("/articles/{id}")   // 데이터 조회 요청 접수
    public String show(@PathVariable Long id, Model model) {     // 매개변수로 id 받아 오기
        log.info("id = " + id);     // id를 잘 받았는지 확인하는 로그 찍기
        // 1. id를 조회해 데이터 가져오기
//        Optional<Article> articleEntity = articleRepository.findById(id);
        Article articleEntity = articleRepository.findById(id).orElse(null);
        // 2. 모델에 데이터 등록하기
        model.addAttribute("article", articleEntity);
        // 3. 뷰 페이지 반환하기
        return "articles/show";
    }
    
    @GetMapping("/articles")
    public String index(Model model) {
        // 1. 모든 데이터 가져오기
        List<Article> articleEntityList= articleRepository.findAll();
//        List<Article> articleEntityList = (List<Article>)articleRepository.findAll();
//        Iterable<Article> articleEntityList = articleRepository.findAll();
        // 2. 모델에 데이터 등록하기
        model.addAttribute("articleList", articleEntityList);
        // 3. 뷰 페이지 설정하기
        return "articles/index";
    }




1주차 마무리

이번 1주차 스프링 부트 학습을 통해서 스프링 부트의 기본 개념과 웹 서비스 동작 원리를 이해할 수 있었습니다.

MVC 패턴을 적용하여 뷰 템플릿 페이지를 구현하고, 게시판의 핵심 기능인 Create와 Read를 직접 만들어 보면서 웹 서비스의 기초를 다졌습니다. 특히 롬복 라이브러리를 활용하여 코드 작성 효율성을 크게 높일수 있었던 점이 인상 깊었습니다 .앞으로 남은 CRUD 기능 학습과 더 심화된 내용들을 통해 꾸준히 성장해 나가겠습니다.



답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다