[TIL] 20250331

김민석·2025년 3월 31일
post-thumbnail

오늘 목표

  • 수업 전 7시 기상 후 운동(O)
  • 수업 내용 모르는 거 및 공부내용 정리(O)
  • 프로젝트 진행 해보기(O)

공부내용

프로토타입

이전 와이어 프레임에 했던 것에 이벤트 및 interaction을 연결하였고 또한 로그인 상태로 접속한
화면과 비로그인으로 접속한 화면을 나눠 진행하게 하였고 Modal을 만들어 비로그인 시 로그인을 해야만하는 상황이 발생할 경우 Modal을 통해 로그인 창으로 가게끔 유도하였습니다.

프로젝트 진행

블로그 프로젝트를 진행하다가 post를 작성하면 Post를 DB에 저장한 후 그것을 TimeStamp DEFAULT CURRENT_TIMESTAMP로 지정하여 현재 시간을 저장하게 하였다. 그 후 나중에 Post를 불러올 때 TimeStamp로 지정한 current_at 값을 눌러오는데 계속 null값만 불러와졌다.. 계속
다양한 방법을 시도했지만 되지않았다.. 결국 시도하고 시도하면서 해냇따!..

create_at 불러오기 실패...

원인 분석

MyBatis에서 resultType="Post"을 사용하면, 데이터베이스 컬럼명과 Java 객체의 필드명을 자동으로 매핑하려고 해.
하지만 MyBatis는 컬럼명이 자바 필드명과 완전히 일치해야 자동 매핑이 가능해

문제점

데이터베이스 컬럼명: created_at, updated_at (스네이크 케이스)
Java 필드명: createdAt, updatedAt (카멜 케이스)
여기서... Post에 @Column(name = "created_at")을 이용하여 변환하였다고 생각하였지만
MyBatis는 기본적으로 자동으로 created_at을 createdAt으로 변환하지 못한다고 한다..
그래서 계속 데이터를 못 불러 왔고... 나중에 알게되었다.

✅ 해결 방법: resultMap 사용
resultMap을 사용하면 컬럼명과 자바 필드명을 수동으로 매핑 가능하다!

<resultMap id="postResultMap" type="Post">
    <result column="id" property="id"/>
    <result column="title" property="title"/>
    <result column="category" property="category"/>
    <result column="content" property="content"/>
    <result column="created_at" property="createdAt"/>  <!-- 수동 매핑 -->
    <result column="updated_at" property="updatedAt"/>  <!-- 수동 매핑 -->
</resultMap>

<select id="getAllPost" resultMap="postResultMap">
    SELECT * FROM post
</select>

결론

MyBatis의 자동 매핑 기능이 스네이크 케이스 → 카멜 케이스 변환을 못 했다... resultMap을 사용해서 수동 매핑을 하면서 문제 해결함.

API 호출 위치

원래는 Layout 밑에 있는 sideBar에서 category를 선택할 수 있어서 SideBar에 category를 불러오는 api를 넣어놨다 하지만 그 상위 컴포넌트인 Layout에 api를 불러오는 코드를 작성하는 것이 더 효율적이라고 생각하였고 그이유를 알아보자!..

import { Outlet } from "react-router-dom";
import CategorySection from "../components/CategorySection";
import SideBar from "../components/Sidebar";
import axios from "axios";
import { useEffect, useState } from "react";
interface CategoryPostCount {
  category: string;
  postCount: number;
}

function Layout() {
  const [categories, setCategories] = useState<CategoryPostCount[]>([]);

  useEffect(() => {
    axios
      .get("http://localhost:8080/getCategoryAll")
      .then((response) => {
        setCategories(response.data);
      })
      .catch((error) => {
        console.error(error);
      });
  }, []);
  return (
    <div className="flex">
      <SideBar categories={categories}/>
      <div className="flex-1 flex-col ">
        <CategorySection  />
        <main>
          <Outlet/>
        </main>
      </div>
    </div>
  );
}

export default Layout;

장점

중앙 집중화: Layout 컴포넌트에서 API 호출을 한 번 하고 데이터를 상태로 관리하면, SideBar 뿐만 아니라 다른 자식 컴포넌트들에서도 이 데이터를 쉽게 접근할 수 있음. 코드의 재사용성을 높여준다.

컴포넌트 간 데이터 전달: Layout에서 데이터를 불러오고 그 데이터를 SideBar에 전달함으로써, SideBar가 데이터를 직접 불러오는 대신 상위 컴포넌트인 Layout에서 전달된 데이터를 사용하게 함으로 써 데이터의 흐름을 명확하게 만들 수 있습니다.

성능 최적화: API 호출은 일반적으로 비동기적으로 처리됩니다. 만약 SideBar 컴포넌트에서 직접 데이터를 불러온다면 여러 컴포넌트에서 독립적으로 API를 호출할 수 있지만 상위 컴포넌트에서 데이터를 한 번만 요청한 후에 이를 하위 컴포넌트에 전달하는 방식이 더 효율적입니다.

profile
나만의 기록장

0개의 댓글