상세 컨텐츠

본문 제목

프로그래머 도전기 105일차

프로그래머가 될거야!

by Choyee 2024. 1. 22. 17:52

본문

오늘은

 

학원 수료가 이제 한달도 채 남지 않았습니다

수료가 다가오면서 파이널 프로젝트 기간도 있고

설도 있기 때문에 

취업 준비의 압박이 더욱 커질것으로 예상이 됩니다

그리고 동시에 정신이 없을 것 같다는 생각이 들어 긴장이 됩니다

 

 

Spring Boot 공부

 

* 검색
search form

<form action="/board/pagelist" method="get">// 자기 자신에게 보내줌
    <input type="text" name="keyword">
    <input type="submit" value="Search">
</form>



* 파일 업로드
게시판 - 업로드, 수정

<form action="/board/write" method="" enctype="multipart/form-data">
	<input type="file" name="boardFile">
</form>



MultipartFile 클래스
파라미터 2개
(BoarDTO, MultipartFile boardFile)
1. 파일 저장 - 지정한 폴더 (서버)
2. 파일 이름 -> db에 저장 -> 이름 출력
(=> 파일이 직접적으로 db에 저장되는 것은 아님)

 

* BoardController

// 글쓰기 처리
@PostMapping("/write")
public String write(@Valid BoardDTO boardDTO, 
                    MultipartFile boardFile,
                    BindingResult bindingResult) throws IOException, Exception {
    // 에러 처리
    if(bindingResult.hasErrors()) {
        log.info("has errors......");
        return "/board/write";   // error가 있으면 writeForm 폼으로 이동
    }

    // 글쓰기 처리
    boardService.save(boardDTO, boardFile);
    return "redirect:/board/pagelist";
}



* 동시에 파일을 업로드 했을 때 파일 이름 중복 방지
UUID 클래스 + 파일이름
System.currentmiliseconds() + 파일이름

 

* BoardService

public void save(BoardDTO boardDTO, MultipartFile boardFile) throws Exception, IOException {
    // 1. 파일 저장 -> 서버
    if(!boardFile.isEmpty()) {  // 전달 된 파일이 있으면
        // 저장 경로 (1. server에 만드는 방법, 2. 하드디스크에 만드는 방법)
        String filepath = "C:\\bootworks\\bootboard\\src\\main\\resources\\static\\upload\\";
        UUID uuid = UUID.randomUUID();  // 무작위 아이디 생성 = 중복파일의 이름 방지
        String filename = uuid + "_" + boardFile.getOriginalFilename();  // 원본 파일

        // File 클래스 객체 생성
        File savedFile = new File(filepath, filename);   // upload 폴더에 저장
        boardFile.transferTo(savedFile);

        // 2. 파일 이름 저장 -> DB
        boardDTO.setFilename(filename);
        boardDTO.setFilepath("/upload/" + filename); // 파일 경로 설정
    }

    //dto -> entity 변환 메서드 필요
    Board board = Board.toSaveEntity(boardDTO);
    // entity를 db에 저장
    boardRepository.save(board);
}




<업로드 파일 수정>
* 수정 시 문제점
= 이미지가 사라지는 문제
=> service에서 처리

 

* BoardService

public void update(BoardDTO boardDTO, MultipartFile boardFile) throws Exception, IOException {
    // save() = 삽입(id가 없는 경우), 수정(id가 있는 경우)로 나뉨
    Board board = null;
    // 1. 파일 저장 -> 서버
    if(!boardFile.isEmpty()) {  // 전달 된 파일이 있으면
        // 저장 경로 (1. server에 만드는 방법, 2. 하드디스크에 만드는 방법)
        String filepath = "C:\\bootworks\\bootboard\\src\\main\\resources\\static\\upload\\";
        UUID uuid = UUID.randomUUID();  // 무작위 아이디 생성 = 중복파일의 이름 방지
        String filename = uuid + "_" + boardFile.getOriginalFilename();  // 원본 파일

        // File 클래스 객체 생성
        File savedFile = new File(filepath, filename);   // upload 폴더에 저장
        boardFile.transferTo(savedFile);

        // 2. 파일 이름 저장 -> DB
        boardDTO.setFilename(filename);
        boardDTO.setFilepath("/upload/" + filename); // 파일 경로 설정
    }else {
        // 수정할 파일이 없으면 게시글 번호 경로만 보여줌
        boardDTO.setFilepath(findById(boardDTO.getId()).getFilepath());
    }
    // dto->entity
    board = Board.toUpdateEntity(boardDTO);
    boardRepository.save(board);
}

 

 

 

 

 

 

 

 

React 공부

 

<<Page Routuing>>
페이지 라우팅

* Router
= 데이터의 경로를 실시간으로 지정해주는 역할을 하는 무언가

* Routing
= 어떤 네트워크 내에서 통신 데이터를 보낼 경로를 선택하는 일련의 과정
   경로를 정해주는 행위 자체와 그런 과정들을 다 포함하여 일컫는 말

