개요

  • 하나의 파일, 하나의 프로젝트 내에서 함수의 개수가 점점 많아지고 유사한 기능이 점점 많아지다보면, 함수명을 짓는게 힘듦.
  • 특히 상속 받은 함수, 클래스 내 고유한 함수를 구분해주어야 하는 등 속성 측면에서도 함수명을 보다 구체적이고 구분 되도록 지어야 함.
  • 따라서 이번 프로젝트 (hand-pose-detection, face-landmarks-detection, pose-detection) 에서는 함수를 구분하기 위해 ①상속 받은 함수는 부모 클래스와 동일한 함수명 ②static 키워드 ③_함수명 을 가장 많이 사용하였음
  • 이하에서는 위 방법 중 ②, ③ 에 대해 소개함. 

 


 

1. static 

 

정적 메서드와 정적 프로퍼티

 

ko.javascript.info

  • 핵심 코드
static detect(imageData) {
  if (!this._detector) {
      this._createDetector().then(detector => {
          this._detector = detector;
          console.log("model loading success!, detector: ", this._detector);
      })
  }
  //...//
}
  • 의미, 기능
    • 정적 메서드
    • 클래스의 prototype이 아닌 함수 자체에 메서드를 설정 → 양자는 메서드 접근 방법에서 차이가 있음
const HandposeDetector = require('./detector-handpose');

// prototype에 메서드를 설정 : 생성자 호출 -> 메서드 호출  
const handposeDetector = new HandposeDetector();
handposeDetector.detect(imageData);

// 함수 자체에 메서드를 설정 : 클래스명.메서드명으로 메서드 호출
HandposeDetector.detect(imageData);
  • HandposeDetector.detect(imageData) 이 코드 같은 메서드 접근 방법에서도 알 수 있듯, 정적 메서드는 프로퍼티 형태로 직접 할당하는 것처럼 메서드를 정의
    (마치 프로퍼티에 접근하는 것처럼 메서드를 호출)
  • 정적 메서드도 상속됨. 따라서 자식클래스명.함수명 형태로 호출 가능
  • 사용 이유 : 데이터를 클래스 수준에 저장하고 싶을 때
    • 프로젝트에 적용
    • HandposeDetector, FaceDetector, PoseDetector 같은 커스텀 detector를 만들 때, Detector 클래스를 상속 받아 만들었음
    • 그래서 상속 받은 함수와 커스텀 detector 만의 함수를 구분 지을 필요 有, 따라서 초기에 static으로 구분
  • 정적 프로퍼티도 static 프로퍼티 정의 형태로 사용하면 됨

 


 

2. _함수명

  • 예시 코드
_createDetector() {
  const model = SupportedModels.MediaPipeHands;
  const detector = createDetector(model, {
      runtime: "tfjs",
      modelType: "lite",
      maxHands: 2, // or 2~10.
      flipHorizontal: false,
      staticImageMode: false,
      detectorModelUrl:
          "/static/tensorflow-models/tfjs-model_handpose_3d_detector_lite_1/model.json",
      landmarkModelUrl:
          "/static/tensorflow-models/tfjs-model_handpose_3d_landmark_lite_1/model.json",
  });
  return detector;
}
  • HandposeDetector, FaceDetector, PoseDetector 같은 커스텀 detector를 만들 때, Detector 클래스를 상속 받아 만들었음
  • 그래서 상속 받은 함수와 커스텀 detector 만의 함수를 구분 지을 필요 有
  • 코딩 초기 당시 static 키워드를 활용하여 구분하였음. 그러나 이 방법은 중간 중간 해당 함수 호출할 때, 클래스명.함수명 으로 호출해야하여 번거롭다는 단점
  • 따라서 사수께서 추천해주신 방법은 _함수명() 임. 위처럼 함수를 정의하고 호출할 때는 this._createDetector() 로 호출하면 됨

