728x90

출처

설치

yarn 설치

Yarn은 프로젝트 관리자의 역할을 하는 패키지 관리자입니다. 간단한 프로젝트에서 작업하든 업계 단일 레포에서 작업하든, 오픈 소스 개발자이든 엔터프라이즈 사용자이든 Yarn이 지원합니다.

D:\workspace.nodejs>npm install -g yarn

nestjs 설치

D:\workspace.nodejs>npm i -g @nestjs/cli

프로젝트 생성

D:\workspace.nodejs>nest new nestjs_example
⚡  We will scaffold your app in a few seconds..

? Which package manager would you ❤️  to use? yarn
CREATE nestjs_example/.eslintrc.js (688 bytes)
CREATE nestjs_example/.prettierrc (54 bytes)
CREATE nestjs_example/nest-cli.json (179 bytes)
CREATE nestjs_example/package.json (2022 bytes)
CREATE nestjs_example/README.md (3420 bytes)
CREATE nestjs_example/tsconfig.build.json (101 bytes)
CREATE nestjs_example/tsconfig.json (567 bytes)
CREATE nestjs_example/src/app.controller.ts (286 bytes)
CREATE nestjs_example/src/app.module.ts (259 bytes)
CREATE nestjs_example/src/app.service.ts (150 bytes)
CREATE nestjs_example/src/main.ts (216 bytes)
CREATE nestjs_example/src/app.controller.spec.ts (639 bytes)
CREATE nestjs_example/test/jest-e2e.json (192 bytes)
CREATE nestjs_example/test/app.e2e-spec.ts (654 bytes)

√ Installation in progress... ☕

🚀  Successfully created project nestjs_example
👉  Get started with the following commands:

$ cd nestjs_example
$ yarn run start


                          Thanks for installing Nest 🙏
                 Please consider donating to our open collective
                        to help us maintain this package.


               🍷  Donate: https://opencollective.com/nest


D:\workspace.nodejs>

src\main.ts 소스

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

실행

npm run start:dev 를 입력하면, 변경사항이 감지되었을 경우 직접 서버를 다시 키지 않아도 이를 감지하여 서버를 자동으로 재시동해준다.

D:\workspace.nodejs>cd nestjs_example

D:\workspace.nodejs\nestjs_example>npm run start

> nestjs_example@0.0.1 start
> nest start

[Nest] 2784  - 2024. 08. 07. 오후 11:53:47     LOG [NestFactory] Starting Nest application...
[Nest] 2784  - 2024. 08. 07. 오후 11:53:47     LOG [InstanceLoader] AppModule dependencies initialized +7ms
[Nest] 2784  - 2024. 08. 07. 오후 11:53:47     LOG [RoutesResolver] AppController {/}: +3ms
[Nest] 2784  - 2024. 08. 07. 오후 11:53:47     LOG [RouterExplorer] Mapped {/, GET} route +1ms
[Nest] 2784  - 2024. 08. 07. 오후 11:53:47     LOG [NestApplication] Nest application successfully started +2ms
728x90
728x90

HTML 소스

input 박스에 inputtype="number" 속성 추가

<form id="frmElMember" onsubmit="return submitCheckIt()">
  <input name="applied_power" inputtype="number">
</form>

JavaScript 소스

$(document).ready(function() {
	
	// input 박스의 key 눌러 졌을때 이벤트
	$('input[inputtype="number"]').on('change, keyup', function() {
		var value = $(this).val();
		// 숫자를 제외한 문자 제거
		var value = value.replace(/[^0-9]/g, '');
		// 3자리 단위로 콤마(,) 추가
		value = value.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
		$(this).val(value);
	});

    // Input 박스의 값을 3자리 단위로 콤마(,) 추가
	var inputNumber = $('input[inputtype="number"]');
	inputNumber.each(function (index, item) {
		var value = $(item).val();
		var value = value.replace(/[^0-9]/g, '');
		value = value.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
		$(item).val(value);
	});
});

