To create a Node.js REST API that interacts with a PostgreSQL database, you'll need to follow these steps:

1. Set up the project structure and install dependencies
2. Configure the PostgreSQL database connection
3. Create the book model
4. Implement the controller functions for handling requests
5. Set up routes and authentication middleware
6. Start the server

Here's an example implementation of each step:

### 1. Set up the project structure and install dependencies

Create a new directory for your project and initialize it with `npm init`. Then, install the necessary dependencies:

```bash
npm install express pg sequelize body-parser jsonwebtoken bcryptjs dotenv
```

Your project should have the following structure:

```
.
├── config/
│   └── db.config.js
├── controllers/
│   └── book.controller.js
├── models/
│   ├── index.js
│   └── book.model.js
├── routes/
│   ├── auth.routes.js
│   └── book.routes.js
├── middlewares/
│   └── auth.middleware.js
├── .env
└── server.js
```

### 2. Configure the PostgreSQL database connection

In the `.env` file, add your PostgreSQL credentials:

```
DB_USER=your_username
DB_PASSWORD=your_password
DB_NAME=your_database_name
DB_HOST=localhost
DB_PORT=5432
JWT_SECRET=your_jwt_secret
```

In `config/db.config.js`, set up the Sequelize configuration:

```javascript
const dotenv = require('dotenv');
dotenv.config();

module.exports = {
  username: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  dialect: 'postgres',
};
```

### 3. Create the book model

In `models/book.model.js`, define the Book model:

```javascript
module.exports = (sequelize, DataTypes) => {
  const Book = sequelize.define('Book', {
    title: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    author: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    description: {
      type: DataTypes.TEXT,
    },
    publishedYear: {
      type: DataTypes.INTEGER,
    },
  });

  return Book;
};
```

In `models/index.js`, set up Sequelize and import the models:

```javascript
const Sequelize = require('sequelize');
const config = require('../config/db.config');

const sequelize = new Sequelize(config.database, config.username, config.password, config);

const db = {};

db.Sequelize = Sequelize;
db.sequelize = sequelize;

db.books = require('./book.model')(sequelize, Sequelize);

module.exports = db;
```

### 4. Implement the controller functions for handling requests

In `controllers/book.controller.js`, implement the CRUD operations:

```javascript
const db = require('../models');
const Book = db.books;

exports.create = async (req, res) => {
  try {
    const book = await Book.create(req.body);
    res.status(201).send(book);
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

exports.findAll = async (req, res) => {
  try {
    const books = await Book.findAll();
    res.send(books);
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

exports.findOne = async (req, res) => {
  try {
    const book = await Book.findByPk(req.params.id);
    if (!book) {
      return res.status(404).send({ message: 'Book not found' });
    }
    res.send(book);
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

exports.update = async (req, res) => {
  try {
    const book = await Book.findByPk(req.params.id);
    if (!book) {
      return res.status(404).send({ message: 'Book not found' });
    }

    await book.update(req.body);
    res.send(book);
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

exports.delete = async (req, res) => {
  try {
    const book = await Book.findByPk(req.params.id);
    if (!book) {
      return res.status(404).send({ message: 'Book not found' });
    }

    await book.destroy();
    res.send({ message: 'Book deleted successfully' });
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};
```

### 5. Set up routes and authentication middleware

In `middlewares/auth.middleware.js`, implement the JWT authentication middleware:

```javascript
const jwt = require('jsonwebtoken');
const dotenv = require('dotenv');

dotenv.config();

module.exports = (req, res, next) => {
  const token = req.header('x-auth-token');
  if (!token) {
    return res.status(401).send({ message: 'Access denied. No token provided.' });
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    res.status(400).send({ message: 'Invalid token.' });
  }
};
```

In `routes/book.routes.js`, set up the routes for books:

```javascript
const express = require('express');
const router = express.Router();
const authMiddleware = require('../middlewares/auth.middleware');
const bookController = require('../controllers/book.controller');

router.post('/', authMiddleware, bookController.create);
router.get('/', authMiddleware, bookController.findAll);
router.get('/:id', authMiddleware, bookController.findOne);
router.put('/:id', authMiddleware, bookController.update);
router.delete('/:id', authMiddleware, bookController.delete);

module.exports = router;
```

### 6. Start the server

In `server.js`, set up the Express app and start the server:

```javascript
const express = require('express');
const bodyParser = require('body-parser');
const bookRoutes = require('./routes/book.routes');
const db = require('./models');

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

db.sequelize.sync();

app.use('/api/books', bookRoutes);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
```

Now you have a Node.js REST API that interacts with a PostgreSQL database to manage a collection of books. You can use tools like Postman or curl to test your endpoints.
PostgreSQL 데이터베이스와 상호 작용하는 Node.js REST API를 생성하려면 다음 단계를 따라야 합니다.

1. 프로젝트 구조 설정 및 종속성 설치
2. PostgreSQL 데이터베이스 연결 구성
3. 도서 모델 생성
4. 요청 처리를 위한 컨트롤러 기능 구현
5. 경로 및 인증 미들웨어 설정
6. 서버 시작

