VSCode에서 나만의 스니펫(Snippets) 설정하기

Server The SOPT·2022년 5월 18일
4
post-thumbnail

✏️ 작성자: 령이
📌 작성자의 한마디: "User Snippets 설정으로 개발 시간 단축하기 삽가능!"

컴퓨터 앞에서 같은 일을 반복하고 있다면 무언가 잘못하고 있는 것이다.

✨ 개인적으로 개발하면서 가장 좋아하는 말입니다 :))

같은 일을 반복하지 않기 위해 만든 컴퓨터로 휴먼이 반복을 하고 있다니..
효율면에서 아주 극악이죠..
컴퓨터 작업에서희 효율개선은 물론 코드의 중복을 제거할 때도 이 말을 되새깁니다.

Duplication Everywhere!!!

근데 생각해보면 우리가 개발을 하면서 어쩔 수 없이 매번 반복하고 있는 일들이 있지 않나요?

내가 익숙한 것, 개발할 때 꼭 필요한 것 등등이 있다보니, 새로운 프로젝트를 시작할 때 늘 똑같은 것(조금씩 업그레이드 되겠지만)을 사용하죠!

비슷한 일을 하는 함수들을 여러개 만들면서 같은 구문을 반복하는 경우도 분명 있습니다.

이 때의 중복을 해결하기 위해서 우리가 택하는 방법은 다음과 같습니다.

  1. 자주 사용하는, 꼭 필요한 package들과 설정을 담은 보일러 플레이트를 만들어둔다.
  2. 함수를 완성하고 중복을 제거하면서 개발한다.

아..그래도 느려.. 조금 더 빠르게 타이핑하고 싶은데..!

이렇게 중복을 제거하고 효율을 높이려고 노력해도, 여전히 발생하는 병목들이 있습니다.
꼭 지켜야하는 컨벤션이 그 중 하나죠!
- 컨벤션을 병목을 칭하는 것이 싫지만, 어쨌든 그렇습니다. 💨

중복 예시 1. 프론트엔드

잠깐 프론트엔드의 이야기를 해보겠습니다.
react에서 컴포넌트를 정의하는 방법에는 다음과 같이 여러가지가 있습니다.

export default function MyComponent() {
	return ();
}

function MyComponent() {
	return ();
}
export default MyComponent;

export default const MyComponent = () => {
	return ();
};

이 중에서 더 익숙한 것을 골라 사용하기도 하고, 팀에서 정한 컨벤션에 따라 맞추기도 하죠!
아주 고맙게도 react에서는 rfc와 같은 명령어를 입력하면 자동으로 해당 컨벤션에 맞춘 초기 세팅을 제공해주고 있습니다!

중복 예시 2. 백엔드

서버 개발자는 어떨까요?
예를 들어, mongoose에서 Schema를 정의하기 위해서는 다음과 같은 구조가 필요합니다.

import mongoose from "mongoose";
import { SoptMemberInfo } from "../interfaces/SoptInfo";

const SoptMemberSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
  },
  isSopt: {
    type: Boolean,
  },
})

export default mongoose.model<SoptMemberInfo & mongoose.Document>("SoptMember", SoptMemberSchema);

또한, controller를 정의할 때에도 다음과 유사한 구조가 필요합니다.

const createUser = async (req: Request, res: Response) => {
  const UserCreateDto: UserCreateDto = req.body;

  try {
    const data: PostBaseResponseDto = await UserService.createUser(UserCreateDto);

    res.status(statusCode.CREATED).send(util.success(statusCode.CREATED, message.CREATED_USER_SUCCESS, data));
  } catch (error) {
    res.status(statusCode.INTERNAL_SERVER_ERROR).send(util.fail(statusCode.INTERNAL_SERVER_ERROR, message.INTERNAL_SERVER_ERROR));
  }
}

여러 개의 스키마, 여러 개의 controller, 여러 개의 service를 정의하다보면 유사한 구조가 매번 반복되는 것을 알 수 있습니다.
대개는 같은 구조를 복붙해서 변수명이나 타입 등을 한 번에 변경하는 식으로 하기도 합니다.
그리고 팀의 컨벤션에 따라 무한히 변형될 수 있죠..!

그래서 매번

  1. 이전에 만든 유사한 파일을 찾아 복사하고
  2. 다시 해당 파일로 돌아와서 붙여넣고
  3. ctrl + d 등을 이용해 변수명을 수정

하는 분들도 계실텐데요.. (그쵸..? 저만 그런거 아니쥬..?) 🥴

파일을 찾아다니는 시간, 변경될 변수명을 찾아 바꾸는 시간..
별 것 아닌 것처럼 보여도 이런 시간들이 생각보다 많은 병목을 유발합니다.
저처럼 타이핑이 느린 사람들은 더욱 잘 아시겠죠...? 개발자라고 모두가 타이핑이 빠른 것은 아니니까요..

그래서 스니펫!

서론이 너무 길었습니다.
그래서 저는 스니펫을 설정해보면서 사용해보고 있는데, 이게 참 마법같은 친구에요!✨


화질이 넘모 깨지네요.... 속상....