// submit 체크 - submit시 콤마 제거
function submitCheckIt() {
	var inputNumber = $('input[inputtype="number"]');
	inputNumber.each(function (index, item) {
		var value = $(item).val();
		var value = value.replace(/[^0-9]/g, '');
		$(item).val(value);
	});
	
	return true;
}
728x90
728x90

출처

환경설정

set ANDROID_SDK_ROOT=C:\Android\sdk-tools-windows
set PATH=%PATH%;C:\Server\node-v18.20.3;%APPDATA%\npm;%ANDROID_SDK_ROOT%\platform-tools;%ANDROID_SDK_ROOT%\emulator

ionic 설치

D:\project>npm install -g ionic@5.4.16
D:\project>ionic -v
5.4.16

프로젝트 생성

D:\project>ionic start myApp tabs

Pick a framework!

Please select the JavaScript framework to use for your new app. To bypass this prompt next time, supply a value for the
--type option.

? Framework: Angular
√ Preparing directory .\myApp - done!
√ Downloading and extracting tabs starter - done!

Installing dependencies may take several minutes.

  ──────────────────────────────────────────────────────────────────

     Ionic Studio, a powerful, local editor made with love by Ionic

                  Lightning fast app creation
         Quickest & easiest way to get started with Ionic

        Learn more: https://ion.link/studio

  ──────────────────────────────────────────────────────────────────


> npm.cmd i
npm warn deprecated inflight@1.0.6: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm warn deprecated @humanwhocodes/config-array@0.11.14: Use @eslint/config-array instead
npm warn deprecated rimraf@3.0.2: Rimraf versions prior to v4 are no longer supported
npm warn deprecated glob@7.2.3: Glob versions prior to v9 are no longer supported
npm warn deprecated @humanwhocodes/object-schema@2.0.3: Use @eslint/object-schema instead

added 1195 packages, and audited 1196 packages in 2m

220 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
> git.exe init
Initialized empty Git repository in D:/project/myApp/.git/
> git.exe add -A
warning: in the working copy of '.browserslistrc', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.editorconfig', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.eslintrc.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.gitignore', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.vscode/extensions.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.vscode/settings.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'angular.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'ionic.config.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'karma.conf.js', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'package-lock.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'package.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app-routing.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app.component.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app.component.spec.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app.component.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/explore-container/explore-container.component.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/explore-container/explore-container.component.scss', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/explore-container/explore-container.component.spec.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/explore-container/explore-container.component.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/explore-container/explore-container.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab1/tab1-routing.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab1/tab1.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab1/tab1.page.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab1/tab1.page.spec.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab1/tab1.page.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab2/tab2-routing.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab2/tab2.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab2/tab2.page.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab2/tab2.page.spec.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab2/tab2.page.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab3/tab3-routing.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab3/tab3.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab3/tab3.page.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab3/tab3.page.spec.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tab3/tab3.page.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tabs/tabs-routing.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tabs/tabs.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tabs/tabs.page.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tabs/tabs.page.scss', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tabs/tabs.page.spec.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/tabs/tabs.page.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/assets/shapes.svg', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/environments/environment.prod.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/environments/environment.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/global.scss', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/index.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/main.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/polyfills.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/test.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/theme/variables.scss', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/zone-flags.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'tsconfig.app.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'tsconfig.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'tsconfig.spec.json', LF will be replaced by CRLF the next time Git touches it
> git.exe commit -m "Initial commit" --no-gpg-sign
Author identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'xxx@DESKTOP-784ARID.(none)')
[WARN] Error encountered during commit. Disabling further git operations.

[INFO] Next Steps:

       - Go to your newly created project: cd .\myApp
       - Run ionic serve within the app directory to see your app
       - Build features and components: https://ion.link/scaffolding-docs
       - Run your app on a hardware or virtual device: https://ion.link/running-docs

실행

D:\project>cd myApp

D:\project\myApp>ionic serve
> ng.cmd run app:serve --host=localhost --port=8100
[ng] - Generating browser application bundles (phase: setup)...
[ng] √ Browser application bundle generation complete.