개요

  • 이번 프로젝트에서는 ①클래스를 상속 받아 기능 확장하여, ②Tensorflow-models 모델의 전형적인 구조에 따라 핵심 코드를 작성하였음
  • 상속 
    • 의미 : 부모 클래스의 프로퍼티, 메서드를 자식 클래스가 물려받는 것
    • 기능 : 부모 클래스 기능을 자식 클래스에서 확장시킬 수 있음.
    • ES6 모듈 개발 전 : 프로토타입 체인 방식으로 상속, 그러나 이는 가독성 떨어짐.
    • ES6 모듈 개발 후 : Class + extends 키워드를 사용하여 상속, 상속하는 것 확실히 티 낼 수 있게 됨
  • 이번 프로젝트에서의 상속
    • Detector 클래스
class Detector {
  constructor () { }

// 그 외 내용: 자바스크립트에서의 getter and setter
// https://ko.javascript.info/property-accessors
  static get DIMENSIONS () {  // 
      return [480, 360];
  }
  enable () {
      this._enable = true;
  }
  disable () {
      this._enable = false;
      this._result = null;
  }
  detect (imageData) { }
  isExistContent (result) {
      return result && result.length > 0;
  }
  draw (canvas) { }
}
module.exports = Detector;

 

  • HandposeDetector 클래스
class HandposeDetector extends Detector {
  constructor() {
      super();
      this._result;
  }

  enable() {
      super.enable();
      this._canvas = document.createElement("canvas");
      this._canvas.width = Detector.DIMENSIONS[0];
      this._canvas.height = Detector.DIMENSIONS[1];
      this._context = this._canvas.getContext("2d");
  }

  disable() {
      super.disable();
      delete this._context;
      delete this._canvas;
      this._context = null;
      this._canvas = null;
  }

  _createDetector() {
      const model = SupportedModels.MediaPipeHands;
      const detector = createDetector(model, {
          runtime: "tfjs",
          modelType: "lite",
          maxHands: 2, // or 2~10.
          flipHorizontal: false,
          staticImageMode: false,
          detectorModelUrl:
              "/static/tensorflow-models/tfjs-model_handpose_3d_detector_lite_1/model.json",
          landmarkModelUrl:
              "/static/tensorflow-models/tfjs-model_handpose_3d_landmark_lite_1/model.json",
      });

      console.log("model loading success!, detector: ", this._detector);
      return detector;
  }
  
  detect(imageData) {
      if (!this._detector) {
          this._createDetector().then(detector => {
              this._detector = detector;
              console.log("model loading success!, detector: ", this._detector);
          })
      }

      return new Promise((resolve, reject) => {   
          this._detector.estimateHands(imageData).then(result => {
              this._result = result;
              console.log(`this._result: `, this._result);

              this._result.forEach((res) => {
                  console.log(`${res.handedness} hand keypoints:`);
                  res.keypoints.forEach((keypoint, i) => {
                      let x = keypoint.x - 320;
                      let y = keypoint.y - 240;
                      console.log(`Keypoint ${i}: [${x}, ${y}]`);
                  })
              })
              resolve(this._result);
          }).catch(e => {
              reject(e);
          });
      })
  }
/**
중략
**/
}
module.exports = HandposeDetector;

 


 

개념 정리

출처 : https://ko.javascript.info/class-inheritance

1. class와 prototype

  • 부모 클래스 Animal과 객체 animal
class Animal {
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
  run(speed) {
    this.speed = speed;
    alert(`${this.name} 은/는 속도 ${this.speed}로 달립니다.`);
  }
  stop() {
    this.speed = 0;
    alert(`${this.name} 이/가 멈췄습니다.`);
  }
}

