아랄라랄라
R 스토리
아랄라랄라
전체 방문자
오늘
어제
  • All (207) N
    • Web (152) N
      • Markup | WEB (9)
      • Styles (45)
      • javascript (32)
      • jquery (28)
      • vue (16)
      • react (17) N
      • more (5)
    • IT (32)
      • CS (3)
      • git hub (5)
      • UI | UX (18)
      • more (6)
    • ETC (23) N
      • 이슈노트 (13) N
      • 스터디 (10)
      • 아랄라 ☞☜ (0)
      • JOB🛠 (0)

인기 글

반응형
hELLO · Designed By 정상우.
아랄라랄라

R 스토리

Web/react

[Next.js] Next.js + TypeScript + Tailwind CSS 관리자 페이지 만들기 1

2026. 5. 8. 13:17

대상

이 문서는 아래와 같은 사람을 기준으로 설명합니다.

  • HTML/CSS는 익숙하다
  • JavaScript는 초급 수준이다
  • React를 아주 조금 들어봤다
  • Next.js는 처음이다
  • 실무 스타일의 관리자 페이지를 만들어보고 싶다

 


 

지금까지 만든 것

나는 현재 아래 기능까지 만들었다.

/admin
/admin/ads
/admin/ads/[id]

 

즉,

대시보드
광고 목록
광고 상세

이 흐름을 만들었다.

그리고 아래 기술들을 사용했다.

Next.js
TypeScript
Tailwind CSS
App Router
Dynamic Route
layout.tsx
map()
Link
usePathname()

 

 


 

Next.js란?

Next.js는 React 기반 프레임워크다.

 

쉽게 말하면:

React를 더 실무적으로 편하게 쓰게 해주는 도구

라고 생각하면 된다.

 

예를 들면 React만 쓰면 직접 설정해야 하는 것들을:

라우팅
페이지 구조
서버 기능
최적화
빌드

Next.js가 자동으로 처리해준다.

 

그래서 실무에서는 React 단독보다 Next.js를 훨씬 많이 사용한다.

 

 


 

왜 TypeScript를 같이 쓰는가?

나는 Next.js를 만들 때:

npx create-next-app@latest

를 사용했고,

TypeScript: Yes

를 선택했다.

 

 


 

TypeScript란?

TypeScript는 JavaScript에 타입 기능을 추가한 언어다.

 

예를 들어:

const name = "홍길동";

이건 JavaScript.

 

TypeScript에서는:

const name: string = "홍길동";

처럼 타입을 명시할 수 있다.

 

 


 

타입을 왜 쓰는가?

예를 들어 광고 데이터를 만든다고 생각해보자.

{
    id: 1,
    title: "메인 광고",
    status: "진행중"
}

 

그런데 실수로:

{
    id: "안녕하세요"
}

이렇게 넣으면?

광고 id는 숫자여야 하는데 문자열이 들어간 거다.

TypeScript는 이런 실수를 미리 잡아준다.

 

즉:

개발 실수를 줄여준다

이게 가장 큰 장점이다.

 

 


 

Tailwind CSS란?

나는 CSS를 이렇게 작성하지 않았다.

.box {
    padding: 20px;
    background: white;
}

 

대신:

<div className="p-5 bg-white">

 

처럼 작성했다.

이게 Tailwind CSS다.

 

 


 

Tailwind CSS 장점

1. 빠르다

<div className="flex items-center justify-between">

한 줄로 레이아웃 가능.

 

 


 

2. 클래스 이름 고민이 없다

보통 CSS는:

.card-box
.card-wrap
.card-inner

이런 네이밍 고민이 많다.

Tailwind는 그런 고민이 거의 없다.

 

 


 

3. 반응형 작업이 편하다

className="p-4 lg:p-8"

모바일:

padding: 16px

PC:

padding: 32px

자동 처리.

 

 


 

App Router란?

나는:

src/app

폴더를 사용하고 있다.

이걸 App Router 방식이라고 한다.

Next.js 최신 방식이다.

 

 


 

App Router 핵심 개념

폴더 이름이 곧 URL이다.

 

예:

src/app/admin/page.tsx

는:

/admin

페이지가 된다.

 

 


 

src/app/admin/ads/page.tsx

는:

/admin/ads

가 된다.

 

 


 

현재 프로젝트 구조

src
 ├─ app
 │   ├─ layout.tsx
 │   ├─ globals.css
 │   │
 │   └─ admin
 │       ├─ layout.tsx
 │       ├─ page.tsx
 │       │
 │       └─ ads
 │           ├─ page.tsx
 │           │
 │           └─ [id]
 │               └─ page.tsx
 │
 ├─ components
 │   └─ admin
 │       ├─ AdminHeader.tsx
 │       └─ AdminSidebar.tsx
 │
 └─ lib
     └─ dummy-data.ts

 

 

 


 

layout.tsx 이해하기

이건 Next.js 초보가 가장 헷갈려하는 부분이다.

 

 


 