스니펫을 잘 설정해두면 내가 지정한 명령어를 입력하면 내가 지정한 코드 컨벤션대로 자동완성을 할 수 있습니다!

스니펫 사용 예시

예를 들어, controller를 만든다고 가정해봅시다!

함수명은 createUser, updateUser로 짓고, 그 안에서 사용되는 dto들은 userCreateDto, userUpdateDto의 이름으로 하고, 타입명도 UserCreateDto, UserUpdateDto로 정해봅시다! 그리고, try {} catch (error) {}를 사용해서 보내질 성공과 실패에서의 형식도 정해봅시다!

다음과 같이 묘~하게 반복되는 코드가 발생할 수 밖에 없겠네요..

const ${controller 함수명} = async (req: Request, res: Response) => {
  const ${dto 변수명}: ${dto 타입} = req.body;
  
  try {
  
    // 성공시 보내질 코드,
    res.status(statusCode.${statusCode}).send();
  } catch (error) {
    // console.log(error);
   	// 500 에러에서 보내질 내용
    res.status(statusCode.INTERNAL_SERVER_ERROR).send(util.fail(statusCode.INTERNAL_SERVER_ERROR, message.INTERNAL_SERVER_ERROR));
  }
};

(지금은 함수 중복에 대해서는 잠깐 무시하겠습니다 :-))

아아- 이정도만 자동완성이 되더라도 너무 좋겠죠!
✨그래서 저는 스니펫을 씁니다!✨

드.디.어. 스니펫 설정법

VSCode의 설정에서 User Snippets를 찾아주세요!
아래 화면은 윈도우 기준입니다.

설정 표시는 윈도우는 좌측 하단, 맥은 좌측 상단에 있습니다 :)
단축키가 있던 것 같은데 확실하지 않으니 pass~

User Snippets를 클릭하면 중앙 상단에 다음과 같은 입력창이 나옵니다.
여기서 내가 스니펫을 적용하고 싶은 파일을 골라주세요!
해당 파일 확장자에서만 작동할 수 있도록 설정할 수 있습니다!

global로 설정하고 싶은 경우에는 New Global Snippets file...을 선택해주세요!

그럼 다음과 같은 화면이 나옵니다.

이곳에 우리의 스니펫을 설정해주시면 됩니다!
사용법은 사실, 주석을 읽으면 쉽게 사용하실 수 있는데, 귀찮으실테니 제가 해석해드릴게요 :) ✌️

스니펫 구조 톺아보기

{
  "스니펫 이름": {
      "prefix - 명령어(alias) 설정": "//express-controller",
      "body - 스니펫 본문": [
          "...",
      ],
    "description - 스니펫 설정": ""
  }
}
  • 스니펫 이름은 여러 스니펫 속에서도 구분할 수 있는 이름이 좋습니다!
  • prefix는 스니펫을 불러올 때 사용할 명령어입니다! 자주 쓰는 단어와 겹치지 않도록 저는 명령어 앞에 //을 붙이는 편입니다.
  • body는 스니펫에 들어갈 내용을 정의합니다. string 배열의 형식으로 한 줄 한 줄을 따옴표로 묶어주시면 됩니다.
  • description은 스니펫을 설명할 때 사용합니다.

스니펫 body 작성하기

body가 가장 중요하니, 한 번 작성해봅시다!
이상의 controller 코드에서 변경될 내용을 제외하고 작성하면 다음과 같이 작성됩니다.

{
  "express controller": {
    "prefix": "//express-controller",
    "body": [
      "const ${1} = async (req: Request, res: Response) => {",
      "  const ${2}: ${3} = req.body;",
      "  ",
      "  try {",
      "  ",
      "    res.status(statusCode.CREATED).send();",
      "  } catch (error) {",
      "    // console.log(error);",
      "    res.status(statusCode.INTERNAL_SERVER_ERROR).send(util.fail(statusCode.INTERNAL_SERVER_ERROR, message.INTERNAL_SERVER_ERROR));",
      "  }",
      "};"
    ]
  }
}

정말 한 줄 한 줄을 모두 작성해주시면 됩니다.

⚠️ 탭이 들어갈 자리는 띄어쓰기로 작성해주셔야합니다!

스니펫 자동완성 후 변경되어야하는 부분에는 ${}을 작성해주시면 되는데, 이상한 번호들이 있죠?
이건 커서가 이동할 path를 지정해주는 것입니다.

📌 커서 이동
자동 완성 후 ${1}에 커서가 자동으로 포커스 됩니다.
그리고 tab을 누르면 ${2}${3}으로 자동 이동합니다.
엄청나죠.. 저는 매번 놀라는 중ㅎ

필요하다면 ${1:placeholder}의 형식으로 placeholder를 지정할 수도 있습니다!

파일 저장 후, 새로운 파일을 만들어 지정한 prefix를 입력하면 자동완성이 ✨짜잔-!✨

이상, 저만 알고 싶은 꿀팁이었습니다 :))

profile
대학생연합 IT벤처창업 동아리 SOPT 30기 SERVER 파트 기술 블로그입니다.

1개의 댓글

comment-user-thumbnail
2022년 5월 31일

좋은 정보네요!! 공유 감사합니다 :)

답글 달기