capacitor 기본 패키지 설치

D:\project\myApp>npm install -g @capacitor/core@5.1.1
D:\project\myApp>npm install -g @capacitor/cli@5.1.1
D:\project\myApp>capacitor --version
5.1.1

capacitor/android 패키지 설치

D:\project\myApp>npm install -g @capacitor/android@5.1.1

android

D:\project\myApp>npx cap add android
√ Adding native android project in android in 47.32ms
√ add in 48.01ms
[warn] sync could not run--missing www directory.
[success] android platform added!
Follow the Developer Workflow guide to get building:
https://capacitorjs.com/docs/basics/workflow

[info] Opening Android project at: android.

cap init

D:\project\myApp>npx cap init
[?] What is the name of your app?
    This should be a human-friendly app name, like what you'd see in the App Store.
√ Name ... myApp
[?] What should be the Package ID for your app?
    Package IDs (aka Bundle ID in iOS and Application ID in Android) are unique identifiers for apps. They must be in
    reverse domain name notation, generally representing a domain name that you or your company owns.
√ Package ID ... com.example.app
√ Creating capacitor.config.ts in D:\project\myApp in 7.19ms
[success] capacitor.config.ts created!

Next steps:
https://capacitorjs.com/docs/getting-started#where-to-go-next
[?] Join the Ionic Community! 💙
    Connect with millions of developers on the Ionic Forum and get access to live events, news updates, and more.
√ Create free Ionic account? ... yes
[?] Would you like to help improve Capacitor by sharing anonymous usage data? 💖
    Read more about what is being collected and why here: https://capacitorjs.com/telemetry. You can change your mind at
    any time by using the npx cap telemetry command.
√ Share anonymous usage data? ... yes

Thank you for helping to make Capacitor better! 💖
Information about the data we collect is available on our website: https://capacitorjs.com/telemetry

빌드

D:\project\myApp>npm run build

> myApp@0.0.1 build
> ng build

√ Browser application bundle generation complete.
√ Copying assets complete.
- Generating index html...20 rules skipped due to selector errors:
  :host-context([dir=rtl]) .ion-float-start -> Unknown pseudo-class :host-context([object Object])
  .ion-float-start:dir(rtl) -> Unknown pseudo-class :dir
  :host-context([dir=rtl]) .ion-float-end -> Unknown pseudo-class :host-context([object Object])
  .ion-float-end:dir(rtl) -> Unknown pseudo-class :dir
  :host-context([dir=rtl]) .ion-float-sm-start -> Unknown pseudo-class :host-context([object Object])
  .ion-float-sm-start:dir(rtl) -> Unknown pseudo-class :dir
  :host-context([dir=rtl]) .ion-float-sm-end -> Unknown pseudo-class :host-context([object Object])
  .ion-float-sm-end:dir(rtl) -> Unknown pseudo-class :dir
  :host-context([dir=rtl]) .ion-float-md-start -> Unknown pseudo-class :host-context([object Object])
  .ion-float-md-start:dir(rtl) -> Unknown pseudo-class :dir
  :host-context([dir=rtl]) .ion-float-md-end -> Unknown pseudo-class :host-context([object Object])
  .ion-float-md-end:dir(rtl) -> Unknown pseudo-class :dir
  :host-context([dir=rtl]) .ion-float-lg-start -> Unknown pseudo-class :host-context([object Object])
  .ion-float-lg-start:dir(rtl) -> Unknown pseudo-class :dir
  :host-context([dir=rtl]) .ion-float-lg-end -> Unknown pseudo-class :host-context([object Object])
  .ion-float-lg-end:dir(rtl) -> Unknown pseudo-class :dir
  :host-context([dir=rtl]) .ion-float-xl-start -> Unknown pseudo-class :host-context([object Object])
  .ion-float-xl-start:dir(rtl) -> Unknown pseudo-class :dir
  :host-context([dir=rtl]) .ion-float-xl-end -> Unknown pseudo-class :host-context([object Object])
  .ion-float-xl-end:dir(rtl) -> Unknown pseudo-class :dir