Root Layout

파일:

src/app/layout.tsx

이건 앱 전체의 가장 바깥 껍데기다.

 

나는 이렇게 만들었다.

<html lang="ko">
    <body>
        {children}
    </body>
</html>

 

 


 

왜 html/body가 필요한가?

Next.js App Router에서는:

<html>
<body>

가 반드시 있어야 한다.

 

없으면 이런 에러가 난다.

Missing <html> and <body> tags in the root layout.

 

 


 

children이란?

{children}

은:

실제 페이지 내용이 들어오는 자리

라고 이해하면 된다.

 

예:

/admin

에 접속하면:

src/app/admin/page.tsx

내용이 children에 들어간다.

 

 


 

관리자 전용 layout

파일:

src/app/admin/layout.tsx

이건 관리자 페이지 전용 공통 레이아웃이다.

 

나는 여기서:

사이드바
헤더
콘텐츠 영역

을 만들었다.

 

즉:

/admin
/admin/ads
/admin/users

같은 관리자 페이지들은 전부 같은 레이아웃을 공유한다.

 

 


 

왜 layout을 쓰는가?

예를 들어 사이드바를 모든 페이지에 직접 넣으면:

/admin/page.tsx
/admin/ads/page.tsx
/admin/users/page.tsx

전부 같은 코드를 반복해야 한다.

 

layout.tsx를 쓰면:

한 번만 작성하면 모든 페이지에 자동 적용

된다.

실무에서 매우 중요하다.

 

 


 

컴포넌트란?

나는:

AdminSidebar
AdminHeader

를 만들었다.

이런 걸 컴포넌트라고 한다.

 

 


 

컴포넌트를 왜 쓰는가?

예를 들어 헤더를 여러 곳에서 사용한다고 생각해보자.

컴포넌트가 없으면:

복붙
복붙
복붙

해야 한다.

 

컴포넌트로 만들면:

<AdminHeader />

한 줄로 재사용 가능하다.

 

 


 

map() 이해하기

나는 메뉴와 광고 목록에서 map()을 사용했다.

예:

menuItems.map((item) => {
    return <li>{item.name}</li>;
});

 

map()이란?

배열을 반복하는 함수다.

예:

const numbers = [1, 2, 3];

 

이걸 반복하면:

1
2
3

하나씩 꺼낼 수 있다.


 

광고 목록에서 map()

{ads.map((ad) => {
    return (
        <tr>
            <td>{ad.title}</td>
        </tr>
    );
})}

 

의미는:

광고 배열을 반복해서 테이블 행을 만들어라

이다.


 

key란?

<tr key={ad.id}>

React는 반복 요소를 구분하기 위해 key가 필요하다.

 

즉:

각 요소의 고유값

이다.

 

보통:

id

를 많이 사용한다.


 

Link 컴포넌트

나는 a 태그 대신:

<Link href="/admin/ads">

를 사용했다.


 

왜 a 태그를 안 쓰는가?

Next.js에서는 페이지 이동을 최적화하기 위해 Link를 사용한다.

장점:

빠른 페이지 이동
새로고침 최소화
성능 향상

 

동적 라우트 [id]

나는:

src/app/admin/ads/[id]/page.tsx

를 만들었다.

 

대괄호 폴더는:

동적으로 변하는 값

을 의미한다.


 

예시

/admin/ads/1
/admin/ads/2
/admin/ads/3

 

여기서:

1
2
3

이 id가 된다.


 

params란?

Next.js는 URL의 값을 params로 전달한다.

 

예:

/admin/ads/3

이면:

params.id

값은:

"3"

이다.


 

Next.js 최신 버전에서 바뀐 점

예전에는:

params.id

를 바로 사용할 수 있었다.

하지만 최신 Next.js에서는 params가 Promise가 되었다.

 

그래서:

const { id } = await params;

처럼 사용해야 한다.


 

왜 async를 붙였는가?

export default async function AdDetailPage()

await를 사용하려면 함수가 async여야 한다.

 

즉:

비동기 함수로 만들어야 await 사용 가능

이다.


 

find() 이해하기

나는 광고 상세 페이지에서:

const ad = ads.find((item) => {
    return item.id === adId;
});

를 사용했다.


 

find()란?

배열에서 조건에 맞는 하나를 찾는 함수다.

 

예:

const users = [
    { id: 1, name: "철수" },
    { id: 2, name: "영희" },
];

여기서 id가 2인 사람 찾기:

users.find((user) => {
    return user.id === 2;
});

 

결과:

{ id: 2, name: "영희" }

 

notFound()

나는:

if (!ad) {
    notFound();
}

를 사용했다.


 

왜 필요한가?

예:

/admin/ads/999

 

같이 존재하지 않는 페이지 접근 시:

404 페이지

로 보내기 위해 사용한다.


 

반응형 작업

나는 Tailwind 반응형 문법도 사용했다.

 

예:

