728x90

출처

리눅스 버전 확인

bluesanta@bluesanta-AI-Series:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.3 LTS
Release:        24.04
Codename:       noble
bluesanta@bluesanta-AI-Series:~$ lsmod | grep amdgpu
amdgpu              19836928  5
amddrm_ttm_helper      12288  1 amdgpu
amdttm                131072  2 amdgpu,amddrm_ttm_helper
amddrm_buddy           24576  1 amdgpu
amdxcp                 16384  1 amdgpu
amddrm_exec            12288  1 amdgpu
drm_suballoc_helper    20480  1 amdgpu
amd_sched              61440  1 amdgpu
amdkcl                 36864  4 amd_sched,amdttm,amddrm_exec,amdgpu
drm_panel_backlight_quirks    12288  1 amdgpu
drm_display_helper    278528  1 amdgpu
cec                    94208  2 drm_display_helper,amdgpu
i2c_algo_bit           16384  1 amdgpu
drm_ttm_helper         16384  1 amdgpu
video                  77824  1 amdgpu
bluesanta@bluesanta-AI-Series:~$ dkms status
amdgpu/6.16.6-2255209.24.04, 6.14.0-37-generic, x86_64: installed

ComfyUI 설치

가상환경실행

bluesanta@bluesanta-AI-Series:~$ cd Application/stable_diffusion/
bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ source .venv/bin/activate
(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ 

ComfyUI 다운로드

(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ git clone https://github.com/comfyanonymous/ComfyUI.git

ComfyUI 참조 패키지 설치

(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ cd ComfyUI/
(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion/ComfyUI$ pip install -r requirements.txt

ComfyUI 실행

(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion/ComfyUI$ python main.py
Checkpoint files will always be loaded safely.
Total VRAM 14844 MB, total RAM 29688 MB
pytorch version: 2.9.1+rocm7.10.0
Set: torch.backends.cudnn.enabled = False for better AMD performance.
AMD arch: gfx1150
ROCm version: (7, 2)
Set vram state to: NORMAL_VRAM
Device: cuda:0 AMD Radeon 890M Graphics : native
Using async weight offloading with 2 streams
Enabled pinned memory 28203.0
Using sub quadratic optimization for attention, if you have memory or speed issues try using: --use-split-cross-attention
Python version: 3.12.3 (main, Nov  6 2025, 13:44:16) [GCC 13.3.0]
ComfyUI version: 0.7.0
****** User settings have been changed to be stored on the server instead of browser storage. ******
****** For multi-user setups add the --multi-user CLI argument to enable multiple user profiles. ******
ComfyUI frontend version: 1.35.9
[Prompt Server] web root: /home/bluesanta/Application/stable_diffusion/.venv/lib/python3.12/site-packages/comfyui_frontend_package/static
Total VRAM 14844 MB, total RAM 29688 MB
pytorch version: 2.9.1+rocm7.10.0
Set: torch.backends.cudnn.enabled = False for better AMD performance.
AMD arch: gfx1150
ROCm version: (7, 2)
Set vram state to: NORMAL_VRAM
Device: cuda:0 AMD Radeon 890M Graphics : native
Using async weight offloading with 2 streams
Enabled pinned memory 28203.0
 
Import times for custom nodes:
   0.0 seconds: /home/bluesanta/Application/stable_diffusion/ComfyUI/custom_nodes/websocket_image_save.py
 
Context impl SQLiteImpl.
Will assume non-transactional DDL.
No target revision found.
Starting server
 
To see the GUI go to: http://127.0.0.1:8188

ComfyUI Manager 설치

(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion/ComfyUI$ cd custom_nodes/
(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion/ComfyUI/custom_nodes$ git clone https://github.com/Comfy-Org/ComfyUI-Manager.git
(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion/ComfyUI/custom_nodes$ pip install -r ComfyUI-Manager/requirements.txt
728x90
728x90

출처

리눅스 버전 확인

bluesanta@bluesanta-AI-Series:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.3 LTS
Release:        24.04
Codename:       noble

AMD GPU 드라이버 설치

AMD GPU 설치 프로그램 설치

bluesanta@bluesanta-AI-Series:~$ wget https://repo.radeon.com/amdgpu-install/30.20.1/ubuntu/noble/amdgpu-install_7.1.1.70101-1_all.deb
bluesanta@bluesanta-AI-Series:~$ sudo dpkg -i amdgpu-install_7.1.1.70101-1_all.deb 
[sudo] password for bluesanta: 
Selecting previously unselected package amdgpu-install.
(Reading database ... 215673 files and directories currently installed.)
Preparing to unpack amdgpu-install_7.1.1.70101-1_all.deb ...
Unpacking amdgpu-install (30.20.1.0.30200100-2255209.24.04) ...
Setting up amdgpu-install (30.20.1.0.30200100-2255209.24.04) ...

ROCm 패키지 설치

bluesanta@bluesanta-AI-Series:~$ sudo amdgpu-install --usecase=rocm,hiplibsdk --no-dkms

설치 확인

(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ lsmod | grep amdgpu
amdgpu              19836928  6
amddrm_ttm_helper      12288  1 amdgpu
amdttm                131072  2 amdgpu,amddrm_ttm_helper
amddrm_buddy           24576  1 amdgpu
amdxcp                 16384  1 amdgpu
amddrm_exec            12288  1 amdgpu
drm_suballoc_helper    20480  1 amdgpu
amd_sched              61440  1 amdgpu
amdkcl                 36864  4 amd_sched,amdttm,amddrm_exec,amdgpu
drm_panel_backlight_quirks    12288  1 amdgpu
drm_display_helper    278528  1 amdgpu
cec                    94208  2 drm_display_helper,amdgpu
i2c_algo_bit           16384  1 amdgpu
drm_ttm_helper         16384  1 amdgpu
video                  77824  1 amdgpu
(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ dkms status
amdgpu/6.16.6-2255209.24.04, 6.14.0-37-generic, x86_64: installed

아키텍처 강제 인식

HX 370(gfx1150)은 최신 아키텍처이므로, PyTorch가 이를 인식하도록 환경 변수를 선언해야 합니다. 터미널에서 다음을 입력하거나 .bashrc에 추가

bluesanta@bluesanta-AI-Series:~$ vi ~/.bashrc

.bashrc 파일에 HSA_OVERRIDE_GFX_VERSION 값 설정

export HSA_OVERRIDE_GFX_VERSION=11.5.0

PyTorch 설치

가상환경만들기

bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ sudo apt install python3-venv
bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ python3 -m venv .venv
bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ source .venv/bin/activate
(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ 

ROCm 지원 PyTorch 빌드 및 설치

(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ python -m pip install --index-url https://repo.amd.com/rocm/whl/gfx1150/ torch torchvision torchaudio

적용 확인

(.venv) bluesanta@bluesanta-AI-Series:~/Application/stable_diffusion$ python -c "import torch; print(torch.cuda.is_available())"
True
728x90
728x90

출처

MicroPython Tools Plugin for JetBrains IDEs | JetBrains Marketplace

플러그인 설치

MicroPython Tools 설정 1

MicroPython Tools 설정 2

MicroPython Tools 도구 창 열기

소스 파일

from machine import Pin
import time

# Define the GPIO pin connected to the built-in LED
# (This may vary depending on your specific ESP32-C3 board)
led_pin = Pin(8, Pin.OUT) # Example: Assuming GPIO8 for the LED

while True:
    led_pin.on()  # Turn the LED on
    print("LED ON")
    time.sleep(1) # Wait for 1 second

    led_pin.off() # Turn the LED off
    print("LED OFF")
    time.sleep(1) # Wait for 1 second

Python 파일 실행

소스파일 선택 -> 오른쪽 메뉴에서 Execute File REPL 메뉴 실행

실행 콘솔 확인

728x90
728x90

출처

Node.js 설치

[bluesanta@localhost ~]$ cd ~
[bluesanta@localhost ~]$ curl -sL https://rpm.nodesource.com/setup_18.x -o nodesource_setup.sh
[bluesanta@localhost ~]$ sudo bash nodesource_setup.sh
   
2025-04-21 16:22:50 - Repository is configured and updated.
2025-04-21 16:22:50 - You can use N|solid Runtime as a node.js alternative
2025-04-21 16:22:50 - To install N|solid Runtime, run: dnf install nsolid -y
2025-04-21 16:22:50 - Run 'dnf install nodejs -y' to complete the installation.
[bluesanta@localhost ~]$ sudo dnf install nodejs openssl -y
[bluesanta@localhost ~]$ node --version
v18.20.8
[bluesanta@localhost ~]$ sudo npm install -g configurable-http-proxy

jupyterhub 설치

[bluesanta@localhost ~]$ su - 
[root@localhost ~]# pip3.11 install sudospawner

jupyterhub 관리자 계정 생성

[bluesanta@localhost ~]$ sudo groupadd jupyterhub
[bluesanta@localhost ~]$ sudo useradd -g jupyterhub -s /bin/bash -m jupyterhubapp

jupyterhub 관리자 계정 로그인

[bluesanta@localhost ~]$ su - jupyterhubapp
암호:
[jupyterhubapp@localhost ~]$ 

jupyterhub 실행

[jupyterhubapp@localhost ~]$ jupyterhub
[I 2025-04-21 16:59:44.638 JupyterHub app:3354] Running JupyterHub version 5.3.0
[I 2025-04-21 16:59:44.638 JupyterHub app:3384] Using Authenticator: jupyterhub.auth.PAMAuthenticator-5.3.0
[I 2025-04-21 16:59:44.638 JupyterHub app:3384] Using Spawner: jupyterhub.spawner.LocalProcessSpawner-5.3.0
[I 2025-04-21 16:59:44.638 JupyterHub app:3384] Using Proxy: jupyterhub.proxy.ConfigurableHTTPProxy-5.3.0
   
[I 2025-04-21 16:59:44.987 JupyterHub proxy:477] Adding route for Hub: / => http://127.0.0.1:8081
16:59:44.988 [ConfigProxy] info: Adding route / -> http://127.0.0.1:8081
16:59:44.988 [ConfigProxy] info: Route added / -> http://127.0.0.1:8081
16:59:44.989 [ConfigProxy] info: 201 POST /api/routes/ 
[I 2025-04-21 16:59:44.989 JupyterHub app:3778] JupyterHub is now running at http://:8000

jupyterhub_config.py 생성

[jupyterhubapp@localhost ~]$ cd /etc/jupyterhub/
[jupyterhubapp@localhost jupyterhub]$ jupyterhub --generate-config
Writing default config to: jupyterhub_config.py
[jupyterhubapp@localhost jupyterhub]$ ls
jupyterhub_config.py

jupyterhub 사용자 계정 만들기

[bluesanta@localhost ~]$ sudo useradd -g jupyterhub -s /bin/bash -m user01
[bluesanta@localhost ~]$ sudo passwd user01
user01 사용자의 비밀 번호 변경 중
새 암호:
새 암호 재입력:
passwd: 모든 인증 토큰이 성공적으로 업데이트 되었습니다.

jupyterhub_config.py 파일 수정

[bluesanta@localhost ~]$ sudo vi /etc/jupyterhub/jupyterhub_config.py
c.JupyterHub.hub_connect_ip = '0.0.0.0'
c.JupyterHub.port = 8000

c.Authenticator.whitelist = set({'user01'})
c.Authenticator.allow_all = True

c.PAMAuthenticator.admin_users = set({'jupyterhubapp'})
# c.PAMAuthenticator.admin_groups = set({'jupyterhub'})

jupyterhub 서비스 등록

jupyterhub.service 파일 생성

[bluesanta@localhost ~]$ sudo vi /etc/systemd/system/jupyterhub.service
[Unit]
Description=JupyterHub
After=syslog.target network.target

[Service]
Type=simple
PIDFile=/run/jupyter.pid
User=root
WorkingDirectory=/etc/jupyterhub
ExecStart=/usr/local/bin/jupyterhub -f /etc/jupyterhub/jupyterhub_config.py

[Install]
WantedBy=multi-user.target

jupyterhub 서비스 등록

[bluesanta@localhost ~]$ sudo systemctl enable jupyterhub.service 
Created symlink /etc/systemd/system/multi-user.target.wants/jupyterhub.service → /etc/systemd/system/jupyterhub.service.

jupyterhub 서비스 갱신

[bluesanta@localhost ~]$ sudo systemctl daemon-reload

8000 포트 개방

[bluesanta@localhost ~]$ sudo firewall-cmd --permanent --zone=public --add-port=8000/tcp
success
[bluesanta@localhost ~]$ sudo firewall-cmd --reload
success
728x90
728x90

출처

application.properties

#File upload settings
# support multipart uploads (default: true)
spring.servlet.multipart.enabled=true
# Threshold at which files are written to memory (default: 0B)
#spring.servlet.multipart.file-size-threshold=0B 
# Temporary storage space for uploaded files
spring.servlet.multipart.location=d:/usr/local/cnssm/resources
# Maximum size of the file (default: 1MB)
spring.servlet.multipart.max-file-size=10144MB
# Maximum size of request (default: 10MB)
spring.servlet.multipart.max-request-size=10144MB

FileStorageProperties.java

package com.bx.config.property;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties(prefix = "spring.servlet.multipart")
public class FileStorageProperties {

	private String location;

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}
}

FileUploadController.java

package com.bx.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.stream.Collectors;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
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.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.bx.common.util.ExcelUtil;
import com.bx.config.property.FileStorageProperties;
import com.bx.service.FileStorageService;

@Controller
public class FileUploadController {

	@Autowired
	private FileStorageService fileStorageService;

	@Autowired
	private FileStorageProperties fileStorageProperties;

	@RequestMapping(value = "/bx/uploadFile", method = RequestMethod.POST)
	public String uploadFile(@RequestParam("file") MultipartFile file, ModelMap modelMap) {
		String fileName = fileStorageService.storeFile(file);
		modelMap.put("fileName", fileName);
		
		try {
			if (fileName != null && (fileName.endsWith(".xls") || fileName.endsWith(".xlsx"))) {
				FileInputStream fis = new FileInputStream(new File(fileStorageProperties.getLocation() + "/" + fileName));
				Workbook workbook = new XSSFWorkbook(fis);
				
				Sheet sheet = workbook.getSheetAt(0); // 첫 번째 시트 가져오기
				
				// 행 반복 (첫 번째 행부터 마지막 행까지)
				for (Row row : sheet) {
					// 열 반복 (첫 번째 열부터 마지막 열까지)
					for (Cell cell : row) {
						// 셀 값 출력
						System.out.print(ExcelUtil.getCellValue(cell) + "\t");
					}
					System.out.println(); // 행 끝나면 줄바꿈
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return "bx/uploadOk";
	}

	@RequestMapping(value = "/uploadMultipleFiles", method = RequestMethod.POST)
	public String uploadMultipleFiles(@RequestParam("files") MultipartFile[] files, ModelMap modelMap) {
		Arrays.asList(files).stream().map(file -> uploadFile(file, modelMap)).collect(Collectors.toList());

		return "bx/uploadOk";
	}

}

FileStorageService.java

package com.bx.service;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import com.bx.common.exception.FileNotFoundException;
import com.bx.common.exception.FileStorageException;
import com.bx.config.property.FileStorageProperties;

@Service
public class FileStorageService {

	private final Path fileStorageLocation;

	@Autowired
	public FileStorageService(FileStorageProperties fileStorageProperties) {
		this.fileStorageLocation = Paths.get(fileStorageProperties.getLocation()).toAbsolutePath().normalize();

		try {
			Files.createDirectories(this.fileStorageLocation);
		} catch (Exception ex) {
			throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
		}
	}

	public String storeFile(MultipartFile file) {
		// Normalize file name
		String fileName = StringUtils.cleanPath(file.getOriginalFilename());

		try {
			// Check if the file's name contains invalid characters
			if (fileName.contains("..")) {
				throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
			}

			// Copy file to the target location (Replacing existing file with the same name)
			Path targetLocation = this.fileStorageLocation.resolve(fileName);
			Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

			return fileName;
		} catch (IOException ex) {
			throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
		}
	}

	public Resource loadFileAsResource(String fileName) {
		try {
			Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
			Resource resource = new UrlResource(filePath.toUri());
			if (resource.exists()) {
				return resource;
			} else {
				throw new FileNotFoundException("File not found " + fileName);
			}
		} catch (MalformedURLException ex) {
			throw new FileNotFoundException("File not found " + fileName, ex);
		}
	}
}

FileNotFoundException.java

package com.bx.common.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.NOT_FOUND)
public class FileNotFoundException extends RuntimeException {

	private static final long serialVersionUID = 1L;
	
	public FileNotFoundException(String message) {
		super(message);
	}
	
	public FileNotFoundException(String message, Throwable cause) {
		super(message, cause);
	}
}

FileStorageException.java

package com.bx.common.exception;

public class FileStorageException extends RuntimeException {
	
	private static final long serialVersionUID = 1L;

	public FileStorageException(String message) {
		super(message);
	}
	
	public FileStorageException(String message, Throwable cause) {
		super(message, cause);
	}
}

HTML

<form method="post" action="<c:url value="/cnssm/uploadFile"/>" enctype="multipart/form-data">

  <div>
    file : <input type="file" name="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
  </div>
  
  <input type="submit">

</form>
728x90
728x90

구출처

OpenCV 패키지 설치

(venv) D:\workspace.python\cubotino>pip install opencv_python opencv_contrib_python_headless opencv_contrib_python opencv_python_headless numpy==1.26.4

main.py

import cv2

def detect_faces(image_path):
    # 이미지 파일을 로드합니다.
    image = cv2.imread(image_path)

    # 이미지를 회색으로 변환합니다. (얼굴 인식은 흑백 이미지에서 수행되므로)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # 얼굴 인식을 위해 얼굴 검출기를 로드합니다.
    print(f'cv data path = {cv2.data.haarcascades}')
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

    # 이미지에서 얼굴을 검출합니다.
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

    # 검출된 얼굴 주위에 사각형을 그립니다.
    for (x, y, w, h) in faces:
        cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)

    # 결과 이미지를 화면에 출력합니다.
    cv2.imshow('Face Detection', image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 얼굴을 인식할 이미지를 지정합니다.
image_path = 'face.jpg'

# 얼굴 인식 함수를 호출합니다.
detect_faces(image_path)

실행

D:\workspace.python\cubotino\venv\Scripts\python.exe D:\workspace.python\cubotino\main.py 
cv data path = D:\workspace.python\cubotino\venv\Lib\site-packages\cv2\data\

728x90
728x90

[File] > [New Project...] 메뉴 선택

실행 환경 설정

main.py 소스

# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.


def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    print(f'Hi, {name}')  # Press Ctrl+F8 to toggle the breakpoint.


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    print_hi('PyCharm')

# See PyCharm help at https://www.jetbrains.com/help/pycharm/

실행

상단에 Run 버튼 선택

실행 결과

D:\workspace.python\Example1\venv\Scripts\python.exe D:\workspace.python\Example1\main.py 
Hi, PyCharm
728x90
728x90

출처

Entity 객체

Entity 부모 클래스 ( node_modules\typeorm\decorator\entity\Entity.d.ts )

import { EntityOptions } from "../options/EntityOptions";
/**
 * This decorator is used to mark classes that will be an entity (table or document depend on database type).
 * Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it.
 */
export declare function Entity(options?: EntityOptions): ClassDecorator;
/**
 * This decorator is used to mark classes that will be an entity (table or document depend on database type).
 * Database schema will be created for all classes decorated with it, and Repository can be retrieved and used for it.
 */
export declare function Entity(name?: string, options?: EntityOptions): ClassDecorator;

User 클래스 ( entities/user.entity.ts )

import { BaseEntity, Column, Entity, PrimaryGeneratedColumn} from 'typeorm';

@Entity({ name: 'users' })
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number;

  @Column()
  public roleId: number;

  @Column()
  public avatarId: number;

  @Column()
  public nickname: string;

  @Column()
  public email: string;

  @Column()
  public phone: string;

  @Column()
  public phoneWithCountryCode: string;

  @Column()
  public bio: string;

}

Service 클래스 ( user.service.ts )

Controller에서 요청 받은 내용을 Service 객체를 통해서 데이터 저장 및 검색한 결과를 반환

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';

import { User } from './entities/user.entity';

@Injectable()
export class UsersService {

  constructor(
    @InjectRepository(User)
    private readonly _usersRepository: Repository<User>,
  ) { }

  public async detailUser(id: number): Promise<any> {
    const queryBuilder = this._usersRepository.createQueryBuilder('users');
    queryBuilder.where('users.id = :userId', { userId: id });
    const user = await queryBuilder.getOne();
    return user;
  }
}

Controller 클래스 ( user.controller.ts )

Controller는 http 요청을 처리 하고 클라이언트에 응답을 반환하는 하는 클래스

import { Controller, Get, Param } from '@nestjs/common';
import { User } from './entities/user.entity';
import { UsersService } from './user.service';

@Controller()
export class UsersController {
  constructor(
    private readonly _userService: UsersService
  ) { }

  @Get('detail/:id')
  public async findOne(@Param('id') id : number) {
    return this._userService.detailUser(id);
  }

}

Module 클래스 ( user.module.ts )

Module 데코레이터가 붙어있는 클래스로 Nest가 전체 어플리케이션의 구조를 정의한 메타데이터 제공

  • providers : Service 클래스
  • controllers : Controller 클래스
  • imports : 
  • exports : 
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersController } from './user.controller';
import { User } from './entities/user.entity';
import { UsersService } from './user.service';

@Module({
  imports: [ TypeOrmModule.forFeature([ User ]), ],
  controllers: [ UsersController ],
  providers: [ UsersService ],
})
export class UsersModule {
}

메인 Module 클래스 ( app.module.ts )

imports에 UsersModule 추가

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';

import { configValidationSchema } from 'config/validation/config-validation';
import databaseConfig from '../config/database.config';
import { UsersModule } from './v1/users/user.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      cache: true,
      envFilePath: [ '.env.' + process.env.NODE_ENV ],
      ignoreEnvFile: process.env.NODE_ENV === 'prod',
      validationSchema: configValidationSchema,
      load: [ databaseConfig ],
    }),
    TypeOrmModule.forRootAsync({
      imports: [ ConfigModule ],
      useFactory: (configService: ConfigService) =>
          configService.get('database'),
      inject: [ ConfigService ],
    }),
    UsersModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

실행

728x90

+ Recent posts