* Page Routing
- 인터넷을 사용해서 웹 사이트에 접속한다
  = 브라우저를 통해서 웹 서버에게 경로를 요청을 보내고 웹을 받아보는 과정

* SPA
= Single Page Application
= 단일 페이지 어플리케이션
   페이지가 1개인 간단한 어플리케이션
=> 다른 페이지 요청을 해도 같은 html을 반환
=> 페이지 요청시 서버를 통하지 않고 React App에서 페이지를 업데이트 하는 것
     = 페이지 전환 자체가 빨라진다
     => 데이터가 필요한 경우 = 서버와 데이터만 주고받게된다

* CSR
= Client Side Rendering
=> 브라우저, 클라이언트 측에서 알아서 페이지를 렌더링 하는 것



<React Router>
= React애플리케이션에서 페이지 네비게이션을 관리하기 위한 라이브러리
   React애플레키이션에서 다양한 페이지 간의 전환 및 라우팅을 쉽게 구현할 수 있다
=> React Router는 React 컴포넌트를 사용하여 URL과 컴포넌트 간의 매핑을 정의하고 
     페이지간의 전환을 처리한다

* 라우팅(Routing)
= 웹 애플리케이션에서 사용자가 특정 URL로 이동할 때 해당하는 화면이나 컴포넌트를 보여주는 프로세스를 의미
   즉, 사용자가 애플레케이션 내에서 다른 페이지로 이동할 때,
   해당 페이지에 맞는 컴포넌트를 동적으로 로드하고 렌더링하는 것을 말한다

* 설치 명령어
= npm install react-router-dom@6(버전)
=> package.json - dependencies 에서 확인

* 주요 컴포넌트
1. BrowserRouter
   = HTML의 History API를 사용하여 브라우저의 주소 표시줄을 업데이트하고, UI를 렌더링하는데 사용
2. Route
   = 특정 URL에 대해 어떤 컴포넌트를 렌더링할지 정의
      주어진 URL 경로에 대해 특정 컴포넌트를 연결
3. Link
   = 사용자가 클릭할 수 있는 링크를 제공
      클릭 시에 React Router는 지정된 URL로 이동하고 해당하는 컴포넌트를 렌더링

* ex

import React from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';

const Home = () => <div>홈 페이지</div>;
const About = () => <div>소개 페이지</div>;

const App = () => (
  <Router>
    <div>
      <nav>
        <ul>
          <li><Link to="/">홈</Link></li>
          <li><Link to="/about">소개</Link></li>
        </ul>
      </nav>

      <Route path="/" exact component={Home} />
      <Route path="/about" component={About} />
    </div>
  </Router>
);

export default App;



=> BrowserRouter -> 라우팅 설정 
     Link 컴포넌트 -> 페이지 간 이동 가능
     Router 컴포넌트 -> 각 URL에 대한 컴포넌트 매핑



<<Emotion Diary Project>>
* 페이지로 사용될 component
- Home.js
- New.js
- Edit.js
- Diary.js

* 페이지 라우팅
1. 브라우저 url과 react app을 연결하는 기능을 하는 browser router라는 component로
   app component가 return하는 부분을 감싸준다
   => 감싸져 있는 부분들은 브라우저 url과 매핑될 수 있다

2. pages 들을 app.js에 import 해준다

3. 페이지 경로 매핑
   브라우저의 url이 바뀌게 되면 어떤 component를 rendering 해서
   그 component가 페이지 역할을 하게 할 것인지 결정하기 위해서
   <Routes>component로 <Route>component를 감싸준다
   그리고 <Route> component 태그 안에 url경로를 적어준다

* Route
= 실질적으로 url경로와 component를 mapping시켜주는 component
=> <Route path="/root" element={<component/>} />

* 매핑된 경로에 따라 바뀌는 페이지는 
  <Routes>component로 감싸져 있는 부분만 해당되기 때문에
  어떤 페이지를 가도 공통으로 보여주고 싶은 부분은
  <Routes>component 밖으로 빼주면 된다

4. 페이지를 이동시키는 요소 생성
* <Link> component
=> <a> 태그가 아닌 <Link> 컴포넌트를 활용하여 매핑을 해주면
     페이지가 새로고침 되지 않고 리렌더링만으로 페이지 전환을 할 수 있다 (CSR방식)

* CSR 방식으로 페이지 이동시키는 방식
= 실제로 페이지를 이동시킨다기 보다는
   페이지 역할을 하는 컴퍼넌트를 갈아 끼우고
   url도 바꾸어서 페이지를 이동하는 것 처럼 보이게 만드는 방식이라고 할 수 있다
=> 페이지 이동 시 깜빡임도 없고 이동 속도가 매우 빨라서 쾌적한 페이지 이동을 할 수 있다

* App.js