다음은 각 단계의 구현 예제입니다.

### 1. 프로젝트 구조 설정 및 종속성 설치

프로젝트를 위한 새 디렉터리를 생성하고 `npm init`으로 초기화합니다. 그런 다음 필요한 의존성을 설치합니다:

```bash
npm install express pg sequelize body-parser jsonwebtoken bcryptjs dotenv
```

프로젝트의 구조는 다음과 같아야 합니다:

```
.
├── config/
│   └── db.config.js
├── controllers/
│   └── book.controller.js
├── models/
│   ├── index.js
│   └── book.model.js
├── routes/
│   ├── auth.routes.js
│   └── book.routes.js
├── middlewares/
│   └── auth.middleware.js
├── .env
└── server.js
```

### 2. PostgreSQL 데이터베이스 연결 구성

`.env` 파일에 PostgreSQL 자격 증명을 추가합니다:

```
DB_USER=your_username
DB_PASSWORD=your_password
DB_NAME=your_database_name
DB_HOST=localhost
DB_PORT=5432
JWT_SECRET=your_jwt_secret
```

`config/db.config.js`에서 시퀄라이즈 구성을 설정합니다:

```javascript
const dotenv = require('dotenv');
dotenv.config();

module.exports = {
  username: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  dialect: 'postgres',
};
```

### 3. 도서 모델 생성

`models/book.model.js`에서 도서 모델을 정의합니다:

```javascript
module.exports = (sequelize, DataTypes) => {
  const Book = sequelize.define('Book', {
    title: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    author: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    description: {
      type: DataTypes.TEXT,
    },
    publishedYear: {
      type: DataTypes.INTEGER,
    },
  });

  return Book;
};
```

`models/index.js`에서 Sequelize를 설정하고 모델을 가져옵니다:

```javascript
const Sequelize = require('sequelize');
const config = require('../config/db.config');

const sequelize = new Sequelize(config.database, config.username, config.password, config);

const db = {};

db.Sequelize = Sequelize;
db.sequelize = sequelize;

db.books = require('./book.model')(sequelize, Sequelize);

module.exports = db;
```

### 4. 요청 처리를 위한 컨트롤러 함수 구현

`controllers/book.controller.js`에서 CRUD 작업을 구현합니다:

```javascript
const db = require('../models');
const Book = db.books;

exports.create = async (req, res) => {
  try {
    const book = await Book.create(req.body);
    res.status(201).send(book);
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

exports.findAll = async (req, res) => {
  try {
    const books = await Book.findAll();
    res.send(books);
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

exports.findOne = async (req, res) => {
  try {
    const book = await Book.findByPk(req.params.id);
    if (!book) {
      return res.status(404).send({ message: 'Book not found' });
    }
    res.send(book);
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

exports.update = async (req, res) => {
  try {
    const book = await Book.findByPk(req.params.id);
    if (!book) {
      return res.status(404).send({ message: 'Book not found' });
    }

    await book.update(req.body);
    res.send(book);
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};

exports.delete = async (req, res) => {
  try {
    const book = await Book.findByPk(req.params.id);
    if (!book) {
      return res.status(404).send({ message: 'Book not found' });
    }

    await book.destroy();
    res.send({ message: 'Book deleted successfully' });
  } catch (error) {
    res.status(500).send({ message: error.message });
  }
};
```

### 5. 경로 및 인증 미들웨어 설정

`middlewares/auth.middleware.js`에서 JWT 인증 미들웨어를 구현합니다:

```javascript
const jwt = require('jsonwebtoken');
const dotenv = require('dotenv');

dotenv.config();

module.exports = (req, res, next) => {
  const token = req.header('x-auth-token');
  if (!token) {
    return res.status(401).send({ message: 'Access denied. No token provided.' });
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (error) {
    res.status(400).send({ message: 'Invalid token.' });
  }
};
```

`routes/book.routes.js`에서 책에 대한 경로를 설정합니다:

```javascript
const express = require('express');
const router = express.Router();
const authMiddleware = require('../middlewares/auth.middleware');
const bookController = require('../controllers/book.controller');

router.post('/', authMiddleware, bookController.create);
router.get('/', authMiddleware, bookController.findAll);
router.get('/:id', authMiddleware, bookController.findOne);
router.put('/:id', authMiddleware, bookController.update);
router.delete('/:id', authMiddleware, bookController.delete);

module.exports = router;
```

### 6. 서버 시작

`server.js`에서 Express 앱을 설정하고 서버를 시작합니다:

```javascript
const express = require('express');
const bodyParser = require('body-parser');
const bookRoutes = require('./routes/book.routes');
const db = require('./models');

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

db.sequelize.sync();

app.use('/api/books', bookRoutes);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
```

이제 책 컬렉션을 관리하기 위해 PostgreSQL 데이터베이스와 상호 작용하는 Node.js REST API가 생겼습니다. Postman이나 curl과 같은 도구를 사용하여 엔드포인트를 테스트할 수 있습니다.