NextJS에서 form 다루기 - docs

Evan Lee ㅣ 2023. 4. 5. 04:10

Form을 다룰 일이있어서 공식문서 읽어볼겸 영어도 공부할겸 적어보겠습니다. 


https://nextjs.org/docs/guides/building-forms
 

Building Forms with Next.js | Next.js

Learn how to create forms with Next.js, from the form HTML element to advanced concepts with React.

nextjs.org

 

Part 1: HTML Form

HTML forms are built using the <form> tag. It takes a set of attributes and fields to structure the form for features like text fields, checkboxes, dropdown menus, buttons, radio buttons, etc.

Here's the syntax of an HTML form:

HTML Form들은 <form> 태그를 사용해서 설계합니다. attributes와 텍스트, 체크박스, 드랍다운 메뉴, 버튼 라디오박스 기타 등등 같은 각기 다른 필드들의 세트들을 사용해서 구조화를 하게됩니다. 아래는 HTML 폼의 문법입니다. 

프론트엔드 쪽에서는 아래와 같이 보일겁니다. 

 

 

The HTML <form> tag acts as a container for different <input> elements like text field and submit button. Let's study each of these elements:

  • action: An attribute that specifies where the form data is sent when the form is submitted. It's generally a URL (an absolute URL or a relative URL).
  • method: Specifies the HTTP method, i.e., GET or POST used to send data while submitting the form.
  • <label>: An element that defines the label for other form elements. Labels aid accessibility, especially for screen readers.
  • <input>: The form element that is widely used to structure the form fields. It depends significantly on the value of the type attribute. Input types can be text, checkbox, email, radio, and more.
  • <button>: Represents a clickable button that's used to submit the form data.
HTML `<form>` 태그는 텍스트 필드와 제출 버튼과 같은 요소들 같은 각기 다른 `<input>` 태그들의 컨테이너와 같은 역할을 합니다. 

-`action`: Form이 제출될때, Form의 데이터를 어디로 보내질지 명시하는 속성입니다. 일반적으로 URL입니다. ( 절대 경로 혹은 상대 경로입니다. )

- `method`: HTTP Method를 명시합니다, 즉, Form 제출될 동안  데이터를 전송하는 데 사용되는 GET 아니면 POST가 사용됩니다.

- `<label>`: 다른 Form 요소들에 대해서 라벨링을 선언해주는 요소입니다. 라벨 태그는 접근성을 지원합니다. 특히나 스크린 리더같은 예가 있습니다. 

- `<input>`:  Form 필드들을 구조화하기 위해 제일 폭 넓게 사용하는 Form 요소입니다. 타입 속성의 값에 따라 상당히 다르게 작용되는데, Input 타입들은 text, checkbox, email, raido 그리고 여러가지 가 있습니다. 

- `<button>`: Form 데이터를 제출하기 위해 사용되는 클릭가능한 버튼들을 말합니다. 

 

Form Validation 

 