import "./App.css";
// 브라우저 url과 react app을 연결하는 기능
import { BrowserRouter, Route, Routes } from "react-router-dom";

// 페이지들을 import 해준다
import Home from "./pages/Home.js"; // .js 생략 가능
import New from "./pages/New";
import Edit from "./pages/Edit";
import Diary from "./pages/Diary";

import RouteTest from "./components/RouteTest.js";

function App() {
  return (
    // BrowserRouter로 감싸준다
    // = 감싸져있는 부분은 브라우저 url과 매핑될 수 있다
    <BrowserRouter>
      <div className="App">
        <h2>App.js</h2>
        <Routes>
          {/* 페이지 경로 매핑 */}
          {/* path="/"  == path="/index" */}
          <Route path="/" element={<Home />} />
          <Route path="/new" element={<New />} />
          <Route path="/edit" element={<Edit />} />
          {/* :id = ':'을 사용하여 id라는 이름으로 값을 전달하겠다 라는 의미 */}
          <Route path="/diary/:id" element={<Diary />} />
        </Routes>
        <RouteTest />
      </div>
    </BrowserRouter>
  );
}

export default App;

 

 

 


<React Router>
* React Router Dom의 유용한 기능
- React Router v6
  = React에서 CSR기반의 페이지 라우팅을 할 수 있게 해주는 라이브러리

1. Path Variable
   - useParams
     = 경로에 변수 사용
   - ex) Diary 페이지 
          경로 : /diary 
          특징 : 어떤 일기를 보여줘야 할 지 전달 받아야 함
           => /diary/1 = 1번 일기

 

* Diary.js

import { useParams } from "react-router-dom"; // = custom hooks의 하나

const Diary = () => {
  // id로 정의된 path variable을 id로 꺼내온다
  // useParams() = id로 전달된 path variable을 모아서 객체로 전달하는 기능을 함
  const { id } = useParams();
  console.log(id);

  return (
    <div>
      <h1>Diary</h1>
      <p>이 곳은 일기 상세 페이지입니다</p>
    </div>
  );
};

export default Diary;

 

 


2. Query String
   - useSearchParams
     = url과 함께 data를 전달
     = path variable과 유사
   - ex) edit?id=10&mode=dark
          => Query String 이라고 표현한다
   - url을 사용하면서 '?'물음표 키워드를 사용하여 &로 묶어서 데이터를 전송할 수 있는 기법
     = 간단하게 페이지에 데이터를 전달할 수 있는 방식이다
   - useParams와는 다르게 비구조화 할당을 사용하여
     searchParams와 setsearchParams, 이 두개로 전달받을 수 있는 배열을 반환하게 된다
     => 첫번째 반환받는 index = get()을 통해 전해받은 query string 들을 꺼내 쓸 수 있는 용도로 사용
          두번재 반환받는 index = searchParams를 변경하는 기능 = 전달받은 query string을 바꿀 수 있다는 의미
                                                                               = 상태변화 함수

 


3. Page Moving
   - useNavigate 
   = 함수를 통해 페이지 이동
   => 로그인이 안된 사용자가 로그인을 하려고 로그인 페이지로 가려고 할 때
        -> 로그인 값을 검사해서 로그인이 되어있지 않다면 강제로 로그인 페이지로 보내버리는 경우 사용 가능
        => 페이지를 클릭하지 않아도 의도적으로 페이지를 바꿔버릴 수 있다

* navigate 뒤로가기
=> <button onClick={() => { navigate(-1); }}> 뒤로가기 </button>

 


* Edit.js

import { useNavigate, useSearchParams } from "react-router-dom";

const Edit = () => {
  // Query String 꺼내서 사용하기 = 비구조화 할당으로 사용
  // useSearchParams() = query string을 처리하는 custom hook
  const [searchParams, setSearchParams] = useSearchParams();

  // useNavigate hook = 페이지를 이동시킬 수 있는 기능을 하는 함수 하나를 반환
  // 그 함수의 이름을 navigate로 받음
  const navigate = useNavigate();

  const id = searchParams.get("id");
  console.log("id: ", id);

  const mode = searchParams.get("mode");
  console.log("mode: ", mode);

  return (
    <div>
      <h1>Edit</h1>
      <p>이 곳은 일기 수정 페이지입니다</p>
      {/* setSearchParams를 바꾸는 버튼(객체를 전달한다) */}
      <button onClick={() => setSearchParams({ who: "name" })}>
        QS 바꾸기
      </button>
      <button
        onClick={() => {
          // navigate의 인자로 경로를 작성하면
          // navigate 함수를 호출해서 경로를 옮겨줄 수 있다
          navigate("/home");
        }}
      ></button>
      <button
        onClick={() => {
          navigate(-1);
        }}
      >
        뒤로가기
      </button>
    </div>
  );
};

export default Edit;




 

 

 

 

 

 

 

 

 

2023. 01. 22 (월)

관련글 더보기