let animal = new Animal("동물");
  • 객체 animal과 클래스 Animal의 관계

  • Animal vs Animal.prototype
    Animal : Class Definition Animal.prototype : Prototype-Based Definition
    class 키워드로 정의한 클래스 객체의 프로토타입을 확장하여 메서드와 속성을 추가한 것
    ES6 이후 문법 ES6 이전 문법
    클래스 = 메서드(run, stop) + 속성(speed, name)  
    클래스는 생성자(constructor)를 가질 수 있음  
    • constructor
      • 함수 자신, 따라서 위 그림에서 constructor : Animal 로 표시됨
        (∵ 자바스크립트에서 클래스⊂함수, 클래스는 생성자 함수로써 내부적으로 생성자 함수와 프로토타입을 생성하기 때문)
      • 만약 Animal 함수의 프로퍼티 ‘prototype’에 constructor 객체 하나만 있다면 ‘디폴트 프로퍼티가 있다’고 표현 가능
        (디폴트 프로퍼티 : 개발자가 별도로 할당하지 않아도 기본적으로 가지는 프로퍼티)
      • 기능적으로 클래스에서 객체를 생성하고 초기화하기 위해 사용하는 메서드라고 볼 수 있음. 클래스를 통해 새로운 객체를 생성할 때 자동 호출됨

 


 

2. extends키워드로 상속 받기

  • 자식 클래스 Rabbit
class Rabbit extends Animal {
  hide() {
    alert(`${this.name} 이/가 숨었습니다!`);
  }
}

let rabbit = new Rabbit("흰 토끼");

rabbit.run(5); // 흰 토끼 은/는 속도 5로 달립니다.
rabbit.hide(); // 흰 토끼 이/가 숨었습니다!
  • 클래스 Rabbit을 이용하여 만든 객체 rabbit
    : rabbit은 rabbit.hide() 로 Rabbit 클래스의 메서드에도, rabbit.run() 으로 Animal의 메서드에도 접근 가능
  • extends는 프로토타입을 기반으로 동작
    • 따라서 extends는 Rabbit.prototype.[[Prototype]]Animal.prototype으로 설정함
    • Rabbit.prototype에서 메서드를 찾지 못하면 Animal.prototype에서 메서드를 가져옴

 

  • 프로젝트에 적용
class HandposeDetector extends Detector { }

 


 

3. 메서드 오버라이딩(Method Overriding) : super 키워드 활용

  • 의미 : 부모 클래스의 메서드재정의하여 자식 클래스에서 사용하는 것
    → 재정의 : 일부 기능만 변경 or 기능 확장
  • super 키워드 활용
    • super(…) : 부모 생성자 자체 호출, 따라서 자식 생성자 내부에서만 사용 가능
    • super.method명(…) : 부모 클래스의 method를 호출
  • 핵심 코드 : 부모 클래스의 stop() method를 오버라이딩한 rabbit.stop() 정의
class Rabbit extends Animal {
  hide() {
    alert(`${this.name}가 숨었습니다!`);
  }

  stop() {
    super.stop(); // 부모 클래스의 stop을 호출해 멈추고,
    this.hide(); // 숨습니다.
  }
}

let rabbit = new Rabbit("흰 토끼");
rabbit.run(5); // 흰 토끼가 속도 5로 달립니다.
rabbit.stop(); // 흰 토끼가 멈췄습니다. 흰 토끼가 숨었습니다!
  • 프로젝트에 적용
enable() {
      super.enable();
      this._canvas = document.createElement("canvas");
      this._canvas.width = Detector.DIMENSIONS[0];
      this._canvas.height = Detector.DIMENSIONS[1];
      this._context = this._canvas.getContext("2d");
  }

 


 

4. 생성자 오버라이딩(Constructor Overriding)

  • 의미 : 부모 클래스의 생성자재정의하여 자식 클래스에서 사용하는 것
  • super 키워드 활용
    • super 키워드가 상속 클래스의 생성자 함수가 실행되면, 부모 클래스의 생성자가 ①빈 객체를 만들고 ②this에 이 객체가 할당되도록 함
    • 따라서 super 키워드가 없으면 this가 될 객체가 생성되지 않아 자식 클래스 생성자 실행 시 오류 발생함
  • 핵심 코드
