---
title: Back4App으로 풀스택 웹 애플리케이션 생성 및 호스팅 가이드
slug: docs-kr/advanced-guides/web-application-hosting
description: Back4App을 이용한 프론트엔드 및 백엔드 웹 애플리케이션 호스팅 가이드.
image: https://www.back4app.com/_public/img/back4app-og.png
createdAt: 2024-01-26T13:45:06.946Z
---

# 풀스택 웹 애플리케이션 만들기 및 호스팅

## 소개

풀스택 애플리케이션을 시작하는 것은 벅찰 수 있습니다. 프론트 엔드를 호스팅하고, 서버를 구성/제공하며, 모든 것을 연결하는 것에 대해 걱정해야 합니다. 당신은 몰랐을 수도 있지만, Back4App은 위의 모든 것에 최적의 인프라를 제공합니다.

Back4App의 웹 호스팅을 사용하면 프론트엔드 HTML(React 및 Vue와 같은 프론트엔드 프레임워크 포함)을 쉽게 제공할 수 있습니다. 클라우드 코드는 빠르게 시작되는 훌륭한 백엔드를 만듭니다. 이 가이드에서는 Back4App에서 완전한, 비록 기본적인, 웹 애플리케이션을 구축할 것입니다.

이것은 [John Considine](https://github.com/considine)이 작성한 게스트 튜토리얼입니다. 그는 [K-Optional](https://koptional.com/)의 수석 개발자입니다.

## 목표

Back4App에서 풀스택 웹 애플리케이션 시작하기

## 전제 조건

:::hint{type="info"}
이 튜토리얼을 완료하려면 다음이 필요합니다:



- 명령줄에 익숙해야 합니다.
- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) 및 [NPM](https://docs.npmjs.com/getting-started)이 설치되어 있어야 합니다.
- Back4App 계정이 있어야 하며, CLI 도구가 설치되고 구성되어 있어야 합니다. 도움말은 [여기에서 확인하세요.](https://blog.back4app.com/cli-parse-server/)
- Back4App 대시보드에서 새 프로젝트를 생성해야 합니다. 도움말은 [여기에서 확인하세요.](https://www.back4app.com/docs/get-started/new-parse-app).
- 이 튜토리얼은 Parse Server 버전 3.1.x로 설정되어야 합니다. 자세한 내용은 아래를 참조하세요.
:::

:::hint{type="danger"}
이 프로젝트는 새로 출시된 3.1 버전의 Parse Server를 사용할 것입니다. 이는 Back4App 프로젝트가 이 릴리스로 설정되어 있어야 함을 의미합니다. 그렇지 않으면 작동하지 않습니다. 프로젝트 대시보드에서 서버 설정 » Parse Server 관리(설정)로 이동하여 3.1.1을 선택하세요(베타일 수 있습니다).
Parse Server 3.1.x로 마이그레이션에 대한 자세한 정보는 [이 가이드를 참조하세요.](https://www.back4app.com/docs/advanced-guides/parse-server-3).
이 프로젝트의 클라우드 코드 구문을 이해하지 못하는 경우 이 가이드를 참조하세요.
:::

## 프로젝트 배경

우리는 기본적인 티켓 교환 애플리케이션을 출시할 것입니다. 이 애플리케이션은 사용자가 가입하고 로그인하며, 관리자가 대시보드를 사용하여 생성할 수 있는 다양한 이벤트에 대해 판매하는 티켓을 게시할 수 있도록 합니다. 다른 사용자는 게시자가 표시하기로 선택한 이메일 또는 전화번호를 통해 그들과 연락할 수 있습니다.

나는 이 앱을 출시했습니다 [여기](http://ticketlister.koptional.com/), 이 가이드에서 탐색하는 동일한 코드를 사용하여. 계정을 만들고, 티켓을 게시하고, 앱이 어떻게 생겼는지 확인하는 것은 자유입니다.

이 튜토리얼의 목적은 애플리케이션을 효율적으로 출시하는 방법을 보여주는 것입니다. 따라서 각 코드 줄에 대해 깊이 파고들기보다는 대부분 완료된 코드베이스로 시작하여 배포의 용이성에 집중할 것입니다. 코드를 편집해야 하는 곳은 단 하나입니다:

- 1단계에서는 프로젝트 설정(애플리케이션 ID, JavaScript 키 및 서버 URL)을 추가해야 합니다.

하지만 이 애플리케이션을 원하는 대로 수정하고 확장하는 것은 환영합니다.

## 프로젝트 구조

코드를 준비하기 시작하기 전에 이 프로젝트의 파일 구조를 이해하는 것이 중요합니다. 이 가이드 전반에 걸쳐 이를 참조로 사용할 것입니다. 모든 것이 완료되면 디렉토리는 다음과 같이 보일 것입니다:

:::BlockQuote
1   project
2   │   .parse.local
3   │   .parse.project
4   │   .gitignore
5   │   README.md
6   └───public
7   │   │   index.html
8   │   │   login.html
9   │   │   signup.html
10  │   └───css
11  │       │   signin.css
12  │       │   bootstrap.min.css
13  │   └───js
14  │       │   main.js
15  │       │   parse.js
16  │       │   signin.js
17  │       │   signup.js
18  │
19  └───cloud
20      │   main.js
:::

이 설정에서 주요 요점은 다음과 같습니다:

1. 프론트엔드 코드는 **public** 디렉토리에 있습니다. 프론트엔드는 최종 사용자가 상호작용하는 애플리케이션의 부분입니다.
2. 백엔드 코드는 **cloud** 디렉토리에 있습니다. 백엔드는 애플리케이션에서 비하인드 씬 작업을 수행합니다. 여기에는 데이터베이스에 항목을 저장하고 데이터를 전송하는 것이 포함됩니다.

*프론트엔드는 HTTP 요청을 보내 백엔드에 무엇을 해야 하는지 알려줍니다. 우리의 경우, 이는 클라우드 기능을 실행하는 것을 의미합니다.*

:::hint{type="info"}
**이 설정의 간단함도 주목해 주세요. 세 개의 HTML 파일이 이 애플리케이션의 세 개의 페이지를 나타냅니다. 우리의 전체 백엔드는 단일 파일입니다!**
:::

2단계에서는 프론트엔드 코드, 즉 공개 디렉토리를 간단히 살펴보겠습니다. 3단계에서는 백엔드로 이동합니다.

## 1 - 파일 준비하기

**앞서 언급한 바와 같이, [필수 조건](https://www.back4app.com/docs/advanced-guides/web-application-hosting#prerequisites), Back4App에 새 프로젝트를 생성하고 [CLI 도구를 구성해야 합니다](https://blog.back4app.com/2017/01/20/cli-parse-server/)**

코드를 방문하기 전에 다운로드하여 준비해야 합니다. 이 단계에서는 바로 그 작업을 수행합니다. 명령줄에서 여러 명령을 실행해야 한다는 점에 유의하세요. 각 명령을 복사하여 실행할 수 있도록 제공하겠습니다. 이 단계에서 혼란스러우면 걱정하지 마세요; 이는 Back4App 앱을 Git에 있는 프로젝트에 연결하기 위해 필요한 과정일 뿐입니다. 무슨 일이 일어나고 있는지 아는 것은 중요하지 않습니다.

이 단계에서 우리는:

1. CLI를 사용하여 Back4App 프로젝트로 로컬 디렉토리를 초기화합니다.
2. .git을 사용하여 이 디렉토리로 예제 프로젝트 파일을 가져옵니다.

**Back4App으로 초기화**

명령줄에서 다음을 실행합니다.

:::BlockQuote
1 b4a new
:::

다음과 같은 메시지가 표시됩니다:

:::BlockQuote
1   새 앱을 만들거나 기존 앱에 Cloud Code를 추가하시겠습니까?
2   "(n)ew" 또는 "(e)xisting"을 입력하세요:
:::

기존 앱을 위해 “e”를 선택하세요. 그런 다음 목록에서 생성한 애플리케이션을 선택합니다.

다음으로, 코드가 설치될 디렉토리 이름을 입력하라는 메시지가 표시됩니다. 선호하는 것이 없다면 그냥 ‘enter’를 누르세요. 이 프로젝트를 위해 디렉토리 이름이 “ticketlister”라고 가정하겠습니다. 마지막으로, 질문을 받으면:

:::BlockQuote
1   디렉토리 이름:
2   빈 프로젝트를 설정하거나 현재 배포된 Cloud Code를 다운로드할 수 있습니다.
3   빈 프로젝트를 설정하려면 "(b)lank"를 입력하세요. 그렇지 않으면 ENTER를 누르세요.
:::

그냥 enter를 누르세요 (빈칸을 누르지 마세요). 이 명령이 반환되면 새 디렉토리로 cd할 수 있습니다. “cloud”라는 디렉토리와 “public”이라는 디렉토리가 두 개 보일 것입니다.

**전체 출력은 다음과 비슷하게 보여야 합니다:**

:::BlockQuote
1   $ b4a new
2   새 앱을 만들거나 기존 앱에 Cloud Code를 추가하시겠습니까?
3   "(n)ew" 또는 "(e)xisting"을 입력하세요: e
4   1: ticketlister
5   구성에 추가할 앱 선택: 11
6   최신 배포된 Cloud Code를 다운로드할 폴더 이름을 입력하세요.
7   앱 "ticketlister"의 Cloud Code
8
9   디렉토리 이름:&#x20;
10  빈 프로젝트를 설정하거나 현재 배포된 Cloud Code를 다운로드할 수 있습니다.
11  빈 프로젝트를 설정하려면 "(b)lank"를 입력하세요. 그렇지 않으면 ENTER를 누르세요:&#x20;
12  현재 프로젝트에 대한 이메일이 성공적으로 구성되었습니다: "JACKCONSIDINE3\@GMAIL.COM"
13  Cloud Code가 /tmp/ticketlister에 생성되었습니다.
14
15  여기에는 "Hello world" 클라우드 함수가 포함되어 있으므로 배포 후,
16  인쇄된 curl 명령으로 작동하는지 테스트할 수 있습니다.
17
18  다음으로, 이 코드를 배포하려면:
19
20	  cd /tmp/ticketlister
21	  b4a deploy
22
23  배포가 완료되면 다음을 실행하여 작동하는지 테스트할 수 있습니다:
24  curl -X POST \\
25   -H "X-Parse-Application-Id: Ivy4QAJQuAjDhpqQ2D3MCR4jlrCvDcVVH6yom1kk" \\
26   -H "X-Parse-REST-API-Key: yLgPHNEnt0jnzWy9BYt6ZCWHqmsWRyvCfsmqrvuS" \\
27   -H "Content-Type: application/json" \\
28   -d "\{}" \\
29   https\://parseapi.back4app.com/functions/hello
30
31  $ cd ticketlister&#x20;
32  $ ls
33  cloud  public
:::

**앱을 프로젝트 파일과 동기화 중입니다**

클라우드 및 공개 폴더 외에도 디렉토리에 두 개의 파일이 있습니다:

- .parse.local
- .parse.project

이 파일들은 Back4App 프로젝트와 관련된 데이터를 포함하고 있습니다. 나머지는 [레포지토리](https://github.com/back4app/back4app-ticketlister)의 기존 프로젝트 파일로 덮어써야 합니다. 다음은 이를 수행하는 가장 쉬운 방법입니다:

:::BlockQuote
1   cd ticketlister
2   git init
3   git remote add origin https\://github.com/back4app/back4app-ticketlister
4   git fetch origin
5   git checkout --force -b  master --track origin/master
:::

모든 것이 잘 작동했다면, 이제 다음 파일이 준비되어 있어야 합니다:

:::BlockQuote
$ ls -R
README.md         cloud             index.js          package-lock.json package.json      public

./cloud:
main.js

./public:
css         index.html  js          login.html  signup.html

./public/css:
bootstrap.min.css signin.css

./public/js:
main.js   parse.js  signin.js signup.js
:::

걱정하지 마세요 - 그게 어려운 부분이었습니다! 이제 프로젝트에 집중할 수 있습니다.

## 2 - 프론트엔드

다시 말하지만, 이 앱의 프론트엔드 코드는 **public** 디렉토리에 있습니다. 상대적으로 간단하게 유지하기 위해 React, Angular 또는 Vue와 같은 프론트엔드 프레임워크를 사용하지 않기로 결정했습니다. 이렇게 하면 외부 종속성이나 빌드가 없습니다.

:::hint{type="info"}
이 프로젝트는 HTML5 웹 컴포넌트를 사용합니다. 이들은 브라우저에서 기본적으로 지원됩니다. 이들은 사용자 인터페이스의 다양한 부분의 기능을 캡슐화하는 데 도움을 줍니다. 개발자가 새로운 HTML 요소를 선언할 수 있게 해줍니다(‘\<p>’를 생각해 보세요). 그렇지 않으면 그냥 일반 JavaScript를 사용합니다.
:::

다음&#xC740;**&#x20;public/js** 디렉토리에 있는 4개의 JavaScript 파일입니다:

:::BlockQuote
$ ls public/js
\# main.js   parse.js  signin.js signup.js
:::

1. **main.js**는 메인 페이지에서 로드되는 코드입니다, **index.html**. 이 페이지는 사용자가 티켓 등을 나열하는 곳입니다.
2. **signup.js**는 가입 페이지에서 로드되는 코드입니다, **signup.html**
3. **signin.js**는 로그인 페이지에서 로드되는 코드입니다, **login.html**
4. **parse.js**는 모든 페이지에서 사용하는 간단한 파일입니다. 백엔드와의 연결을 생성합니다. 이 파일만 수정하면 되며, 수정하지 않으면 프로젝트가 작동하지 않습니다!

**Back4App 자격 증명 추가하기**

먼저, **Application ID**와 **JavaScript Key**를 Back4App 프로젝트에서 가져와야 합니다. Back4App에 로그인한 후, 프로젝트를 선택합니다. 그런 다음 왼쪽에서 **App Settings**를 클릭하고 **Security & Keys**를 선택합니다.

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/wm1jDb3MY4-REOljU0KMQ_image.png" size="70" width="602" height="852" position="flex-start" showCaption="false"}

여러 개의 키가 표시되는 것을 볼 수 있어야 합니다. **Application ID**와 **JavaScript Key**를 가져와서 잘 보관하세요.

마지막으로, **public/js/parse.js**를 열고 각 문자열을 적절한 위치에 배치하세요. serverURL이 **https\://parseapi.back4app.com**인지 확인하는 것을 잊지 마세요.

```javascript
1   // PART 1: Put your APP ID, JS Key, and SERVER URL
2   Parse.initialize(
3     '', // YOUR APP ID
4     '' // YOUR Javascript  KEY
5   );
6   // YOUR SERVER URL
7   Parse.serverURL = 'https://parseapi.back4app.com';
```

이제 애플리케이션이 서버와 통신할 수 있습니다!

&#x20;**코드에 대한 간단한 다이브입니다.**

이 프로젝트의 모든 코드는 이 가이드의 범위를 벗어나지만, 각 파일을 살펴보시기를 권장합니다. 아무것도 복잡하지 않으며, 1,000피트 뷰를 제공할 수 있는 시간을 잠깐 가지겠습니다.

- 이 프로젝트는 [HTML5 웹 컴포넌트](https://developer.mozilla.org/en-US/docs/Web/API/Web_components)를 사용하여 인터페이스의 각 논리적 섹션을 캡슐화합니다.
- HTML 파일의 중요한 마크업은 <font color="#2166ae">`HTML <template>`</font> 태그 내에 있습니다. 이것이 우리가 레이아웃을 설명하는 방법입니다.
- 애플리케이션의 “기능성”은 JavaScript 파일에서 발생합니다. 여기서 앱은 양식이 제출되거나 버튼이 클릭될 때 무엇을 해야 하는지를 설명합니다.

예를 들어, 로그인 컴포넌트를 살펴보세요. 마크업 (**public/login.html**)은 다음과 같습니다:

```html
1   <template id="signin-template">
2     <style>
3       @import 'css/signin.css';
4       @import 'css/bootstrap.min.css';
5     </style>
6     <div class="signin-wrapper text-center">
7       <form class="auth-form">
8         <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
9         <label for="inputEmail" class="sr-only">Email address</label>
10        <input
11          type="email"
12          id="inputEmail"
13          class="form-control"
14          placeholder="Email address"
15          required=""
16          autofocus=""
17        />
18        <label for="inputPassword" class="sr-only">Password</label>
19        <input
20          type="password"
21          id="inputPassword"
22          class="form-control"
23          placeholder="Password"
24          required=""
25        />
26        <button class="btn btn-lg btn-primary btn-block" type="submit">
27          Sign in
28        </button>
29        <div class="text-center"><a href="/signup.html"> Sign Up</a></div>
30      </form>
31    </div>
32  </template>
33  <!-- This tag below simply tells the browser to render the component we declared above -->
34  <login-form></login-form>
```

그리고 기능은 JavaScript 파일 (**public/signin.js**)에 나타납니다.

```javascript
1   // Code above ^
2       // When the code is ready, listen for the form to be submitted. When it is,
3       //  call the 'onSubmit' method
4       connectedCallback() {
5         const form = this.shadowRoot.querySelector('form');
6         form.addEventListener('submit', this.onSubmit.bind(this), false);
7       }
8     // Obtain the email and password from the markup inputs
9       onSubmit(e) {
10        e.preventDefault();
11        //   Get inputs
12        const email = this.shadowRoot.querySelector('#inputEmail').value;
13        const password = this.shadowRoot.querySelector('#inputPassword').value;
14        this.login(email, password);
15      }
16    // Send a request to the backend, attempting to login. If the login
17    //  is successful, go to the index.html page. Otherwise, give the user
18    // an alert explaining what went wrong
19      login(email, password) {
20        // Add login method here
21        Parse.User.logIn(email, password)
22          .then(user => {
23            window.location.href = 'index.html';
24          })
25          .catch(e => {
26            alert(e.message);
27          });
28      }
29      // More code below
30
```

전체 애플리케이션은 이 일반적인 구조를 가집니다. 프론트 엔드가 백엔드와 이렇게 통신하는 경우를 주의 깊게 살펴보세요: (**public/js/main.js**).

다음 단계에서는 이러한 함수가 어떻게 선언되는지 살펴보겠습니다.

## 3 - 백엔드

전체 백엔드는 **cloud/main.js**, 클라우드 코드 함수 파일에 있습니다. 이는 Back4App으로 얼마나 적은 코드로 많은 것을 이룰 수 있는지를 증명하는 매우 적은 양의 코드로 구성되어 있습니다.

앱의 일부(티켓이 나열될 수 있는 이벤트 생성)는 단순히 Back4App 대시보드를 사용할 것입니다. 이 멋진 기능은 우리 프로젝트와 함께 제공되므로, 바퀴를 다시 발명할 필요가 없습니다!

다시 말해, 각 코드 라인을 검토하는 것은 우리의 범위를 벗어납니다. 그러나 우리는 코드가 어떻게 작동하는지에 대한 또 다른 넓은 시각을 가질 것입니다.



- 당신은 **Cloud Functions**를 **cloud/main.js** 파일에 선언합니다. 이러한 함수는 프론트 엔드에서 호출할 수 있습니다 (참조 **2단계**). Cloud Functions에 대한 자세한 정보는 [문서](https://docs.parseplatform.org/cloudcode/guide/#cloud-functions)를 참조하세요.
- 또한, 이러한 Cloud Functions는 Parse Server에서 실행됩니다. 이 [가이드](https://www.back4app.com/docs/advanced-guides/parse-server-3)는 사용되는 구문에 대해 설명하므로, 살펴보는 것이 도움이 될 수 있습니다.

보다 구체적으로, 우리가 정의하는 함수는 다음과 같습니다:

1. ‘**user\:signup**’ - 사용자 가입 흐름을 처리하는 코드
2. ‘**tickets\:list**’ - 모든 나열된 티켓을 검색하는 코드
3. ‘**tickets\:create**’ - 새 티켓을 생성하는 코드
4. ‘**events\:list**’ - 모든 이벤트를 나열하는 코드

마지막으로 코드 노트: 파일 상단에 간단한 메서드를 추가했습니다:

```javascript
1   const requireAuth = user => {
2     if (!user) throw new Error('User must be authenticated!');
3   };
```

특정 클라우드 기능은 사용자가 로그인해야 합니다. 요청의 사용자 속성과 함께 이 함수를 호출함으로써, 아무도 무단 요청을 할 수 없도록 보장합니다.

나머지 함수들을 훑어보는 것을 강력히 권장합니다. 그들이 무엇을 하는지 알게 되었으니, 이제 배포할 수 있습니다!

## 4 - 배포하기

모든 코드를 정리했으며, 이제 앱을 Back4App에 배포할 수 있습니다. 다음 명령어는 모든 공개 및 클라우드 파일을 업로드합니다:

:::BlockQuote
b4a deploy
:::

**로컬 웹사이트 호스팅**

업로드한 웹 앱을 보기 위해 공개 도메인을 얻으려면 Back4App 대시보드에서 웹 호스팅을 활성화해야 합니다.

먼저, 대시보드 왼쪽에서 “서버 설정”을 엽니다:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/V5-yoz42if7bmLRlv-pU3_image.png" size="70" width="500" height="715" position="flex-start" showCaption="false"}

다음으로, “웹 호스팅 및 라이브 쿼리” 아래의 “설정” 링크를 클릭합니다.

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/VOlHTaDxFfwg6chUQZRnT_image.png" size="70" width="500" height="559" position="flex-start" showCaption="false"}

마지막으로, “Back4App 호스팅 활성화”를 체크합니다. 고유한 하위 도메인을 선택해야 합니다. 이 프로젝트에 대해 ticketlister를 이미 등록했으므로 다른 것을 선택하세요. 선택적으로, 소유한 도메인을 이 back4app 도메인으로 “포인팅”하도록 구성할 수 있습니다. 나는 [http://ticketlister.koptional.com](https://www.back4app.com/docs/advanced-guides/my%20website)에 대해 이렇게 설정했습니다:&#x20;

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/YlLshpzkdaVyh9C-gVoQA_image.png" size="70" width="500" height="484" position="flex-start" showCaption="false"}

웹사이트에서 시작할 계획이라면 “사용자 정의 도메인” 아래의 텍스트를 주의 깊게 확인하세요.

이 단계를 제대로 완료하면 도메인으로 이동하여 앱을 사용할 수 있습니다. 사용자 정의 도메인이 없는 경우, http\://\<YOUR\_SUBDOMAIN>.back4app.io를 열면 됩니다. 여기서 YOUR\_SUBDOMAIN은 방금 선택한 이름입니다.

## 5 - 사용 및 대시보드

티켓을 나열하려면 Back4App의 관리 대시보드에서 이벤트를 생성해야 합니다.

데이터 브라우저로 이동하여 ‘이벤트’ 클래스를 생성하세요. ‘이름’(문자열)과 ‘언제’(날짜)라는 열을 추가합니다. 그런 다음 이벤트를 직접 추가할 수 있습니다. 모든 열을 채우는 것을 잊지 마세요. 다음과 비슷하게 보일 것입니다:

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/eSQqyJ80U9z16k7RVRxGq_image.png" size="70" width="1086" height="636" position="flex-start" showCaption="false"}

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/M8tpIQJ10s21Q5x7xTWJo_image.png" size="70" width="1082" height="636" position="flex-start" showCaption="false"}

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/HyMOBwx-36Yst_44UDAG6_image.png)

이제 웹 앱에서 로그인하고 해당 이벤트로 티켓을 나열할 수 있습니다.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/7Q7WtLTkpTcsr8EXY-LaS_image.png)

Parse / Back4App와 함께 제공되는 이 관리 기능은 작업량을 줄여주는 또 다른 지름길입니다.

## 결론

백엔드가 있는 웹 애플리케이션을 만드는 것은 종종 몇 주 또는 몇 달이 걸리는 작업입니다. 우리는 Back4App의 강력한 인프라와 Parse SDK를 활용하여 훨씬 더 빠르게 출시했습니다. 이 접근 방식을 사용하면 시간을 낭비하지 않고도 놀라운 것을 구축할 수 있습니다.
