thymeleaf

Thymeleaf ์„œ๋ฒ„์—์„œ view๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํƒœ๊ทธ ํ˜•์‹์˜ ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉฐ vue์™€ ์œ ์‚ฌํ•˜๋‹ค. ๊ธฐ๋ณธ ๋ฌธ๋ฒ• thymeleaf ๊ณต์‹ ํŠœํ† ๋ฆฌ์–ผ ์—์„œ ๊ธฐ๋ณธ์ ์ธ ๋ฌธ๋ฒ•์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ํƒœ๊ทธ ์•ˆ์— th:์†์„ฑ="๊ฐ’" ํ˜•ํƒœ์˜ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. text <span th:text="${text}">default text</span>: ์„œ๋ฒ„์—์„œ โ€™textโ€™๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ •์˜ํ•œ ํƒœ๊ทธ๊ฐ€ ์žˆ์œผ๋ฉด text๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. text๋ณ€์ˆ˜๊ฐ€ ์—†์œผ๋ฉด <span>default text</span>๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. utext <span th:utext="${utext}">default text</span>: โ€™textโ€™ ์ด๋ฆ„์œผ๋กœ ์ •์˜ํ•œ ํ…์ŠคํŠธ๋ฅผ โ€˜spanโ€™ ํƒœ๊ทธ์— ๋„ฃ์–ด ํ‘œ์‹œํ•œ๋‹ค. โ€™textโ€™๋ณ€์ˆ˜๊ฐ€ ์—†์œผ๋ฉด โ€˜default textโ€™๋ฅผ ํ‘œ์‹œํ•œ๋‹ค. fragment <div th:fragment="name">: โ€™nameโ€™ ์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ fragment๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. fragment๋Š” th:replace, th:copy ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์žฌํ™œ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. copy <div th:copy="this::name">: ํ˜„์žฌ ํŒŒ์ผ์˜ โ€™nameโ€™ fragment๋ฅผ โ€˜divโ€™ํƒœ๊ทธ๋กœ ํ‘œํ˜„ํ•œ๋‹ค. โ€™thisโ€™ ๋Œ€์‹  ํŒŒ์ผ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค๋ฅธ ํŒŒ์ผ์˜ fragment๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. replace <div th:replace="this::name">: ํ˜„์žฌ ํŒŒ์ผ์˜ โ€™nameโ€™ fragment๋กœ ๋Œ€์ฒดํ•œ๋‹ค.(ํƒœ๊ทธ๋„ ๋ฐ”๋€๋‹ค.) โ€™thisโ€™ ๋Œ€์‹  ํŒŒ์ผ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค๋ฅธ ํŒŒ์ผ์˜ fragment๋ฅผ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค.

<span title='2022-06-29 20:00:00 +0900 KST'>June 29, 2022</span>&nbsp;ยท&nbsp;1 min&nbsp;ยท&nbsp;AswinBlue

Tailwind