class Rabbit extends Animal {
  constructor(name, earLength) {
		super(name);
    this.earLength = earLength;
  }
  // ...
}
  • 프로젝트에 적용
class HandposeDetector extends Detector {
  constructor() {
      super();
      this._result;
  }
}

 


 

배운점 (요약)

  • 이번 프로젝트에서는 ①클래스를 상속 받아 기능 확장하여, ② Tensorflow-models 모델의 전형적인 구조 에 따라 핵심 코드를 작성하였음
  • 실제 코드를 작성할 때는 정확히 무슨 뜻인지 모르고, 용례를 보고 이런 느낌이구나 라고 생각하며 사용했음
  • 그러나 프로젝트를 마무리하며 개념 정리를 하니, 밑그림만 있던 것이 구체적인 채색까지 되는 느낌이었음. 따라서 향후 활용할 수 있는 자신감이 생겼음. 또한 효율적, 효과적인 코드를 위해 상속 및 오버라이딩은 필수 요소라고 생각했음.

유용한 것 발견할 때마다 지속적으로 업데이트 할 예정!!

 


 

단축키

 

1. Ctrl+Shift+L  동일한 명칭 갖고 있는 코드 수정 가능

2. Ctrl+N  파일 탐색기 새 창으로 열기

 


 

확장 앱 

 

1. Git graph  깃 로그 관리하기 좋음. 현재 커밋 푸시 스태쉬 상태 모두 확인 가능 

2. File path  하단에 파일 경로 표시됨. 작업하다 순간 이게 어디 있는거지 하고 멍 때릴 때 정신 차리기 좋음

 

 

 

 

'Backend > Enviornment setting | Git' 카테고리의 다른 글

[Git] commit과 push  (0) 2023.11.30
[Git] git stash  (0) 2023.11.29
[Setting] Windows에서의 Symbolic Link 생성, 삭제  (0) 2023.10.31

npm link 에 대한 개념은 이전 글에서 정리하여 생략하였습니다!

2023.10.17 - [Backend/Etc : Setting | Git] - [Setting] 내부 서버로부터 파일 clone | npm link | build

 


 

문제 인식

  • 1번째 작업 : GUI의 develop 브랜치(root)와 VM의 feature/tfjs-handpose 브랜치에서는 빌드 성공 + 내가 작성한 코드가 반영 잘 됨
  • 그러나 2번째 작업 : face-detection을 적용하기 위한 feature/tfjs-face 브랜치에서 작업 후, 다시 feature/tfjs-handpose로 돌아와 빌드하면 빌드 실패
  • 오류 내용
node:internal/modules/cjs/loader:1084 Uncaught Error: Cannot find module '@mediapipe/hands'
Require stack:
C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\hand-pose-detection\dist\mediapipe\detector.js
C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\hand-pose-detection\dist\create_detector.js
C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\hand-pose-detection\dist\index.js
C:\Workspace\AI\Handpose\ai_roborobo\index.html at node:internal/modules/cjs/loader:1084:15 at Function._resolveFilename (node:electron/js2c/renderer_init:2:5527) at node:internal/modules/cjs/loader:929:27 at Function.<anonymous> (node:electron/js2c/asar_bundle:2:13327) at Function._load (node:electron/js2c/renderer_init:2:4757) at Module.require (node:internal/modules/cjs/loader:1150:19) at require (node:internal/modules/cjs/helpers:121:18) at Object.<anonymous> (C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\face-detection\dist\mediapipe\detector.js:56:21) at Object.<anonymous> (C:\Workspace\AI\Handpose\ai_roborobo\node_modules@tensorflow-models\face-detection\dist\mediapipe\detector.js:210:3) at Module._compile (node:internal/modules/cjs/loader:1271:14)
  • GUI에서 최종 빌드를 진행하기 때문에, 위 오류는 결국 GUI에서 @mediapipe/hands 모듈을 인식하지 못한다는 소리가 됨
  • GUI는 ①node_modules/@tensorflow-models 에서 hand-pose-detection 모델을 인식하고, ②node_modules/scratch-vm/~ 에서 VM과 관련된 코드를 인식함. 이 때 둘은 npm link로 이어져 있음
  • 그러나 나는 VM에 @mediapipe/hands 모듈을 설치해놓은 상태였음에도 GUI가 인식하지 못함
  • 따라서 npm link의 문제라고 생각함

 


 