√ Index html generation complete.

Initial chunk files                   | Names                   |  Raw size | Estimated transfer size
main.5780a7f2819da0c5.js              | main                    | 418.61 kB |               110.08 kB
polyfills.a945b0249cb630b5.js         | polyfills               |  34.70 kB |                11.25 kB
styles.d2b228d0a7e34779.css           | styles                  |  28.79 kB |                 4.43 kB
runtime.3f52e205fd467571.js           | runtime                 |   4.73 kB |                 2.27 kB

                                      | Initial total           | 486.84 kB |               128.03 kB

Lazy chunk files                      | Names                   |  Raw size | Estimated transfer size
polyfills-core-js.c76198334f717402.js | polyfills-core-js       |  94.03 kB |                28.56 kB
2885.07914c80a2400934.js              | -                       |  73.73 kB |                14.07 kB
3506.f1bc6225762d05be.js              | -                       |  55.68 kB |                 7.39 kB
2348.f47b57c1870919b7.js              | -                       |  47.08 kB |                 5.74 kB
7720.29d793ddce51db35.js              | -                       |  41.80 kB |                 9.39 kB
9344.3c79e54f9b487dd0.js              | -                       |  41.08 kB |                 5.70 kB
7076.59ff91c7b2168949.js              | -                       |  38.45 kB |                 6.87 kB
5222.ff26a67661322112.js              | -                       |  35.56 kB |                 6.43 kB
4591.e7a7265e81e3da53.js              | -                       |  28.50 kB |                 5.72 kB
8477.5a1d7782cb7ad812.js              | -                       |  28.23 kB |                 5.55 kB
2560.0a7bc99cfe318ca9.js              | -                       |  27.97 kB |                 5.26 kB
441.d6c6dc38fe064a81.js               | -                       |  27.09 kB |                 6.89 kB
5197.ec55c9b963a8f10e.js              | -                       |  24.99 kB |                 5.26 kB
8193.ec42552ea5af8b55.js              | -                       |  24.39 kB |                 4.44 kB
2075.fdd43d8e56169f84.js              | -                       |  24.18 kB |                 5.30 kB
6433.4151df5b6f30dbcd.js              | -                       |  24.17 kB |                 6.03 kB
8814.01c6630f830c5e72.js              | -                       |  23.18 kB |                 4.39 kB
4463.3b528b013cb14d92.js              | -                       |  22.29 kB |                 3.87 kB
5949.0d2694bbb759106c.js              | -                       |  20.80 kB |                 4.18 kB
3814.192ed711c121bbb4.js              | -                       |  20.78 kB |                 3.59 kB
common.28ef6e9c0b579e2e.js            | common                  |  20.53 kB |                 6.11 kB
2415.7fb0ecad5cc2bd2d.js              | -                       |  20.14 kB |                 5.07 kB
9977.b1441e2758751932.js              | -                       |  19.56 kB |                 1.98 kB
4406.801dc3b596d0a01b.js              | -                       |  19.07 kB |                 3.39 kB
polyfills-dom.bf542500b6fca113.js     | polyfills-dom           |  18.48 kB |                 5.16 kB
8066.c17ca0f6e80ad25b.js              | -                       |  16.70 kB |                 3.26 kB
8314.4818f467b9405d39.js              | -                       |  15.03 kB |                 3.14 kB
3511.266e06f47f10d808.js              | -                       |  14.59 kB |                 2.61 kB
1293.edd386430352426a.js              | -                       |  13.62 kB |                 4.41 kB
3162.808b0fc5ca2f047e.js              | -                       |  12.34 kB |                 2.50 kB
5712.dee2db82c57c5d6a.js              | -                       |  12.28 kB |                 3.89 kB
2375.cc91884e7539b704.js              | -                       |  11.85 kB |                 3.05 kB
8584.32115f49a90f7457.js              | -                       |  11.85 kB |                 2.42 kB
8970.d976f88aac373b61.js              | -                       |  11.81 kB |                 4.05 kB
4699.01733b3942afbe92.js              | ios-transition-js       |  10.68 kB |                 2.73 kB
6840.17839ae9fd6315cc.js              | -                       |  10.40 kB |                 2.31 kB
7372.ce92827f3ad2c2b7.js              | -                       |  10.03 kB |                 2.68 kB
1459.55be0475961bfcff.js              | -                       |   9.78 kB |                 3.15 kB
5100.6eba1730ffd58dd4.js              | -                       |   9.08 kB |                 1.53 kB
6024.129ca0127de0423c.js              | -                       |   7.25 kB |                 1.36 kB
7428.c1c7998cfe4d68c5.js              | -                       |   7.22 kB |                 2.19 kB
8805.51bf5a1b0007a860.js              | -                       |   6.42 kB |                 1.61 kB
4171.ca2e493f5a58fedf.js              | -                       |   6.22 kB |                 1.56 kB
7030.cf5128ce3d43bfdf.js              | -                       |   5.68 kB |                 2.04 kB
2144.5d46fa3641b801f2.js              | ios-transition-js       |   5.34 kB |                 2.08 kB
8361.6999f086673987db.js              | input-shims-0314bbe5-js |   5.04 kB |                 1.92 kB
1102.f4f7b64d666ca729.js              | -                       |   4.27 kB |                 1.53 kB
1049.3b9123fb26df3c32.js              | -                       |   4.24 kB |                 1.18 kB
5887.98b91cb4ef896dd6.js              | -                       |   3.37 kB |                 1.14 kB
964.a047a0655bd3ad37.js               | -                       |   3.17 kB |               969 bytes
9013.ebee29c37be87a93.js              | -                       |   2.88 kB |                 1.08 kB
6521.d6c81fd9c1411df5.js              | -                       |   2.29 kB |                 1.11 kB
4183.515f99e4c38e2301.js              | -                       |   1.85 kB |               761 bytes
5695.66247865f4658b0e.js              | tabs-tabs-module        |   1.80 kB |               662 bytes
7356.911eacb1ce959b5e.js              | index-79b30591-js       |   1.65 kB |               753 bytes
7240.6140dc51b67080fd.js              | -                       |   1.44 kB |               507 bytes
4711.e3500c3b84a19d85.js              | tab1-tab1-module        |   1.20 kB |               568 bytes
5113.fb59a4c1330a649d.js              | tab3-tab3-module        |   1.20 kB |               568 bytes
5378.fa069c1798e166e8.js              | tab2-tab2-module        |   1.20 kB |               569 bytes
1577.d89a56c29ce4c421.js              | -                       |   1.14 kB |               636 bytes
7179.80391eb100990080.js              | md-transition-js        |   1.07 kB |               488 bytes
3810.ad6dd10d2e425b4f.js              | status-tap-17122cea-js  | 528 bytes |               330 bytes

