Vue.js Starter - Axios
Vue.js ํ๋ก์ ํธ ํฌ์ ์ผ์ฃผ์ผ ์ - Part 3
11. Axios ๐ฉโ๐ป
1. Installation
Axios ๋ Promise ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ HTTP Client
๋ก node.js
์
Web-browser
์์ ๋์ผํ ์ฝ๋ ๋ฒ ์ด์ค๋ก ์๋ํ๋ค.
- Server-side : native node.js http module ์ ์ฌ์ฉ.
- Web-browser : XMLHttpRequests ๋ฅผ ์ฌ์ฉ.
npm install axios -S
2. Features
Axios
๋ ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
- ์น ๋ธ๋ผ์ฐ์ ์์
XMLHttpRequests
๋ฅผ ์์ฑ - node.js ์์
HTTP Requests
๋ฅผ ์์ฑ Promise API
๋ฅผ ์ง์- Request ์ Response ์
Intercept
๋ฅผ ์ง์ - Request ์ Response ์ ๋ฐ์ดํฐ๋ฅผ ๋ณํ
- Request ์ ์ทจ์(cancel) ์ฒ๋ฆฌ๋ฅผ ์ง์
- ์๋์ผ๋ก
JSON
๋ฐ์ดํฐ๋ฅผ ๋ณํ - Client-side ์
XSRF
์ ๋ํ ๋ณดํธ๋ฅผ ์ง์
XSRF : CSRF ๋ผ๊ณ ๋ ๋ถ๋ฆฌ๋ฉฐ
Cross-site Request Forgery
์ ์ฝ์ด๋ค.
cf. ์ฌ์ดํธ ๊ฐ ์์ฒญ ์์กฐ
3. Axios Examples
1 ) import library
import axios from "axios"
๋จ, TypeScript ์ ํจ๊ป CommonJS ๋ฐฉ์์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์๋์ ๊ฐ์ด ์ฌ์ฉํด์ผ ์๋์์ฑ๊ณผ intellisense ๊ฐ ์ง์๋๋ค.
const axios = require('axios').default;
2 ) Request Get Examples
๋ค์ 3๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ชจ๋ ๋์ผํ ์์ ์ ์ฒ๋ฆฌํ๋ค.
- Case 1
axios.get('/user?ID=12345')
.then((response) => {
// handle success
console.log(response);
})
.catch((error) => {
// handle error
console.log(error);
})
.then(() => {
// always executed
});
- Case 2
axios.get('/user', {
params: {
ID: 12345
}
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
})
.then(() => {
// always executed
});
- Case 3
const getUser = async () => {
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
}
}
3 ) Request Post Examples
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
4 ) Performing Multiple Concurrent Requests
Axios ๋ Promise ๊ธฐ๋ฐ
์ด๋ฏ๋ก, ์ฌ๋ฌ ์์ฒญ์ ๋์์ ๋ณด๋ด๋ ค๋ฉด Promise.all()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
const getUserAccount = () => {
return axios.get('/user/12345');
}
const getUserPermissions = () => {
return axios.get('/user/12345/permissions');
}
Promise.all([getUserAccount(), getUserPermissions()])
.then((results) => {
const acct = results[0];
const perm = results[1];
});
4. Default Alias Methods
๋ณ๋์ config
์ค์ ์์ด ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ ๊ธฐ๋ณธ ์ ๊ณต ๋ฉ์๋๋ ๋ค์๊ณผ ๊ฐ์ด 8๊ฐ์ง๊ฐ ์กด์ฌํ๋ค.
- axios.request(config)
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.head(url[, config])
- axios.options(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
- axios.patch(url[, data[, config]])
์
Alias ๋ฉ์๋
๋ฅผ ์ฌ์ฉํ๋ฉดurl
,method
,data
properties ๋ฅผ ๋ช ์ํ ํ์๊ฐ ์๋ค.
5. Axios Instance
Axios
instance ๋ ์๋์ ๊ฐ์ด custom config
๋ฅผ ์ด์ฉํด new Instance
๋ฅผ ์์ฑํ๋ค.
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
์ฌ์ฉ ๊ฐ๋ฅํ Instance methods
๋ ๋ค์๊ณผ ๊ฐ์ผ๋ฉฐ, Instance config
์ merge
๋๋ค.
- axios#request(config)
- axios#get(url[, config])
- axios#delete(url[, config])
- axios#head(url[, config])
- axios#options(url[, config])
- axios#post(url[, data[, config]])
- axios#put(url[, data[, config]])
- axios#patch(url[, data[, config]])
- axios#getUri([config])
6. Request Config
์ค์ ๊ฐ๋ฅํ config
๋ ๋ค์๊ณผ ๊ฐ์ผ๋ฉฐ, url
๋ง ํ์๊ฐ์ด๋ค. method
๋ ์๋ต์ ๊ธฐ๋ณธ๊ฐ์ผ๋ก GET
์
์ฌ์ฉํ๋ค.
const config =
{
url: '/user',
method: 'get', // default
baseURL: 'https://some-domain.com/api',
// This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE'
transformRequest: [function (data, headers) {
// Do whatever you want to transform the data
return data;
}],
// it is passed to then/catch
transformResponse: [function (data) {
// Do whatever you want to transform the data
return data;
}],
// `headers` are custom headers to be sent
headers: {'X-Requested-With': 'XMLHttpRequest'},
// `params` are the URL parameters to be sent with the request
// Must be a plain object or a URLSearchParams object
// NOTE: params that are null or undefined are not rendered in the URL.
params: {
ID: 12345
},
// `paramsSerializer` is an optional function in charge of serializing `params`
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function (params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
// `data` is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH'
// When no `transformRequest` is set, must be of one of the following types:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - Browser only: FormData, File, Blob
// - Node only: Stream, Buffer
data: {
firstName: 'Fred'
},
// syntax alternative to send data into the body
// method post
// only the value is sent, not the key
data: 'Country=Brasil&City=Belo Horizonte',
// If the request takes longer than `timeout`, the request will be aborted.
timeout: 1000, // default is `0` (no timeout)
// `withCredentials` indicates whether or not cross-site Access-Control requests
// should be made using credentials
withCredentials: false, // default
// `adapter` allows custom handling of requests which makes testing easier.
// Return a promise and supply a valid response (see lib/adapters/README.md).
adapter: function (config) {
/* ... */
},
// `auth` indicates that HTTP Basic auth should be used, and supplies credentials.
// This will set an `Authorization` header, overwriting any existing
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
// `responseType` indicates the type of data that the server will respond with
// options are: 'arraybuffer', 'document', 'json', 'text', 'stream'
// browser only: 'blob'
responseType: 'json', // default
// `responseEncoding` indicates encoding to use for decoding responses (Node.js only)
// Note: Ignored for `responseType` of 'stream' or client-side requests
responseEncoding: 'utf8', // default
// `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
xsrfCookieName: 'XSRF-TOKEN', // default
// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
xsrfHeaderName: 'X-XSRF-TOKEN', // default
// `onUploadProgress` allows handling of progress events for uploads
// browser only
onUploadProgress: function (progressEvent) {
// Do whatever you want with the native progress event
},
// `onDownloadProgress` allows handling of progress events for downloads
// browser only
onDownloadProgress: function (progressEvent) {
// Do whatever you want with the native progress event
},
// `maxContentLength` defines the max size of the http response content in bytes allowed in node.js
maxContentLength: 2000,
// `maxBodyLength` (Node only option) defines the max size of the http request content in bytes allowed
maxBodyLength: 2000,
// `validateStatus` defines whether to resolve or reject the promise for a given
// HTTP response status code. If `validateStatus` returns `true` (or is set to `null`
// or `undefined`), the promise will be resolved; otherwise, the promise will be
// rejected.
validateStatus: function (status) {
return status >= 200 && status < 300; // default
},
// `maxRedirects` defines the maximum number of redirects to follow in node.js.
// If set to 0, no redirects will be followed.
maxRedirects: 5, // default
// `socketPath` defines a UNIX Socket to be used in node.js.
// e.g. '/var/run/docker.sock' to send requests to the docker daemon.
// Only either `socketPath` or `proxy` can be specified.
// If both are specified, `socketPath` is used.
socketPath: null, // default
// `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
// and https requests, respectively, in node.js. This allows options to be added like
// `keepAlive` that are not enabled by default.
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// `proxy` defines the hostname, port, and protocol of the proxy server.
proxy: {
protocol: 'https',
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},
// `cancelToken` specifies a cancel token that can be used to cancel the request
cancelToken: new CancelToken(function (cancel) {
}),
// `decompress` indicates whether or not the response body should be decompressed
// automatically. If set to `true` will also remove the 'content-encoding' header
// from the responses objects of all decompressed responses
// - Node only (XHR cannot turn off decompression)
decompress: true // default
}
7. Response Scheme
Response
๋ ์๋์ ๊ฐ์ ๊ตฌ์กฐ๋ก ๋์ด์๋ค.
const response =
{
// `data` is the response that was provided by the server
data: {},
// `status` is the HTTP status code from the server response
status: 200,
// `statusText` is the HTTP status message from the server response
// As of HTTP/2 status text is blank or unsupported.
// (HTTP/2 RFC: https://www.rfc-editor.org/rfc/rfc7540#section-8.1.2.4)
statusText: 'OK',
// `headers` the HTTP headers that the server responded with
// All header names are lower cased and can be accessed using the bracket notation.
// Example: `response.headers['content-type']`
headers: {},
// `config` is the config that was provided to `axios` for the request
config: {},
// `request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
// and an XMLHttpRequest instance in the browser
request: {}
}
8. Overriding Config Defaults
1 ) Library defaults
lib/defaults.js
์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ธฐ๋ณธ ์ค์ ๊ฐ์ด ๊ฐ์ฅ ๋จผ์ ์ ์ฉ๋๋ค.
2 ) Global axios defaults & Custom instance defaults
- Global axios defaults
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
- Custom instance defaults
// Set config defaults when creating the instance
const instance = axios.create({
baseURL: 'https://api.example.com'
});
// Alter defaults after instance has been created
instance.defaults.headers.common['Authorization'] = AUTH_TOKEN;
์์ ๊ฐ์ด ์ ์ํ custom config
๊ฐ ์กด์ฌํ ๊ฒฝ์ฐ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ธฐ๋ณธ ์ค์ ๊ฐ์ ๋ฎ์ด์จ ์ ์ญ ์ค์ ํ๋ค.
3 ) Config argument for the request
๊ฐ Request
๋ฉ์๋์ ์์ฑํ config
๋ ํด๋น ๋ฉ์๋์๋ง ์ ์ฉ๋๋ ์ค์ ์ผ๋ก, Inline CSS
์ ๊ฐ์ด
๊ฐ์ฅ ์ฐ์ ์์๊ฐ ๋๋ค.
// Create an instance using the config defaults provided by the library
// At this point the timeout config value is `0` as is the default for the library
const instance = axios.create();
// Override timeout default for the library
// Now all requests using this instance will wait 2.5 seconds before timing out
instance.defaults.timeout = 2500;
// Override timeout for this request as it's known to take a long time
instance.get('/longRequest', {
timeout: 5000
});
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ธฐ๋ณธ๊ฐ์ ์ํด
timeout
config ๋0
์ด๋ค.Custom instance defaults
์ ์ํดtimeout
config ๋2500
์ด ์ ์ญ์ ์ฌ์ฉ๋๋ค.- ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ฒญ์ ๊ฐ๋ณ์ ์ผ๋ก
config
๋ฅผ ์ค์ ํ ์ ์๋ค. ์/ongRequest
์timout
config ๋5000
์ด ์ฌ์ฉ๋๋ค.
9. Interceptors
Axios
๋ฅผ ์ด์ฉํ๋ฉด ์์ฝ๊ฒ Interceptors
๋ฅผ ์ค์ ํ ์ ์์ผ๋ฉฐ, ์ด๋ request ์ response
์ ์ ์ฉํ ์ ์๋ค.
1 ) Add Request Interceptors
axios.interceptors.request.use((config) => {
// Do something before request is sent
return config;
}, (error) => {
// Do something with request error
return Promise.reject(error);
});
2 ) Add Response Interceptors
Response
๋ HTTP status code
๊ฐ 2xx
์ผ ๋์ ์๋ ๋๋ก ๊ตฌ๋ถ๋์ด trigger ๋๋ค.
axios.interceptors.response.use((response) => {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
}, (error) => {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error);
});
3 ) Remove Interceptors
๋ฑ๋กํ Interceptors
๋ฅผ ์ญ์ ํ๋ ๋ฐฉ๋ฒ์ setTimeout()
๋๋ setInterval()
๋ฅผ ํด์ ์ํค๋
๋ฐฉ๋ฒ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ณ๋์ ์์ ๋๋ ๋ณ์์ ์ ์ฅ ํ ํด๋น ๊ฐ์ ์ด์ฉํด ํด์ ์ํจ๋ค.
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
4 ) Add Interceptors to Custom Instance
์ด๋ฏธ ์์ฑํ Instance
์ Interceptors
๋ฅผ ์ถ๊ฐํ ์ ์๋ค.
const instance = axios.create();
instance.interceptors.request.use(() => {/*...*/});
10. Error Handling
1 ) Split catches
์ 3. Axios Examples ์์ then
, catch
, then
์ผ๋ก ์ด์ด์ง๋
์ฒ๋ฆฌ ํ๋ก์ธ์ค๋ฅผ ๊ฐ๋ตํ๊ฒ ์ค๋ช
ํ๋ค.
๋ค์ ์ฝ๋๋ ์ด ์ค catch
์์ ์๋์ ๊ฐ์ด response ์๋ฌ > request ์๋ฌ > ๋ชจ๋ ์๋ฌ ์์ผ๋ก
๊ตฌ๋ถํด ์ฒ๋ฆฌํด ๋์๊ฐ๋ ์๋ฅผ ๋ณด์ฌ์ค๋ค. ์ด๋ try-catch
๋ฅผ ์ด์ฉํด ์๋ฌ๋ฅผ ๋จ๊ณ๋ณ๋ก ๊ตฌ๋ถํด ์ฒ๋ฆฌํด ๋๊ฐ๋
๊ฒ๊ณผ ๊ฐ์ ๋ฐฉ์์ด๋ค.
axios.get('/user/12345')
.catch((error) => {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
}
console.log(error.config);
});
2 ) Using validateStatus
config option
6. Request Config ์ validateStatu
๋ฅผ ์ฌ์ฉํด HTTP status code
๋ฅผ
์ผ๋ฐํ ํด ์ ์ํ ์ ์๋ค.
axios.get('/user/12345', {
validateStatus: function (status) {
return status < 500; // Resolve only if the status code is less than 500
}
})
validateStatus
๊ฐtrue
๋๋null
๋๋undefined
๋ฅผ ์๋ตํ๋ฉด Promise ๋resolve()
๊ฐ trigger ๋๊ณ ,false
๋ฅผ ์๋ตํ๋ฉดreject()
๊ฐ trigger ๋๋ค.
3 ) Using toJSON()
method
catch
์์ HTTP ์๋ฌ๋ฅผ ์ข ๋ ์์ธํ๊ฒ ํ์ธํ๊ณ ์ถ๋ค๋ฉด, toJSON()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค.
axios.get('/user/12345')
.catch(function (error) {
console.log(error.toJSON());
});
11. Cancellation
2. Features ์์ ์ค๋ช
ํ Axios
๊ฐ ์ ๊ณตํ๋ ๊ธฐ๋ฅ ์ค 6๋ฒ์งธ Request ์ทจ์์ ๋ํ ์ค๋ช
์ผ๋ก,
Axios
๋ Fetch API
๋ฐฉ์์ ์์ฒญ์ ์ทจ์ํ๊ธฐ ์ํด Web APIs - AbortController
interface ๋ฅผ ์ง์ํ๋ค.
์ด๋ AbortController
instance ๋ฅผ ์์ฑํด ์ฒ๋ฆฌ๋ฅผ ๊ฐ๋ฅ์ผ ํ๋ค.
const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// cancel the request
controller.abort()
CancelToken
์ด๋ ๊ฒ๋ ์๋๋ฐ deprecated ๋์์ผ๋ฏ๋ก ์ฌ์ฉํ์ง ์๋๋ก ํ๋ค.
12. URL-Encoding Bodies
Axios
๋ ๊ธฐ๋ณธ์ ์ผ๋ก JavaScript Objects
๋ฅผ JSON
์ผ๋ก serialize
ํ๋ค.
๋ฐ๋ผ์ JSON
๋์ application/x-www-form-urlencoded
๋ฅผ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด ์๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ
์ ์๋ค.
1 ) Using URLSearchParams
Web APIs - URLSearchParams ๋ฅผ ์ด์ฉํ๋ค.
๋ค์ 3๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ชจ๋ ๋์ผํ ์์ ์ ์ฒ๋ฆฌํ๋ค.
- Case 1
const paramsString = 'foo=bar&baz=qoo';
const searchParams = new URLSearchParams(paramsString);
axios.post('/foo', searchParams);
- Case 2
const searchParams = new URLSearchParams();
searchParams.append('foo', 'bar');
searchParams.append('baz', 'qoo');
axios.post('/foo', searchParams);
- Case 3
const paramsObj = { foo: 'bar', baz: 'qoo' };
const searchParams = new URLSearchParams(paramsObj);
axios.post('/foo', searchParams);
2 ) Using qs library
๋ค์ 2๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ชจ๋ ๋์ผํ ์์ ์ ์ฒ๋ฆฌํ๋ค.
- Case 1
const qs = require('qs');
axios.post('/foo', qs.stringify({ foo: 'bar', baz: 'qoo' }));
- Case 2
import qs from 'qs';
const data = { foo: 'bar', baz: 'qoo' };
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url,
};
axios(options);
12. Axios Examples ๐ฉโ๐ป
1. Create Mock API for Axios Examples
Mock ์๋ฒ๋ฅผ ํตํ ํ
์คํธ๋ฅผ ์งํํ๊ธฐ ์ํด Postman ์ Mock
์๋ฒ์ GET /test
๋ฅผ ์์ฑ ํ ๋ค์๊ณผ ๊ฐ์ด example
๊ณผ
Tests
๋ฅผ ๋ฑ๋กํ๋ค.
- example
[
{"productName": "iPhone 14 Pro Max", "price": 1750000, "category": "Phone"},
{"productName": "iPhone 14 Pro", "price": 1550000, "category": "Phone"},
{"productName": "iPhone 14 Plus", "price": 1350000, "category": "Phone"},
{"productName": "iPhone 14", "price": 1250000, "category": "Phone"},
{"productName": "MacBook Pro 16", "price": 3360000, "category": "Laptop"},
{"productName": "MacBook Pro 14", "price": 2690000, "category": "Laptop"},
{"productName": "iPad Pro 12.9", "price": 1729000, "category": "Tablet"},
{"productName": "iPad Pro 11", "price": 1249000, "category": "Tablet"}
]
- Tests
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test("Get /test JSON data is correct", function () {
const expect = [
{ "productName": "iPhone 14 Pro Max", "price": 1750000, "category": "Phone" },
{ "productName": "iPhone 14 Pro", "price": 1550000, "category": "Phone" },
{ "productName": "iPhone 14 Plus", "price": 1350000, "category": "Phone" },
{ "productName": "iPhone 14", "price": 1250000, "category": "Phone" },
{ "productName": "MacBook Pro 16", "price": 3360000, "category": "Laptop" },
{ "productName": "MacBook Pro 14", "price": 2690000, "category": "Laptop" },
{ "productName": "iPad Pro 12.9", "price": 1729000, "category": "Tablet" },
{ "productName": "iPad Pro 11", "price": 1249000, "category": "Tablet" }
]
var jsonData = pm.response.json();
pm.expect(jsonData).to.eql(expect);
});
Collection
์ โโโ
๋ฅผ ๋๋ฅด๊ณ Run collection
์ ํตํด Mock API
๊ฐ ์ ์ ์๋ํ๋์ง ํ์ธํ๋ค.
2. Axios Examples with mixins.js
Axios
๋ฅผ ์ด์ฉํด ๋ณด๋ด๋ XHR
์์ฒญ์ ๊ณตํต์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด mixins.js
ํ์ผ์ ์์ฑํ๊ณ , ์ฌ๊ธฐ์ ๊ณตํต์ผ๋ก ์ฌ์ฉํ ํจ์๋ฅผ ์์ฑํ๋ค.
mixins ์ ๋ํ ์์ธํ ์ค๋ช ์ mixins ๋ฅผ ์ฐธ๊ณ ํ๋ค.
- /src/mixins.js
import axios from "axios";
export default {
methods: {
async $api(url, method, data) {
return (
await axios({
url: url,
baseURL: "https://0000.mock.pstmn.io",
method: method,
data: data,
}).catch((e) => {
console.log(e);
})
).data;
},
},
};
๊ทธ๋ฆฌ๊ณ ์ mixins
๋ฅผ Vue
instance ์ ๋ฑ๋กํ๋ค.
- /src/main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import mixins from "@/mixins";
createApp(App).use(store).use(router).mixin(mixins).mount("#app");
์ View
ํ์ด์ง๋ฅผ ๋ง๋ค๊ณ Axios
๋ฅผ ์ด์ฉํด Mock API
๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ํ๋ก ๋ ๋๋ง์ ํด๋ณด์.
- /src/views/AxiosTestView.vue
<template>
<div>
<table>
<thead>
<tr>
<th>์ ํ๋ช
</th>
<th>๊ฐ๊ฒฉ</th>
<th>์นดํ
๊ณ ๋ฆฌ</th>
</tr>
</thead>
<tbody>
<tr v-for="(product, i) in productList" :key="i">
<td>{{ product.productName }}</td>
<td>{{ product.price }}</td>
<td>{{ product.category }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
name: "AxiosTestView",
data() {
return {
productList: [],
};
},
created() {
this.getList();
},
methods: {
async getList() {
this.productList = await this.$api("/test", "get");
},
},
};
</script>
<style scoped>
table {
font-family: Arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #ddd;
text-align: left;
padding: 8px;
}
</style>
3. Refactor Axios with DTO Objects
<template>
<tr v-for="(product, i) in productList" :key="i">
<td></td>
<td></td>
<td></td>
</tr>
</template>
TypeScript ๊ฐ ์๋ JavaScript ๋ฅผ ์ฌ์ฉ์ค์ผ ๋ productList ์ ํ์
์ ๋ฏธ๋ฆฌ ์ ํ ์ ์๋ค. ์ธ์คํด์ค๊ฐ ์์ฑ๋๋ฉฐ
Type Inference
๋ฅผ ํตํด์๋ง ํ์
์ด ์ ํด์ง๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฐ๋ผ์ ํ์
์ ๋ฏธ๋ฆฌ ์ ์ ์์ผ๋ IDE
์ Intellisense
๋ฅผ ์ฌ์ฉํ ์
์์ด ์ฝ๋ ์์ฑ์ด ์ด๋ ค์ธ ๋ฟ ์๋๋ผ ํด๋จผ ์๋ฌ๋ฅผ ๋ฐ์์ํค๋ ์์ธ์ด ๋๋ค.
๋ฐ๋ผ์ TypeScript ๊ฐ ์๋ JavaScript ์ ํ๊ณ๋ฅผ ๊ทน๋ณตํ๊ธฐ ์ํด ์๋์ ๊ฐ์ด ํ์
์ถ๋ก ์ ์ํด ๊ฐ์ฒด์ ํ์
์ด ์ง์ ๋๋๋ก ์ด๊ธฐํ ํ
๋ฐ์ดํฐ๋ฅผ ๊ต์ฒดํ๋ Trick
์ ์ฌ์ฉํ ์ ์๋ค.
const product = {
productName: "",
price: 0,
category: ""
}
let productList = new Array(product)
// let productList = Array["product"]
const response = [
{productName: "Choco Pie", price: 2000, category: "Snack"},
{productName: "Oh Yes", price: 2400, category: "Snack"},
{productName: "Sprite", price: 1200, category: "Beverage"}
]
productList = response
for (const product of productList) {
console.log(`${product.productName} is ${product.price > 2000 ? 'over' : 'less'} than 2000 won.`)
}
Choco Pie is less than 2000 won.
Oh Yes is over than 2000 won.
Sprite is less than 2000 won.
์ ์์ ์ mixins.js
๋ฅผ Axios Default Alias Methods
๋ฅผ ์ฌ์ฉํ๋๋ก ๋ฆฌํฉํ ๋ง ํ๊ณ , productList Array ์ ํ์
์
๋ฏธ๋ฆฌ ์ง์ ํด JavaScript ์ IDE
์ Intellisense
๊ฐ ์ด๋ฅผ ์ธ์ํ๋๋ก ๋ณ๊ฒฝํด๋ณด์.
- /src/mixins.js
import axios from "axios";
export default {
created: function () {
this.$api = axios.create({
baseURL: "https://0000.mock.pstmn.io",
});
},
methods: {
$get: async function (url, data) {
return await this.$api
.get(url, data)
.then((res) => res.data)
.catch((e) => console.log(e));
},
$post: async function (url, data) {
return await this.$api
.post(url, data)
.then((res) => res.data)
.catch((e) => console.log(e));
},
$put: async function (url, data) {
return await this.$api
.put(url, data)
.then((res) => res.data)
.catch((e) => console.log(e));
},
$patch: async function (url, data) {
return await this.$api
.patch(url, data)
.then((res) => res.data)
.catch((e) => console.log(e));
},
$delete: async function (url, data) {
return await this.$api
.delete(url, data)
.then((res) => res.data)
.catch((e) => console.log(e));
},
},
};
์ด์
this.$api.get(...)
๊ณผ ๊ฐ์ด ๊ธฐ๋ณธconfig
๋ฅผ ํฌํจํ instance ์ ์ผ๋ถ config ๋ฅผ ์์ ํด Custom Request ๋ฅผ ์ฌ์ฉํ ์ ์์ ๋ฟ ์๋๋ผ,this.$get(url, data)
์ ๊ฐ์ด ๋ณ๋์ ์ค์ ์์ด ๊ณตํต์ผ๋ก ์ค์ ํ ๊ธฐ๋ณธ config ๊ฐ ์ ์ฉ๋Axios Default Alias Methods
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
- /src/views/AxiosTestView.vue
<script>
export default {
name: "AxiosTestView",
data() {
return {
productList: Array["product"],
product: {
productName: "",
price: 0,
category: "",
},
};
},
created() {
this.getList();
},
methods: {
async getList() {
this.productList = await this.$get("/test");
},
},
};
</script>
๋จ,
Vue
์data() Closure
๋Vanilla JS
์์ ์ฌ์ฉํ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์Trick
๊ณผ๋ ๋ฌ๋ฆฌnew Array(product)
๋ ์ฌ์ฉํ ์ ์๊ณ ,Array["product"]
๋ง ์ฌ์ฉํ ์ ์๋ค.
4. Refactor Axios with DTO Classes
์์ ๊ฐ์ด Options API ๋ด์ data ๋ฅผ ์ด์ฉํด Object
๋ฅผ DTO
๋ก ์ฌ์ฉํ๋ ๊ฒ์ ๋ค๋ฅธ Component ์์ ์ฌ์ฌ์ฉ ํ ์ ์๋ค.
๋ํ, ํ์์ ๋ฐ๋ผ Getter/Setter
๋ฅผ ๋ง๋ค๊ฑฐ๋ ์ ์ฝ์ ์ํด Wrapper
๋ฅผ ์ฌ์ฉํ๋ ๋ฑ ์ถ๊ฐ์ ์ธ ์ฒ๋ฆฌ๋ฅผ ์ฝ๋ ๋ถํ๊ธฐ๊ฐ ํ๋ค๋ค.
๋ฐ๋ผ์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ์ฑ์ด ์๋ ์ด๋ฐ Entities
๋ Vue
ํ์ผ์ด ์๋ ๋ณ๋์ JavaScript ํ์ผ๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ข๋ค. ๊ทธ๋ฆฌ๊ณ
๋จ์ Object ๋ณด๋ค๋ ์ข ๋ ๊ธฐ๋ฅ์ด ๋ง์ Class
๋ฅผ ์ด์ฉํด DTO
๋ฅผ ๋ง๋ค์ด ๊ด๋ฆฌํ ์ ์๋ค.
- /src/dto/Product.js
export default class Product {
productName;
price;
category;
constructor(productName, price, category) {
this._productName = productName;
this._price = price;
this._category = category;
}
}
- /src/views/AxiosTestView.vue
<script>
import Product from "@/dto/Product";
export default {
name: "AxiosTestView",
data() {
return {
productList: Array[Product],
};
},
created() {
this.getList();
},
methods: {
async getList() {
this.productList = await this.$get("/test");
},
},
};
</script>
Reference
- ๊ณ ์น์. Vue.js ํ๋ก์ ํธ ํฌ์ ์ผ์ฃผ์ผ ์ . ๋น์ ์ดํผ๋ธ๋ฆญ Chapter 7, 2021.
- โAxios.โ Axios Documents, accessed Dec. 29, 2022, Axios.
- โ์ฌ์ดํธ ๊ฐ ์์ฒญ ์์กฐ.โ ์ํค๋ฐฑ๊ณผ, Fab. 6, 2022, accessed Dec. 29, 2022, ์ฌ์ดํธ ๊ฐ ์์ฒญ ์์กฐ.
- โAbortController.โ MND, Oct. 10, 2022, accessed Dec. 29, 2022, Web APIs - AbortController.
- โURLSearchParams.โ MND, Oct. 10, 2022, accessed Dec. 29, 2022, Web APIs - URLSearchParams.