1. npm link 의미(용도)

  • Symbolic link ( 줄여서 Symlink) = 바로가기 파일
  • GUI에서 npm link VM 을 실행하면, 외부 모듈(VM)이 현재 프로젝트(GUI)의 node_modules 디렉토리에 설치된 것처럼(npm install한 것처럼) 사용될 수 있게 해줌
  • 즉 해당 모듈(GUI)에 VM에 대한 전역 심볼릭 링크를 설정하는 것

 


 

2. npm link 사용법

  • 위 오류 해결 방법 후보
    1. 프로젝트 변경될 때마다 (VM에 브랜치 생성할 때마다), GUI의 develop 브랜치에 npm link
    2. 프로젝트 변경될 때마다 (VM에 브랜치 생성할 때마다), GUI에 브랜치 생성하여 npm link
  • 내 생각 1: GUI root 디렉토리를 계속 건드리는게 좋지 않아 보임, 따라서 후보2를 실행해보려고 함
  • 그러나 npm link는 브랜치 단위가 아닌 프로젝트 단위(디렉토리 단위)로 생성
    • 따라서 후보2를 실행해도 브랜치별로 다른 npm link가 걸리는 것이 아니라, 설정된 npm link가 계속 변경됨
    • 따라서 후보1 실행하기로 함
  • 핵심 코드
// blocks
npm link l10n

// l10n
npm link l10n

// VM
npm link l10n blocks --force  // peer dependency conflict 방지

// GUI
npm link l10n blocks VM
  • npm link를 프로젝트가 작은 것 → 큰 것 순서로 진행하는 느낌
  • --force 또는 --legacy-peer-deps 는 peer dependency conflict 를 방지하기 위해 실행 

 


 

해결법

프로젝트 변경될 때마다 (VM에 브랜치 생성할 때마다), GUI의 develop 브랜치에 npm link 하고 build

문제 인식

  • 나는 지금까지 항상 git commit -m “커밋 메시지”git push origin 브랜치명 을 모두 실행하여 내 코드를 공유했었음
  • 그래서 commit과 push의 의미를 구별하지 못 함, 왜 2가지 단어가 있는지 의문이었음. 따라서 나는 항상 ‘push 했다’ 라고 표현해왔음
  • 그러나 내가 하나의 프로젝트 작업을 완료하자, 사수께서 서버에 올려 달라고 하심
  • 나는 지금까지 commit, push만 있는줄 알았는데 또 무엇인가 해야 하나 고심하였음. 그러나 알고보니 작업한 코드를 서버에 올리는 것 = push 라는 것이었음
  • 따라서 양자의 차이를 알게 됨

 


 

1. commit과 push 의 차이점

  Commit  Push
명령어 git commit -m “커밋 메시지” git push origin 브랜치명
의미 로컬 저장소에 저장 원격 저장소에 저장 → 원격 저장소는 서버, 깃헙 등을 말함
과정 내가 작업하다가 끊고 싶을 때 마음대로 커밋하면 됨 PM의 허락 받고 푸시해야 함
Staging → Commit Staging → Commit → Push
   