className="p-4 lg:p-8"

의미:

모바일: padding 16px
PC: padding 32px

 

Tailwind 반응형 규칙

기본 = 모바일
sm = 작은 태블릿
md = 태블릿
lg = 노트북/PC
xl = 큰 화면

 

예시

className="flex flex-col lg:flex-row"

 

의미:

모바일: 세로
PC: 가로

 

관리자 페이지 반응형 전략

나는:

모바일
- 상단 메뉴
- 테이블 가로 스크롤
- 작은 padding

PC
- 왼쪽 사이드바
- 넓은 콘텐츠
- 큰 여백

전략으로 만들었다.


 

overflow-x-auto

테이블 반응형에서 중요한 코드:

<div className="overflow-x-auto">

 

이건:

가로 스크롤 허용

이라는 뜻이다.

관리자 테이블은 컬럼이 많아서 모바일에서 자주 사용한다.


 

현재 메뉴 활성화

나는:

usePathname()

를 사용해서 현재 메뉴를 활성화했다.


 

usePathname()

현재 URL 경로를 가져오는 훅이다.

 

예:

/admin/ads

이면:

const pathname = usePathname();

 

결과:

/admin/ads

 

왜 "use client"가 필요한가?

usePathname은 React 훅이다.

React 훅은 클라이언트 컴포넌트에서만 사용할 수 있다.

그래서:

"use client";

를 파일 최상단에 넣었다.


 

서버 컴포넌트 vs 클라이언트 컴포넌트

Next.js App Router의 핵심 개념 중 하나다.


 

서버 컴포넌트

기본 상태.

장점:

빠름
성능 좋음
보안 유리

 

클라이언트 컴포넌트

브라우저에서 동작하는 컴포넌트.

필요한 경우:

useState
useEffect
클릭 이벤트
브라우저 API
React Hook

 

정리

기본은 서버 컴포넌트
필요할 때만 use client

이 Next.js 최신 스타일이다.


 

지금까지 익힌 실무 개념

나는 이미 꽤 많은 핵심 개념을 익혔다.

프로젝트 구조
App Router
layout.tsx
컴포넌트 분리
Tailwind CSS
반응형
map()
find()
Link
동적 라우트
params
notFound()
서버 컴포넌트
클라이언트 컴포넌트

이건 실제 관리자 페이지 실무에서도 정말 많이 쓰이는 개념들이다.


 

현재 관리자 페이지 흐름

/admin
  ↓
대시보드

/admin/ads
  ↓
광고 목록

/admin/ads/1
  ↓
광고 상세

이미:

목록 → 상세

흐름까지 완성했다.


 

다음 단계에서 만들 것

다음에는 아래 기능들을 만들면 좋다.

광고 등록
광고 수정
폼 입력
input 상태 관리
useState
삭제 버튼
모달
API 연결

 

특히 다음 단계부터:

폼 처리
상태 관리
이벤트 처리

가 본격적으로 들어간다.

이 부분부터 React 느낌이 강해진다.


 

지금 가장 중요한 것

지금은:

외우는 것

보다:

"왜 이렇게 구조를 나누는가"

를 이해하는 게 훨씬 중요하다.

 

예:

왜 layout을 쓰는가?
왜 컴포넌트를 분리하는가?
왜 map을 쓰는가?
왜 Link를 쓰는가?

이런 흐름이 이해되면 Next.js 실력이 정말 빨리 는다.


 

추천 공부 방법

1. 화면 먼저 만들기

나처럼 HTML/CSS가 강하면:

UI 먼저

가 훨씬 유리하다.


2. 작은 기능 반복

목록
상세
등록
수정
삭제

이 흐름을 계속 반복하면 React 구조가 몸에 익는다.


3. 직접 수정해보기

예:

컬럼 추가
상태 추가
메뉴 추가
카드 UI 변경

직접 바꿔보는 게 가장 많이 는다.


마지막 정리

지금 나는 단순히 예제를 따라친 수준이 아니라:

실무 관리자 페이지 구조

를 이미 경험하고 있는 단계다.

 

특히:

layout.tsx
컴포넌트 구조
동적 라우트
반응형 관리자 UI

이건 Next.js 실무에서 정말 핵심이다.

지금 흐름 그대로 가면:

실무형 프론트엔드 구조 감각

이 꽤 빠르게 생길 거다!

 

 

 

728x90
저작자표시 (새창열림)

'Web > react' 카테고리의 다른 글

[Next.js] Next.js + TypeScript + Tailwind CSS 관리자 페이지 만들기 2  (0) 2026.05.14
[Next.js] Server vs Client Component 완전 정리  (0) 2026.05.08
[Next.js] 초보의 관리자 페이지 만들기 시작기  (0) 2026.04.28
[Next.js] 프로젝트 시작하기  (0) 2026.04.24
[Next.js] 공부 시작 전, 내 현재 수준과 학습 방향 정리  (0) 2026.04.21

티스토리툴바