
📅 2025-11-11
➡️ axios, Supabase에 대해 새롭게 알게 된 것 또는 헷갈리는 부분 정리
// src/api/client.js
import axios from "axios";
// 공통 설정을 미리 적용한 axios 인스턴스 생성
const client = axios.create({
baseURL: "http://localhost:4000",
headers: {
"Content-Type": "application/json",
},
});
export default client;// App.jsx
import { useEffect } from "react";
import client from "./api/client";
export default function App() {
useEffect(() => {
client
.get("/cafe")
.then((res) => console.log(res.data))
.catch((err) => console.error("요청 실패:", err));
}, []);
return <div>Axios Custom Instance 예제</div>;
}
요청 전(request) : 요청이 서버로 전송되기 전
응답 후(response) : 응답이 .then이나 .catch로 넘어가기 전
import axios from "axios";
const instance = axios.create({
baseURL: "http://localhost:4000",
});
instance.interceptors.request.use(
function (config) {
// 요청을 보내기 전 수행
console.log("인터셉트 요청 성공!");
return config;
},
function (error) {
// 오류 요청을 보내기 전 수행
console.log("인터셉트 요청 오류!");
return Promise.reject(error);
}
);
instance.interceptors.response.use(
function (response) {
console.log("인터셉트 응답 받았습니다");
// 정상 응답
return response;
},
function (error) {
console.log("인터셉트 응답을 못받았습다");
return Promise.reject(error);
}
);
export default instance;

| 구성요소 | 설명 |
|---|---|
| Frontend | 사용자가 보는 화면 (React 등) |
| Backend | 데이터 처리, 인증, 비즈니스 로직 담당 |
| Database | 실제 데이터를 저장하는 저장소 |
| 구분 | NoSQL | SQL |
|---|---|---|
| 구조 | JSON / key-value | 테이블 기반 |
| 스키마 | 유연함 (필드를 자유롭게 추가 가능) | 고정 구조 (엄격한 구조) |
| 관계 | 없음 | 외래키(Foreign Key)로 연결 |
| 예시 | MongoDB, Firebase 등 | MySQL, PostgreSQL, Oracle, SQLite 등 |
| 기능 | 설명 |
|---|---|
| 관계형 데이터 관리 | SQL, JOIN, Foreign Key, Transaction 지원 |
| 실시간 데이터 반응 | DB 변경 시 UI 자동 갱신 가능 |
| 인증/스토리지 내장 | 회원가입, 로그인, 파일 업로드 쉽게 구현 가능 |
| 오픈소스 | 무료로 시작 가능, 자가 호스팅도 가능 |
설치
yarn add @supabase/supabase-js
프로젝트 생성 후, 테이블 만들고 데이터 넣기
// src/supabaseClient.js
import { createClient } from "@supabase/supabase-js";
// Supabase 프로젝트 설정 정보
const SUPABASE_URL = "YOUR_SUPABASE_URL";
const SUPABASE_ANON_KEY = "YOUR_SUPABASE_ANON_KEY";
// 클라이언트 생성
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
export default supabase;
🔗 https://supabase.com/docs/reference/javascript/introduction
import "./App.css";
import FetchData from "./components/FetchData";
function App() {
return (
<>
<h1>Supabase 데이터 조회</h1>
<FetchData />
</>
);
}
export default App;import { useEffect, useState } from "react";
import supabase from "../supabaseClient";
const FetchData = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
const loadUsers = async () => {
const { data, error } = await supabase.from("goorm").select("*");
if (error) {
console.error("데이터 불러오기 실패:", error.message);
return;
}
setUsers(data);
};
loadUsers();
}, []);
return (
<div>
<h3>유저 목록</h3>
{users.map((user) => (
<div
key={user.id}
style={{ border: "1px solid #aaa", padding: "8px", marginBottom: "6px" }}
>
<p>아이디: {user.id}</p>
<p>이름: {user.name}</p>
<p>나이: {user.age}</p>
<p>주소: {user.address}</p>
</div>
))}
</div>
);
};
export default FetchData;import "./App.css";
import AddData from "./components/AddData";
import FetchData from "./components/FetchData";
function App() {
return (
<>
<h1>Supabase</h1>
<FetchData />
<AddData />
</>
);
}
export default App;import React, { useState } from "react";
import supabase from "../supabaseClient";
const AddData = () => {
const [name, setName] = useState("");
const [age, setAge] = useState(0);
const [address, setAddress] = useState("");
const handleAdd = async () => {
const { data, error } = await supabase.from("goorm").insert({
name,
age,
address,
});
if (error) {
console.log("error => ", error);
} else {
alert("데이터가 정상적으로 입력됐습니다.");
console.log("data => ", data);
}
};
return (
<div
style={{
border: "1px solid red",
}}
>
<h2>데이터 추가 로직</h2>
<div>
이름 :{" "}
<input
type="text"
value={name}
onChange={(e) => {
setName(e.target.value);
}}
/>
</div>
<div>
나이 :{" "}
<input
type="number"
value={age}
onChange={(e) => {
setAge(e.target.value);
}}
/>
</div>
<div>
주소 :{" "}
<input
type="text"
value={address}
onChange={(e) => {
setAddress(e.target.value);
}}
/>
</div>
<button onClick={handleAdd}>등록</button>
</div>
);
};
export default AddData;import "./App.css";
import AddData from "./components/AddData";
import FetchData from "./components/FetchData";
import UpdateData from "./components/UpdateData";
function App() {
return (
<>
<h1>Supabase</h1>
<FetchData />
<UpdateData />
<AddData />
</>
);
}
export default App;import React, { useState } from "react";
import supabase from "../supabaseClient";
const UpdateData = () => {
const [targetId, setTargetId] = useState(0);
const [address, setAddress] = useState("");
const handleChange = async () => {
const { error } = await supabase
.from("goorm")
.update({
address,
})
.eq("id", targetId);
if (error) {
console.log("error => ", error);
}
};
return (
<div
style={{
border: "1px solid blue",
}}
>
<h2>데이터 수정 로직</h2>
아이디 :{" "}
<input
type="number"
value={targetId}
onChange={(e) => setTargetId(e.target.value)}
/>
<br />
수정주소 :{" "}
<input
type="text"
value={address}
onChange={(e) => setAddress(e.target.value)}
/>
<button onClick={handleChange}>변경</button>
</div>
);
};
export default UpdateData;import "./App.css";
import AddData from "./components/AddData";
import DeleteData from "./components/DeleteData";
import FetchData from "./components/FetchData";
import UpdateData from "./components/UpdateData";
function App() {
return (
<>
<h1>Supabase</h1>
<DeleteData />
<FetchData />
<UpdateData />
<AddData />
</>
);
}
export default App;import React, { useState } from "react";
import supabase from "../supabaseClient";
const DeleteData = () => {
const [targetId, setTargetId] = useState(0);
const handleDelete = async () => {
const { error } = await supabase
.from("goorm")
.delete()
.eq("id", targetId);
if (error) {
console.log("error => ", error);
}
};
return (
<div
style={{
border: "1px solid blue",
}}
>
<h2>데이터 삭제 로직</h2>
아이디 :{" "}
<input
type="number"
value={targetId}
onChange={(e) => setTargetId(e.target.value)}
/>
<button onClick={handleDelete}>삭제</button>
</div>
);
};
export default DeleteData;