브랜치 삭제로 알아보는 차이 git branch -d 브랜치명 git branch -D 브랜치명 (수정된 파일이 커밋되지 않아도 삭제) git push origin -d 브랜치명
  • origin : 저장소 명; 따라서 각 프로젝트에서 설정한 서버 저장소 명으로 origin 대신 설정 가능. 그러나 대부분 origin으로 설정되어 있음

문제 인식

      • 기능별로 브랜치를 만들어서 작업해야 한다고 하심 ( ex. handpose / face / pose | 각 경우에서 구체적으로 model / detect / draw )
        • 공통 사용할 npm 모듈 설치하여 feature/tfjs → 그 브랜치에서 feature/tfjs-handpose, feature/tfjs-face, feature/tfjs-pose로 뻗어나가기

브랜치 예시

  • 그러나 이미 작업 중인 파일이 있다면, 브랜치 생성하여 checkout 해도 계속 수정된 파일이 남아있다는 문제 + commit은 부담스러움
  • git stash를 사용하면 됨!

 


의미 (용도)

 

  • 임시 저장소
  • commit은 부담스럽고 checkout 해서 다른 브랜치에서 새로 작업하고 싶을 때, stash라는 임시 저장소에 저장하였다가 불러와서 사용하면 됨

 

사용법

  • stash 생성(임시 저장) : git stash (save)
    • save 적어도 되고 안 적어도 됨
    • 위 명령어 사용하여 stash 생성하고, 작업할 브랜치로 checkout 하면 됨
    • Node.js의 경우 package.json (내가 설치, 삭제한 npm 모듈 기록)까지 임시 저장됨
  • stash 저장 목록 확인 : git stash list
    • 임시 저장한 파일을 현재 내가 있는 브랜치로 불러오는 것임
    • stash 이름을 생략하면 가장 최근에 저장된 stash가 나옴 → LIFO: 후입선출, 스택의 자료 구조
  • stash 삭제: git stash drop (@stash{0})
    • stash 이름을 생략하면 가장 최근에 저장된 stash가 삭제됨

개요

심볼릭 링크에 대해서는 '파이썬 2개 버전 동시 사용하기' 글에서 이미 다루었다. 해당 글을 작성하고 최근까지도 나는 이 경우에만 심볼릭 링크를 사용하는 줄 알았다. 그러나 자사 제품의 로컬 실행을 위해 빌드하며 다른 메시지의 오류 2개를 심볼릭 링크로 해결해보며, 이것이 다양한 경우에서 사용될 수 있음을 깨달았다. 요약하자면 심볼릭 링크는 파일 A와 B가 멀리 떨어진 위치에 있을 때, A 파일을 실행하며 종속적으로 B 파일 실행이 필요한 경우 A에 B 파일의 위치를 알려주는 느낌이다.

 


 

Windows에서의 Symbolic Link

Symbolic Link 란?
  • 링크를 연결하여 원본 파일을 직접 사용하는 것과 같은 효과를 내는 링크이다.
  • 윈도우의 바로가기와 비슷한 개념이다.
  • 특정 폴더에 링크를 걸어 NAS, library 원본 파일을 사용하기 위해 심볼릭 링크를 사용한다.
  • 소프트 링크라고도 한다.
  • 리눅스 용어이지만 자사에서는 윈도우로 개발하는 바, 이하에서는 윈도우 명령어와 오류로 설명한다. 

 

명령어 및 결과

1. 링크 생성

  • 파일에 대한 링크 생성 : mklink 생성파일 실행파일 
mklink C:\Workspace\Rogic\scratch-blocks\python.exe C:\Python27\python.exe
// cmd 결과
C:\Workspace\Rogic\scratch-blocks\python.exe <<===>> C:\Python27\python.exe에 대한 기호화된 링크를 만들었습니다.
// 파일탐색기 결과
심볼릭링크 유형으로 실행파일.exe가 추가됨

 

  • 디렉토리에 대한 링크 생성 : mklink 생성디렉토리 실행디렉토리
    -> 파일에서 디렉토리로만 변경되고, 로직 및 결과는 동일하게 확인 가능하다.

 