Build at: 2024-07-05T14:43:19.299Z - Hash: fe605ccf22b29b8d - Time: 2807ms

capacitor 동기화

D:\project\myApp>npx cap sync android
√ Copying web assets from www to android\app\src\main\assets\public in 428.78ms
√ Creating capacitor.config.json in android\app\src\main\assets in 687.10μs
√ copy android in 440.24ms
√ Updating Android plugins in 2.44ms
√ update android in 24.39ms
[info] Sync finished in 0.57s

안드로이드 스튜디오 실행

D:\project\myApp>npx cap open android
[info] Opening Android project at: android.
728x90
728x90

출처

커밋 로그 확인

C:\project>git log --oneline
d09c1ef (HEAD -> master, origin/master) JSON 라이브러리 참조 추가
01eac01 멤버 권한 체크 메뉴 변경
80a8d17 Member 관련 ID 검사 조건 수정

git reset : 커밋 취소하기 (변경된 파일 되돌리기 - 추가된 파일은 삭제 하지 않음)

C:\project>git reset --hard d09c1ef
Updating files: 100% (1865/1865), done.
HEAD is now at d09c1ef JSON 라이브러리 참조 추가

git status : 현재 상태 확인 (추가된 파일 확인)

C:\project>git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        kanji/kanji-jouyou.json