Tailwind Css ํ”„๋ ˆ์ž„์›Œํฌ๋กœ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์œผ๋กœ css๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ํˆด์ด๋‹ค. Tailwind Docs Installation tailwind ๋ชจ๋“ˆ ์„ค์น˜ npm install -D tailwindcss@latest ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์น˜๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. npx tailwindcss init ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜๋ฉด ํ˜„์žฌ ๊ฒฝ๋กœ์— tailwind.config.js ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜๋ฉฐ, ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์—์„œ tailwind๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค. tailwind.config.js ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ๋œ๋‹ค. module.exports = { // ํฌํ•จํ•  ํ•ญ๋ชฉ content: ['./src/**/*.{html,js,jsx,ts,tsx, mustache}'], // ์ œ์™ธํ•  ํ•ญ๋ชฉ (์ตœ์‹  ๋ฒ„์ „์—์„œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๋ฌธ๋ฒ•) // purge: ["./src/**/*.html", "./src/**/*.js"], // jit mode๋Š” purge์™€ ํ•จ๊ป˜ ์„ธํŠธ๋กœ ์‚ฌ์šฉ๋˜์—ˆ๊ณ , ์„ธํŠธ๋กœ ์‚ฌ๋ผ์กŒ๋‹ค.(?) // mode: process.env.NODE_ENV ? 'jit' : undefined, darkMode: 'class', // [false, 'mdeia', 'class'] theme: { fontFamily: { display: ['Open Sans', 'sans-serif'], body: ['Open Sans', 'sans-serif'], }, extend: { fontSize: { 14: '14px', }, backgroundColor: { 'main-bg': '#FAFBFB', 'main-dark-bg': '#20232A', 'secondary-dark-bg': '#33373E', 'light-gray': '#F7F7F7', 'half-transparent': 'rgba(0, 0, 0, 0.5)', }, borderWidth: { 1: '1px', }, borderColor: { color: 'rgba(0, 0, 0, 0.1)', }, width: { 400: '400px', 760: '760px', 780: '780px', 800: '800px', 1000: '1000px', 1200: '1200px', 1400: '1400px', }, height: { 80: '80px', }, minHeight: { 590: '590px', }, backgroundImage: { 'hero-pattern': "url('https://demos.wrappixel.com/premium-admin-templates/react/flexy-react/main/static/media/welcome-bg-2x-svg.25338f53.svg')", }, }, }, plugins: [], }; tailwind๋Š” react์™€ ๊ฐ™์€ framework์—์„œ๋Š” ์ž๋™์œผ๋กœ ์ ์šฉ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ๊ทธ ์™ธ์˜ ๊ฒฝ์šฐ์—๋Š” postcss ๋“ฑ๊ณผ ๊ฐ™์€ ๋ชจ๋“ˆ์˜ ๋„์›€์ด ํ•„์š”ํ•˜๋‹ค. tailwind ๋ชจ๋“ˆ ์„ค์น˜์™€ tailwind.config.js ๊ตฌ์„ฑ์ด ๋๋‚ฌ๋‹ค๋ฉด, tailwind๋กœ ์ž‘์„ฑ๋œ css๋ฅผ ์ฝ”๋“œ์— ์ถ”๊ฐ€ํ•ด์ค˜์•ผ ํ•œ๋‹ค. index.css์— ์•„๋ž˜ ๊ตฌ๋ฌธ์„ ์ถ”๊ฐ€ํ•œ๋‹ค. @tailwind base; @tailwind components; @tailwind utilities; postcss ...

<span title='2022-06-02 21:55:38 +0900 KST'>June 2, 2022</span>&nbsp;ยท&nbsp;3 min&nbsp;ยท&nbsp;AswinBlue

Angular

Angular Angular JS์™€ Angular๋Š” ๋‹ค๋ฅด๋‹ค. Angular JS๋Š” ์ดˆ์ฐฝ๊ธฐ Angular๋ฅผ ์˜๋ฏธํ•˜๊ณ , ๊ทธ๋ƒฅ Angular๋Š” Angular2 ์ด์ƒ์˜ ๋ฒ„์ „์„ ์˜๋ฏธํ•œ๋‹ค. javascript๊ธฐ๋ฐ˜์˜ textscript๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ํ™•์žฅ์ž๊ฐ€ ts๋กœ ๋๋‚œ๋‹ค. ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ธํŒ… nodejs ์„ค์น˜ $ sudo apt install npm :nodejs์™€ npm ๋™์‹œ์— ์„ค์น˜ angular client ์„ค์น˜ $ npm install -g @angular/cli ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์„ค์น˜ workspace ์ƒ์„ฑ client ์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์œผ๋ฉด workspace๋ฅผ ์ƒ์„ฑํ•˜๊ณ  application์„ ์ƒ์„ฑํ•œ๋‹ค. $ ng new <application_name> ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์„ค์น˜ํ•œ๋‹ค. nodejs ๋ฒ„์ „์ด ๋‚ฎ๋‹ค๊ณ  ํ•œ๋‹ค. github์—์„œ ๋ฐ›์•„์„œ ๋นŒ๋“œํ•˜์—ฌ ์จ ๋ณด์ž. ...

<span title='2021-08-23 19:46:09 +0900 KST'>August 23, 2021</span>&nbsp;ยท&nbsp;4 min&nbsp;ยท&nbsp;AswinBlue

React basic

React basic ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ค์น˜ ๋ฐ ์‹คํ–‰ node.js ๋กœ ๋งŒ๋“ค์–ด์ง„ create-react-app ํˆด์„ ์ด์šฉํ•˜๋ฉด ์†์‰ฝ๊ฒŒ react ์•ฑ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. npm์„ ์„ค์น˜ํ•˜๊ณ  ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ create-react-app์„ ์„ค์น˜ํ•œ๋‹ค. npm install -g create-react-app ์›ํ•˜๋Š” ๊ฒฝ๋กœ์— ๋“ค์–ด๊ฐ€ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. create-react-app <NAME> : NAME ๊ฒฝ๋กœ์— ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ ์ฃผ์˜ : ํ”„๋กœ์ ํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ํด๋”๋ช…์€ ๋Œ€๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. ์‹คํ–‰ npm run start ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด localhost:3000์—์„œ ์›นํŽ˜์ด์ง€๋ฅผ ํผ๋ธ”๋ฆฌ์‹ฑํ•œ๋‹ค. ๊ธฐ๋ณธ ์„ค์ • ์‹คํ–‰ ํฌํŠธ package.json ํŒŒ์ผ์—์„œ "proxy": "http://localhost:3000/" ๊ณผ ๊ฐ™์ด ์ž…๋ ฅํ•˜๋ฉด ์‹คํ–‰์‹œ ํฌํŠธ๋ฅผ 3000์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ๋ณธ ๊ตฌ์กฐ /public/index.html ์—์„œ ๊ธฐ๋ณธ ํ™”๋ฉด ๊ตฌ์„ฑ โ€˜rootโ€™ ์ด๋ฆ„์œผ๋กœ ๋œ division์ด ์žˆ๋Š”๋ฐ, ์ด division์— ๋Œ€ํ•œ ์„ค์ •์€ javascript๋กœ ์ •์˜๋˜์–ด์žˆ๋‹ค. src ๊ฒฝ๋กœ์— javascriptํŒŒ์ผ๋“ค ๊ตฌ์„ฑ โ€˜index.jsโ€™ ์— ๋ฉ”์ธ ํ™”๋ฉด์— ์‚ฌ์šฉ๋œ ๊ฐ์ฒด๊ฐ€ ์ •์˜๋˜์–ด ์žˆ๋‹ค. ์•„๋ž˜ ๋‚ด์šฉ์€ id๊ฐ€ โ€˜rootโ€™ ์ธ division์— โ€˜Appโ€™์„ ์ ์šฉํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค. ...

<span title='2021-08-23 18:46:22 +0900 KST'>August 23, 2021</span>&nbsp;ยท&nbsp;19 min&nbsp;ยท&nbsp;AswinBlue

PythonCGI

python CGI CGI๋Š” Common Gateway Interface์˜ ์•ฝ์ž๋‹ค. web application์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์–ธ์–ด๋Š” ruby, java, php ๋“ฑ ๋‹ค์–‘ํ•˜์ง€๋งŒ ๋ชจ๋‘ CGI ๊ทœ์•ฝ์„ ๋”ฐ๋ผ web server์™€ ํ†ต์‹ ํ•œ๋‹ค. web server๋Š” ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ๋ฐ›์œผ๋ฉด ์•ฝ์†๋œ ์ด๋ฆ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ web application์— ์ „๋‹ฌํ•˜์—ฌ ์„œ๋กœ ๊ต๋ฅ˜ํ•œ๋‹ค. apache์—์„œ python์„ ์ด์šฉํ•ด web application์„ ๋งŒ๋“ค์–ด web server์™€ ํ†ต์‹ ํ•ด ๋ณด์ž. $ a2enmod CGI ๋ช…๋ น์œผ๋กœ apache์˜ CGI๋ฅผ ์ผœ ์ฃผ๊ณ , sudo service apache2 restart ๋กœ ์„ค์ • ์ ์šฉ /var/log/apache2/error.log ์•ˆ์— apache ์‹คํ–‰์‹œ ๋ฐœ์ƒํ•œ ์—๋Ÿฌ ๋กœ๊ทธ๊ฐ€ ๋‹ด๊ฒจ์žˆ๋‹ค. ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์›น ์„œ๋ฒ„์— ์š”์ฒญํ•  ๋•Œ ์›น ์„œ๋ฒ„๋Š” ์‘๋‹ต์œผ๋กœ ์›น ํŽ˜์ด์ง€์˜ ๋ฐ์ดํ„ฐ ํƒ€์ž…(ํ—ค๋”)์™€ ํ•จ๊ป˜ ์›น ํŽ˜์ด์ง€๋ฅผ ์ „์†กํ•œ๋‹ค. python CGI๋กœ๋Š” print("content-type:text/html; charset=UTF-8\n") ์™€ ๊ฐ™์ด ํ—ค๋”๋ฅผ ํ‘œ๊ธฐ๋‚ธ๋‹ค. ํ—ค๋”๋ฅผ ์ถœ๋ ฅํ•œ ๋‹ค์Œ ๋ถ€ํ„ฐ๋Š” body ๋ถ€๋ถ„์ด ์ถœ๋ ฅ๋œ๋‹ค. ํŠน์ • ์ฃผ์†Œ๋กœ Redirection์„ ํ•  ๋•Œ์—๋Š” print("location : index.py?id=title")์„ ์ด์šฉํ•œ๋‹ค. ( โ€˜:โ€™ ์ดํ›„ ๋ถ€ํ„ฐ โ€˜"โ€™ ๊นŒ์ง€๋Š” ์›ํ•˜๋Š”๋Œ€๋กœ ์ž‘์„ฑ) formatting string์—์„œ ํŠน์ • ๋ฌธ์ž์—ด์„ ๋‹ค๋ฅธ ๋ฌธ์ž๋กœ ์น˜ํ™˜ํ•˜๋Š” ๊ธฐ๋Šฅ ex) '{} {}'.format('one','tow') ex) '{a} {b}'.format(a='hello', b='world') python ํŒŒ์ผ์—์„œ ๋ฌธ์ž์—ด๊ณผ format ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ๋™์  html์„ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๋‹ค. CGI ๋ชจ๋“ˆ import cgi ๋กœ ๋ชจ๋“ˆ์„ ๋กœ๋“œํ•ด ์‚ฌ์šฉํ•œ๋‹ค. form = cgi.FieldStorage() form์€ jQuery์™€ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค. ex) pageId = form['id'].value : page์˜ id๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. HTML ์—ฐ๋™ input ํƒœ๊ทธ์˜ name ์†์„ฑ : input ํƒœ๊ทธ๋ฅผ ํŠน์ • ์ด๋ฆ„์œผ๋กœ CGI์— ์ „๋‹ฌํ•จ ex) ...

<span title='2020-07-02 19:15:21 +0900 KST'>July 2, 2020</span>&nbsp;ยท&nbsp;3 min&nbsp;ยท&nbsp;AswinBlue