2. 링크 삭제 

  • 파일에 대한 링크 삭제 
    • cmd 창을 이용 : (생성파일이 있는 디렉토리로 이동하여) del 생성파일
    • 파일탐색기 이용 : 위 사진에 있는 심볼릭 링크 파일 삭제
  • 디렉토리에 대한 링크 삭제
    • cmd 창을 이용 : (생성 디렉토리로 이동하여) rmdir 생성디렉토리 
    • 파일탐색기 이용 : 상동

 


 

Trouble Shooting

오류 내용
  • scratch-blocks에서 npm run prepublish 실행 시 아래 오류 발생 
// 파이썬에서 site-packages를 찾을 수 없는 오류
ImportError: No module named site

// 자바가 path에 없다는 오류
Could not find "java" in your PATH.
Using remote compiler: closure-compiler.appspot.com ...

Error: Closure not found.

 

오류 원인(내 생각)
  • 파이썬의 경우 2개 버전을 함께 사용하므로 설치한 후부터 지금까지 경로가 꼬였을 수 있겠다고 생각했다. 따라서 완전 삭제 후 재설치하고 오류를 해결하기로 했다.
  • 그러나 재설치해도 위 오류는 동일하게 발생했다. 따라서 scratch-blocks에서 실행되는 파이썬(ver 2.7.18)에게 site-packages를 찾을 수 있도록 알려주어야 겠다고 생각했다. 
  • 자바의 경우에도 고급 시스템 설정-환경변수-Path에 올바른 경로를 추가해도 위와 같은 오류가 발생했다. 따라서 scratch-blocks에서 실행되는 자바가 어디 있는지 알려주어야 겠다고 생각했다. 
  • 즉 위의 두 문제 모두 메시지는 다르지만 '알려준다' 라는 요점이 같고, 이것이 곧 심볼릭 링크라고 생각했다!

 

해결 
// 파이썬은 두 버전의 명령어를 구분하여 심볼릭 링크 만들기
mklink C:\Workspace\Rogic\scratch-blocks\python.exe C:\Python27\python.exe  // 빌드 명령어 : python
C:\Workspace\Rogic\scratch-blocks\python.exe <<===>> C:\Python27\python.exe에 대한 기호화된 링크를 만들었습니다.

mklink C:\Workspace\Rogic\scratch-blocks\py.exe C:\Users\KHR\AppData\Local\Programs\Python\Python312\python.exe  // ai 개발 명령어 : py
C:\Workspace\Rogic\scratch-blocks\py.exe <<===>> C:\Users\KHR\AppData\Local\Programs\Python\Python312\python.exe에 대한 기호화된 링크를 만들었습니다.


// 자바
mklink "C:\Workspace\Rogic\scratch-blocks\java.exe" "C:\Program Files (x86)\Java\jre-1.8\bin\java.exe"
C:\Workspace\Rogic\scratch-blocks\java.exe <<===>> C:\Program Files (x86)\Java\jre-1.8\bin\java.exe에 대한 기호화된 링크를 만들었습니다.
  • 주의할 점
    • 빌드하는 디렉토리 위치에서 심볼릭링크를 생성해야한다! 처음 cmd 창을 열었을 때 설정 되어있는 기본 디렉토리에서 링크 생성해봤자 소용 없다!
    • cmd 창을 관리자 권한으로 열어야한다! 관리자 권한으로 열지 않으면 명령어가 권한이 없어 작동하지 않는다!

 


 

참고 자료

https://bluedrim.tistory.com/entry/%EC%9C%88%EB%8F%847-%EC%8B%AC%EB%B3%BC%EB%A6%AD-%EB%A7%81%ED%81%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B0%8F-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0

 

윈도7 심볼릭 링크 만들기 및 삭제하기