nothing added to commit but untracked files present (use "git add" to track)

삭제 대상(Untracked files) 목록 확인

C:\project>git clean -f
Removing kanji/kanji-jouyou.json​

Untracked files 파일 삭제

C:\project>git clean -n
Would remove kanji/kanji-jouyou.json
728x90
728x90

출처

Maven pom.xml 설정

Maven 배포시 프로파일 선택 옵션 : mvn clean package -P prod

  <build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
      <resource>
        <directory>src/main/resources/bluexmas-${profile}</directory>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </resource>
    </resources>
    
    <!-- 생략 -->  
  </build>
  
  <profiles>
    <profile>
      <id>dev</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <profile>dev</profile>
      </properties>
    </profile>
    <profile>
      <id>local</id>
      <properties>
        <profile>local</profile>
      </properties>
    </profile>
    <profile>
      <id>prod</id>
        <properties>
          <profile>prod</profile>
      </properties>
    </profile>
  </profiles>

src\main\resources\bluexmas-dev\config\config.properties

username=test
password=test!!

@Configuration 클래스 (PropertyConfig.java)

@Bean(name="config") : Bean 객체 config 이름으로 스프링 컨테이너에 로딩

package com.bluexmas.config;

import java.io.IOException;

import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

@Configuration
public class PropertyConfig {

	@Bean(name="config")
	public static PropertiesFactoryBean config() throws IOException {
		PropertiesFactoryBean pspc = new PropertiesFactoryBean();
		Resource[] resources = new PathMatchingResourcePatternResolver()
				.getResources("classpath:/config/config.properties");
		pspc.setLocations(resources);
		return pspc;
	}
}

Config 값 참조

@Resource(name="config") : config 이름의 Properties 객체 참조
@Value("#{config['username']}") : config 이름의 Properties 객체에서 username 값 참조

package com.bluexmas.controller;

import java.util.Properties;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class SampleController {
	
	@Resource(name="config")
	private Properties config;
	
	@Value("#{config['username']}")
	private String username;
	
	@ResponseBody
	@RequestMapping("/sample")
	public String sample() {
		System.out.println("username.1 = " + config.get("username"));
		System.out.println("username.2 = " + username);
		
		String data = "@ResponseBody 어노테이션을 통해 반환";
		return data;
	}
	
}
728x90
728x90

출처

Maven pom.xml 설정

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.2.3.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.1.1</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.6</version>
    </dependency>
    <!-- mybatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.4.2</version>
    </dependency>
    <!-- mybatis spring -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.4</version>
      <scope>provided</scope>
    </dependency>

application.properties

## MySQL
spring.datasource.driver-class-name=org.gjt.mm.mysql.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test_db?user=user1&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.username=user1
spring.datasource.password=user1!!

# 패키지 result tpye에 명을 생략할 수 있도록 alias 설정
mybatis.type-aliases-package=com.bluexmas.domain

# model 프로퍼티 camel case 설정
# mybatis.configuration.map-underscore-to-camel-case=true

# Mybatis mapper 위치 설정
mybatis.mapper-locations=classpath:/**/**.xml

Domain

package com.bluexmas.domain;

import java.sql.Date;

import lombok.Data;

@Data
public class Notice {
	
	// pk
	private int notice_no;
	
	private String notice_type;
	private String title;
	private String content;
	private int hit;
	private int reg_no;
	private Date reg_dt;
	private Date upt_dt;
	private String del_yn;
	private Date del_dt;
	
}

Persistence

package com.bluexmas.persistence;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Mapper;

import com.bluexmas.domain.Notice;

@Mapper
public interface NoticeMapper {

	public Notice selectNotice(Map<String, Object> params);

	public int insertNotice(Notice notice);

	public int updateNotice(Notice notice);

	public int deleteNotice(Map<String, Object> params);

	public int getCount();

	public List listNotice(Map<String, Object> map);

}

Service