A process that checks if the information provided by a user is correct or not. Form validation also ensures that the provided information is in the correct format (e.g. there's an @ in the email field). These are of two types:

  • Client-side: Validation is done in the browser
  • Server-side: Validation is done on the server

Though both of these types are equally important, this guide will focus on client-side validation only.

Client-side validation is further categorized as:

  • Built-in: Uses HTML-based attributes like required, type, minLength, maxLength, pattern, etc.
  • JavaScript-based: Validation that's coded with JavaScript.
유저가 정확한 정보를 제공했는지를 확인하기 위한 과정입니다. Form 유효성 검사는 제공된 정보가 정확한 포맷으로 작성되있는지를 보증하기도 합니다. ( 예를 들면 email 필드에는 '@' 가 있겠죠. )

두가지 타입이 있습니다.

- 클라이언트 사이드: 브라우저안에서 유효성검사는 끝납니다.
- 서버 사이드: 서버안에서 유효성검사는 끝납니다. 

두가지 타입 둘다 똑같이 중요하지만, 이 가이드는 클라이언트 사이드 유효성에만 집중합니다.

클라이언트 사이드 유효성은 더 나아가서 분류될 수 있는데, 

- 빌트인: required, type, minLength, maxLength, pattern 등 과 같은 HTML 베이스의 속성들을 사용합니다. 


- 자바스크립트 베이스: 자바스크립트로 짜여진 유효성 검사를 말합니다. 

 

Built-in Form Validation Using required, type, minLength, maxLength

 

  • required: Specifies which fields must be filled before submitting the form.
  • type: Specifies the data's type (i.e a number, email address, string, etc).
  • minLength: Specifies minimum length for the text data string.
  • maxLength: Specifies maximum length for the text data string.
- required: Form이 제출되기 전에 반드시 필드안에 값이 채워줘야 한다는 것을 명시합니다.
- type: 데이터의 타입을 명시합니다. ( 즉, 숫자, 이메일주소, 문자열  등 )
- minLength: 문자열 데이터의 최소길이를 명시합니다.
- maxLength: 문자열 데이터의 최대길이를 명시합니다.

 

 

이 속성들은 사용한 Form은 아래와 같이 보일겁니다. 

 

With these validation checks in place, when a user tries to submit an empty field for Name, it gives an error that pops right in the form field. Similarly, a roll number can only be entered if it's 10-20 characters long.

유효성 검사를 추가하게 되면, 유저가 name 이라는 필드를 빈 값으로 제출하려고 시도하면 form 필드에 에러를 띄워줍니다. 같은 원리로,  roll number에는 10-20 글자 길이안에서만 입력이 가능합니다.

 

 

 

자바스크립트 베이스 Form 유효성 검사 

 

Form Validation is important to ensure that a user has submitted the correct data, in a correct format. JavaScript offers an additional level of validation along with HTML native form attributes on the client side. Developers generally prefer validating form data through JavaScript because its data processing is faster when compared to server-side validation, however front-end validation may be less secure in some scenarios as a malicious user could always send malformed data to your server.

Form 유효성은 유저가 올바른 포맷, 올바른 데이터가 제출됬는지 보장하기 위해 중요합니다. 자바스크립트 또한 클라이언트 사이드에서 HTML 내장 Form 속성과 마찬가지로 추가적인 수준의 유효성을 제공합니다. 개발자들은 일반적으로 서버 측 유효성 검사에 비해 데이터 처리 속도가 빠른 자바스크립트를 통한 폼 데이터 유효성 검사를 선호하지만, 일부 시나리오에서는 악의적인 사용자가 계속해서 잘못된 형식의 데이터를 서버로 전송할 수 있기 때문에 안전하지 않을 수 있습니다.

 

 

 

The HTML script tag is used to embed any client-side JavaScript. It can either contain inline scripting statements (as shown in the example above) or point to an external script file via the src attribute. This example validates the name and roll number of a user. The validateFormWithJS() function does not allow an empty name field, and the roll number must be at least three digits long. The validation is performed when you hit the Submit button. You are not redirected to the next page until the given values are correct.

 

HTML `script` 태그는 어떤 클라이언트 사이드 자바스크립트를 포함시키기 위해 사용됩니다. 위 예와 같이 인라인 스크립트 문을 포함하거나 src 속성을 통해 외부 스크립트 파일을 가리킬 수 있습니다. 이 예제는 name과 사용자의 roll number를 유효성 검사를합니다. validateFormWithJS() 함수는 빈 name 필드를 받지 않습니다. 그리고 roll number는 최소 3 digits 길이 이상이 되어야합니다. 유효성검사는 제출 버튼이 클릭되면 실행됩니다. 당신은 주어진 값이 맞을때까지 다음페이지로 리다이렉트가 안 될 것입니다.
 

Form Validation Using Regular Expressions

JavaScript validation with Regular Expressions uses the pattern HTML attribute. A regular expression (commonly known as RegEx) is an object that describes a pattern of characters. You can only apply the pattern attribute to the <input> element. This way, you can validate the input value using Regular Expressions (RegEx) by defining your own rules. Once again, if the value does not match the defined pattern, the input will give an error. The below example shows using the pattern attribute on an input element:

정규식을 사용한 자바스크립트 유효성 검사는 패턴 HTML 속성을 사용합니다. 정규표현식( RegEx라고 흔히 불립니다. )은 글자의 패턴을 묘사하는 객체입니다. 오직 `<input>` 요소에만 패턴 속성을 적용시킬수 있습니다. 이 방법으로, 당신은 본인만의 룰을 정의해서 인풋 값을 정규식 사용해 유효성 검사를 할 수 있습니다. 다시 한번 말하자면, 만약 값이 정의된 패턴과 매치가 되지않는다면 인풋에서는 에러를 뱉습니다. 아래 예제를 보면 인풋 요소에 패턴 속성을 사용합니다. 

The password form field must only contain digits (0 to 9), lowercase alphabets (a to z) and it must be no more than 15 characters in length. No other characters (#,$,&, etc.) are allowed. The rule in RegEx is written as [a-z0-9]{1,15}.

패스워드 Form 필드는 반드시 0부터 9,  소문자 알파벳이 포함되어 있어야하고, 15글자 이상의 초과되면 안됩니다. 특수문자는 허용하지않네요. 위와같은 정규표현식은 다음과 같이 씁니다.  [a-z0-9]{1,15}.

 

Part 2: Project Setup

In the following section you will be creating forms in React using Next.js.

Create a new Next.js app. You can use the create-next-app for a quick start. In your command line terminal, run the following:

이번 섹션에서는 Next.js를 사용해 Form들을 리액트안에서 만들겁니다.  새로운 NextJS 앱을 만듭니다. 아래 명령어를 터미널에서 실행시켜 빠르게 시작하실수 있습니다. 

 

npx create-next-app

 

Answer the questions to create your project, and give it a name, this example uses next-forms. Next cd into this directory, and run npm run dev or yarn dev command to start the development server.

Open the URL printed in the terminal to ensure that your app is running successfully.

프로젝트 생성을 위해 질문에 답하고, 이름을 정하고, 이 예제는 next-fomrs를 사용합니다. 그 다음 해당 디렉토리로 cd를 사용해 들어가고 npm run dev 혹은 yarn dev 명령어를 사용해 개발 서버 실행시킵니다. URL이 터미널에서 출련된다면 성공적으로 시작된 것 입니다. 

 

Part 3: Setting up a Next.js Form API Route

Both the client and the server will be built using Next.js. For the server part, create an API endpoint where you will send the form data. Next.js offers a file-based system for routing that's built on the concept of pages. Any file inside the folder pages/api is mapped to /api/* and will be treated as an API endpoint instead of a page. This API endpoint is going to be server-side only. Go to pages/api, create a file called form.js and paste this code written in Node.js:

클라이언트, 서버 사이드와 둘다 NextJS를 사용해 구현할 것 입니다. 서버쪽은 , form 데이터를 보낼 API 엔드포인트를 만들것입니다. NextJS는 페이지의 컨셉에 따라 설계된 파일-베이스 라우팅 시스템을 제공합니다. pages/api 폴더안에 어떤 파일이는 /api/* 에 매핑이 되고, page 대신에 API 엔드포인트로써 다뤄집니다. 이 API 엔드포인트는 오직 서버사이드에서만 진입하게됩니다. pages/api에 가서, form.js라는 파일을 만들고, 이 코드를 Node.js에 붙여넣습니다. 

 

This form handler function will receive the request req from the client (i.e. submitted form data). And in return, it'll send a response res as JSON that will have both the first and the last name. You can access this API endpoint at http://localhost:3000/api/form or replace the localhost URL with an actual Vercel deployment when you deploy.

이 Form 핸들러 함수는 클라이언트로부터 요청 req를 받습니다. ( 즉 제출된 폼 데이터 ). 그리고 반환값으로, first, last name을 JSON 응답으로 보내줄겁니다. 당신은 API 엔드포인트를 http://localhost:3000/api/form 으로 접근하거나, 배포가 된 실제 Vercel 주소를 localhost URL로 바꿀 수 있습니다. 

 

Form Submission without JavaScript

 

You can now use /api/form relative endpoint inside the action attribute of the form. You are sending form data to the server when the form is submitted via POST HTTP method (which is used to send data).

이제 폼의 action 속성안에서 /api/form 엔드포인트를 사용하실 수 있습니다. Form이 POST HTTP 메서드(데이터 전송에 사용됨)를 통해 제출될 때 Form 데이터를 서버로 보냅니다.

 

 

If you submit this form, it will submit the data to the forms API endpoint /api/form. The server then responds, generally handling the data and loading the URL defined by the action attribute, causing a new page load. So in this case you'll be redirected to http://localhost:3000/api/form with the following response from the server.

만약 form을 제출한다면, API 엔드포인트 /api/form로 forms 데이터를 제출합니다. 그러면 서버가 응답을 하고, 일반적으로 데이터를 처리하고 action 속성에 의해 정의된 URL을 로드하여 새 페이지 로드를 발생시킵니다. 그래서 이 경우에는 http://localhost:3000/api/form 으로 리다이렉트가 될거고 다음과 같은 응답이 서버로부터 올겁니다. 

 

Part 4: Configuring Forms in Next.js

You have created a Next.js API Route for form submission. Now it's time to configure the client (the form itself) inside Next.js using React. The first step will be extending your knowledge of HTML forms and converting it into React (using JSX).

Here's the same form in a React function component written using JSX.

 당신은 form 제출을 위해 Nextjs API 라우트를 생성했습니다. 이제 React를 사용한 Nextjs 안에서 클라이언트를 설정할 시간입니다HTML의 지식을 확장 및 React로 변환하는게 첫번째 단계가 될 것입니다. 

 

 

Here's what changed:

  • The for attribute is changed to htmlFor. (Since for is a keyword associated with the "for" loop in JavaScript, React elements use htmlFor instead.)
  • The action attribute now has a relative URL which is the form API endpoint.

This completes the basic structure of your Next.js-based form.

 

바뀐점을 말하자면: 

- for 속성이 htmlFor로 바뀌었습니다. ( 자바스크립트에 'for' 루프라는 키워드가 있기때문에 React 엘리먼트에서는 htmlFor을 사용합니다. ) 
- action 속성은 이제 form API 엔드포인트인 상대 경로를 갖게됩니다. 

이게 Nextjs 기반 form의 기본적인 구조의 완성본입니다. 

 

Part 5: Form Submission without JavaScript

 

JavaScript brings interactivity to our web applications, but sometimes you need to control the JavaScript bundle from being too large, or your sites visitors might have JavaScript disabled.

There are several reasons why users disable JavaScript:

  • Addressing bandwidth constraints
  • Increasing device (phone or laptop) battery life
  • For privacy so they won’t be tracked with analytical scripts

Regardless of the reason, disabling JavaScript will impact site functionality partially, if not completely.

Next open the next-forms directory. Inside the /pages directory, create a file no-js-form.js.

 

자바스크립트는 웹 어플리케이션에 상호 작용을 제공하지만 때때로 자바스크립트 번들이 너무 크지 않도록 제어해야 하거나 사이트 방문자가 자바스크립트를 사용하지 않도록 설정할 수 있습니다. 사실 유저들이 자바스크립트를 끄게되는 이유는 많습니다.

- 대역폭 제약 해결
- 장비(전화기 또는 노트북) 배터리 수명 증가
- 분석 스크립트로 추적되지 않도록 개인 정보 보호를 위해

 

 

자바스크립트가 비활성화된 상태에서 Submit 버튼을 누르면 action 속성에 정의된 대로 Form 데이터를 수집하여 POST HTTP 메서드를 사용하여 Form API 엔드포인트로 보내는 이벤트가 트리거됩니다. 그리고 form의 action이 동작하듯이 /api/form 엔드포인트 리다이렉트가 될겁니다. from 데이터는 위에 작성된 form 핸들러 함수에 대한 요청 `req`로 서버에 제출됩니다. 데이터를 처리하고 제출된 이름이 포함된 응답 res로 JSON 문자열을 반환합니다.

 

Part 6: Form Submission with JavaScript Enabled

Inside /pages, you'll create another file called js-form.js. This will create a /js-form page on your Next.js app.

Now, as soon as the form is submitted, we prevent the form's default behavior of reloading the page. We'll take the form data, convert it to JSON string, and send it to our server, the API endpoint. Finally, our server will respond with the name submitted. All of this with a basic JavaScript handleSubmit() function.

Here's what this function looks like. It's well documented for you to understand each step:

/pages 안에 js-form.js라는 파일을 만들겁니다.  이를 통해 Nextjs 앱에 /js-form 페이지를 만듭니다. 이제, form이 제출되자마자, 우리는 페이지를 재로딩의 form의 기본 동작을 예방합니다. form 데이터를 가져와 JSON 문자열로 변환하여 서버인 API 엔드포인트로 전송합니다. 마지막으로, 우리 서버는 제출된 이름을 응답합니다. 이 모든 것은 기본 자바스크립트 handleSubmit() 함수를 사용합니다. 이 기능은 다음과 같습니다. 각 단계를 이해할 수 있도록 문서화되어 있습니다.

 

It's a Next.js page with a React function component called PageWithJSbasedForm with a <form> element written in JSX. There's no action on the <form> element. Instead, we use the onSubmit event handler to send data to our {handleSubmit} function.

The handleSubmit() function processes your form data through a series of steps:

  • The event.preventDefault() stops the <form> element from refreshing the entire page.
  • We created a JavaScript object called data with the first and last values from the form.
  • JSON is a language-agnostic data transfer format. So we use JSON.stringify(data) to convert the data to JSON.
  • We then use fetch() to send the data to our /api/form endpoint using JSON and HTTP POST method.
  • Server sends back a response with the name submitted. Woohoo! 🥳
이것은 React 함수 컴포넌트인 PageWithJSbasedForm과 <form> 엘리먼트가 JSX로 작성된 Next.js 페이지입니다. <form> 엘리먼트에 대한 작업이 없습니다. 대신 onSubmit 이벤트 핸들러를 사용하여 데이터를 {handleSubmit} 함수로 보냅니다.

handleSubmit() 함수는 다음과 같은 일련의 단계를 통해 양식 데이터를 처리합니다: 
 
1. event.preventDefault()는 <form> 요소가 전체 페이지를 새로 고치는 것을 중지합니다.
2. 우리는 Form의 첫 번째와 마지막 값으로 데이터라는 자바스크립트 객체를 만들었습니다.
3. JSON은 언어에 구애받지 않는 데이터 전송 형식입니다. 따라서 JSON.stringify(data)를 사용하여 데이터를 JSON으로 변환합니다.
4. 그런 다음 fetch()를 사용하여 JSON 및 HTTP POST 메서드를 사용하여 /api/form 엔드포인트로 데이터를 보냅니다.
5. 서버는 제출된 이름으로 응답을 다시 보냅니다.