윈도7 심볼릭 링크 만들기 및 삭제하는 방법, 심볼릭 링크라고도 하고 소프트 링크라고도 함 먼저 command 창을 관리자 권한으로 실행시키는 것이 필요. 보조프로그램에서 "명령 프롬프트"를 마우

bluedrim.tistory.com

231031 7번째 완료

 

'Backend > Enviornment setting | Git' 카테고리의 다른 글

[Setting] Visual Studio Code 위주 유용한 단축키 + 확장 앱  (0) 2023.11.30
[Git] commit과 push  (0) 2023.11.30
[Git] git stash  (0) 2023.11.29

개요

어제 회사에서 향후 주어질 업무에 대해 차장님과 논의했다. 아마 나는 자사 제품 기능을 Node.js 로 일부 개발 + AI 개발하게 될 것 같다. 일단 너무 좋았다! 백엔드 + AI 조합 ㅎㅎ 그래서 본격적인 업무 시작 전 pc 환경설정을 하는 과정에서 다른 팀원 분들과 Node.js, npm 버전을 맞추어야 했고, 목표 버전은 Node.js는 v16.20.0, npm은 9.6.4이다. 이 때 npm은 Node Package Manager의 약자로 자바스크립트 코드 언어를 위한 노드 패키지를 관리해 주는 툴이다. 

 


 

1. Node.js : cmd를 이용하여 업데이트 하는 방법

npm을 이용
  • n 패키지를 이용한다. 구체적인 코드는 다음과 같다. 
npm install -g n  //global로 설치해 주어야 Node Vesion을 root에서 관리할 수 있다.

n stable  // 안정 버전 설치
n latest  //  최신 버전 설치
n lts  // lts 버전 설치
n x.x.x  // 특정 버전 설치 ( x.x.x 버전 )
n prune  // 이전 버전들 삭제해 주는 명령어

 

nvm( Node Vesion Manager )을 이용
  • nvm 자체를 이용한다. 구체적인 코드는 다음과 같다. 
nvm install [ version ]  // 특정 버전 설치
nvm install node           // 최신 버전 설치
nvm uninstall [ version ]  // 이전 버전을 삭제하는 명령어
nvm alias default [version]  // 여러 버전을 설치하고 필요한 환경으로 지정해 주는 명령어

 


 

2. npm : cmd를 이용하여 업데이트 하는 방법

위에서 Node.js 버전 업데이트가 npm을 이용하는 것이 있어서 사실 나는 npm 버전부터 업데이트 하려고 했다. 구체적인 코드는 다음과 같다.

npm install -g npm@9.6.4   // 특정 버전 설치 ( x.x.x 버전 )
npm install -g npm@latest  // 최신 버전 설치

 

꼬리 문제 

npm이 정상적으로 업데이트 되지 않았다. 검색하고, 생각해봐도 합리적인 원인을 찾기 어려웠다. 그 때 차장님께서 그냥 공식홈페이지 가서 설치하는 것이 빠르다고 조언을 해주셨다...ㅋㅋㅋㅋㅋㅋ 그래서 공홈 가서 릴리즈된 버전을 살펴보니 내가 설치하려 했던 npm 버전이 현재 내 Node.js 버전과 맞지 않았고, 그래서 설치가 되지 않았던 것이었다. 따라서 Node.js는 16.20.2 로 바꿔서 , npm은 9.6.4로 그대로 설치하기로 했다.  

 


 

3. 공식 홈페이지를 통한 업데이트

Node.js 공식 홈페이지로 들어가 OS와 버전을 확인하고 다운로드 받으면 된다. 다만, Node.js 를 설치하면 그에 맞는 npm이 자동 설치되므로 나중에 cmd로 npm 버전을 업데이트 해주어야 한다. 

 


 

4. 업데이트 후 버전 확인

버전 확인 결과

 


 

참고 자료

https://aiday.tistory.com/63

2023.10.18 3번째 완료

 

+ Recent posts