package com.bluexmas.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bluexmas.domain.Notice;
import com.bluexmas.persistence.NoticeMapper;

@Service
public class NoticeService {

	@Autowired
	private NoticeMapper noticeMapper;

	public Notice selectNotice(int noticeNo) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("notice_no",noticeNo);
		return noticeMapper.selectNotice(params);
	}

	public int insertNotice(Notice notice) {
		return noticeMapper.insertNotice(notice);
	}

	public int updateNotice(Notice notice) {
		return noticeMapper.updateNotice(notice);
	}

	public int deleteNotice(int noticeNo) {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("notice_no",noticeNo);
		return noticeMapper.deleteNotice(params);
	}

	public int getCount() {
		return noticeMapper.getCount();
	}

	public List listNotice() throws Exception {
		Map<String, Object> params = new HashMap<String, Object>();
		return noticeMapper.listNotice(params);
	}
}

src\main\mybatis\com\bluexmas\persistence\NoticeMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.bluexmas.persistence.NoticeMapper">

	<!-- selectNotice -->
	<select id="selectNotice" parameterType="map" resultType="com.bluexmas.domain.Notice">
		select *
		  from notice
		 where notice_no = #{notice_no}
	</select>

	<!-- insertNotice -->
	<insert id="insertNotice" parameterType="com.bluexmas.domain.Notice" statementType="PREPARED">
		insert into notice(
		    <trim suffixOverrides=",">
		      <if test="notice_type != null">notice_type ,</if>
		      <if test="title != null">title ,</if>
		      <if test="content != null">content ,</if>
		      <if test="hit != null">hit ,</if>
		      <if test="reg_no != null">reg_no ,</if>
		      <if test="reg_dt != null">reg_dt ,</if>
		      <if test="upt_dt != null">upt_dt ,</if>
		      <if test="del_yn != null">del_yn ,</if>
		      <if test="del_dt != null">del_dt ,</if>
		    </trim>
		    ) values (
		    <trim suffixOverrides=",">
		      <if test="notice_type != null">#{notice_type, jdbcType=VARCHAR} ,</if>
		      <if test="title != null">#{title, jdbcType=VARCHAR} ,</if>
		      <if test="content != null">#{content, jdbcType=VARCHAR} ,</if>
		      <if test="hit != null">#{hit, jdbcType=INTEGER} ,</if>
		      <if test="reg_no != null">#{reg_no, jdbcType=INTEGER} ,</if>
		      <if test="reg_dt != null">#{reg_dt, jdbcType=TIMESTAMP} ,</if>
		      <if test="upt_dt != null">#{upt_dt, jdbcType=TIMESTAMP} ,</if>
		      <if test="del_yn != null">#{del_yn, jdbcType=VARCHAR} ,</if>
		      <if test="del_dt != null">#{del_dt, jdbcType=TIMESTAMP} ,</if>
		    </trim>
		)
		<selectKey keyProperty="notice_no" resultType="Integer">
			SELECT LAST_INSERT_ID()
		</selectKey>
	</insert>

	<!-- updateNotice -->
	<update id="updateNotice" parameterType="com.bluexmas.domain.Notice" statementType="PREPARED">
		update notice
		    <trim prefix="SET" suffixOverrides=",">
		      <if test="notice_type != null">notice_type = #{notice_type, jdbcType=VARCHAR} ,</if>
		      <if test="title != null">title = #{title, jdbcType=VARCHAR} ,</if>
		      <if test="content != null">content = #{content, jdbcType=VARCHAR} ,</if>
		      <if test="hit != null">hit = #{hit, jdbcType=INTEGER} ,</if>
		      <if test="reg_no != null">reg_no = #{reg_no, jdbcType=INTEGER} ,</if>
		      <if test="reg_dt != null">reg_dt = #{reg_dt, jdbcType=TIMESTAMP} ,</if>
		      <if test="upt_dt != null">upt_dt = #{upt_dt, jdbcType=TIMESTAMP} ,</if>
		      <if test="del_yn != null">del_yn = #{del_yn, jdbcType=VARCHAR} ,</if>
		      <if test="del_dt != null">del_dt = #{del_dt, jdbcType=TIMESTAMP} ,</if>
		    </trim>
		 where notice_no = #{notice_no}
	</update>

	<!-- deleteNotice -->
	<delete id="deleteNotice" parameterType="map" statementType="PREPARED">
		delete from notice
		 where notice_no = #{notice_no}
	</delete>

	<!-- getCount -->
	<select id="getCount" resultType="int">
		select count(*)
		  from notice
	</select>

	<!-- listNotice -->
	<select id="listNotice" parameterType="map" resultType="com.bluexmas.domain.Notice">
		select a.*
		  FROM notice a
	</select>

</mapper>

Controller 소스

package com.bluexmas.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.bluexmas.domain.Notice;
import com.bluexmas.service.NoticeService;

@Controller
public class NoticeController {

	@Autowired
	private NoticeService noticeService;
	
	@RequestMapping(value="/notice_list.do", method=RequestMethod.GET)
	public @ResponseBody Map<String, Object> notice_list(ModelMap modelMap) throws Exception {
		//
		Map<String, Object> result = new HashMap<> ();
		
		//
		List<Notice> listNotice = noticeService.listNotice();
		result.put("notice_list", listNotice);
		
		//
		return result;
	}
}

실행

728x90
728x90

출처

Maven pom.xml 설정

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.2.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-tomcat -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>3.1.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper -->
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-jasper</artifactId>
      <version>9.0.31</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

Spring Boot JSP ViewResolver 구성

JSP 파일 위치를 해결하려면 두 가지 방법을 사용할 수 있습니다.

1) application.properties에 항목 추가

#http port
server.port=7070

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

2) JSP 페이지를 제공하도록 InternalResourceViewResolver 구성

package com.bluexmas.config;
 
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
 
@Configuration
@EnableWebMvc
@ComponentScan
public class MvcConfiguration extends WebMvcConfigurerAdapter
{
  @Override
  public void configureViewResolvers(ViewResolverRegistry registry) {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/view/");
    resolver.setSuffix(".jsp");
    resolver.setViewClass(JstlView.class);
    registry.viewResolver(resolver);
  }
}

Controller 소스

package com.bluexmas.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class SampleController {
	
	/*
	 * 스프링부트에서의 jsp 호출 테스트
	 */
	@RequestMapping("/jspSample")
	public String jspSample(ModelMap modelMap) throws Exception {
		modelMap.put("name", "홍길동");

		List jspSample = new ArrayList();
		jspSample.add("국어 : 100점");
		jspSample.add("수학 : 90점");
		jspSample.add("영어 : 75점");

		modelMap.put("list", jspSample);
		
		return "jspSample";
	}
}

View(JSP) - src\main\webapp\WEB-INF\jsp\jspSample.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
 
<html>
<head>
<meta charset="UTF-8">
    <title>JSP Sample Page</title>
</head>
    <body>
 
       <div>[${name}]님의 시험성적입니다.</div>
 
        <c:forEach var="item" items="${list}">
         ${item} <br />
        </c:forEach>
 
    </body>
</html>

실행

728x90
728x90

출처

Maven pom.xml 설정

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.2.4.RELEASE</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-tomcat -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
      <version>3.1.0</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper -->
    <dependency>
      <groupId>org.apache.tomcat.embed</groupId>
      <artifactId>tomcat-embed-jasper</artifactId>
      <version>9.0.31</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

Spring Boot main 소스

Spring Boot main 소스 하위 패키지만 자동으로 로딩(Controller, Service)

package com.bluexmas;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

@SpringBootApplication
//@ComponentScan(basePackages = {"com.bluexmas.controller"})
public class BluexmasApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(BluexmasApplication.class, args);
    }
    
}

Controller 소스

package com.bluexmas.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class SampleController {
	
	@ResponseBody
	@RequestMapping("/sample")
	public String sample() {
		String data = "@ResponseBody 어노테이션을 통해 반환";
		return data;
	}

}

실행

728x90

+ Recent posts