티스토리 뷰
몽고 DB를 써도 서버를 올려야 하나 보다. 그럼 그냥 Lambda로 하는게 편할듯 싶긴 하다. 람다를 쓰면 그냥 C#으로 작성하면 더 편하다.
AWS Lambda + DynamoDB로 갈지 AWS Lambda + MongoDB로 갈지만 정하면 되고 그냥 코드는 C#으로 짜자.
이거 보니까 으음 이것만 잘 연결해 주면 C#으로 짜서 MongoDB에 연결하는 거는 별 어려움이 없어 보인다.
C#으로 짤수도 있긴 한데 node.js로 짜면 그냥 쌩 node.js로 짜는 것보다는 express로 짜는게 더 직관적인거 같다. 이번에 써보니까 그렇더라.
그냥 쌩 node.js로 짜는 것보다 express로 짜는게 편하다.
import express, {request, response} from 'express'
import mongoose from 'mongoose'
import dotenv from 'dotenv'
import { Product } from './models/productModel.js'
dotenv.config();
const app = express()
app.use(express.json())
const port = 3000
mongoose.connect(process.env.DATABASE_URL)
.then(() => console.log('Connected to MongoDB Atlas'))
.catch(error => console.log('Error connecting to MongoDB:', error))
app.listen(port, () => console.log(`Node is running on port ${port}`))
app.get('/collection', async (request, response) => {
try {
const collections = await mongoose.connection.db.listCollections().toArray()
const collectionNames = collections.map(collection => collection.name)
response.status(200).json(collectionNames)
} catch (error) {
console.log('Error fetching collections:', error)
response.status(500).json({ message: error.message })
}
})
app.get('/product', async (request, response) => {
try {
const product = await Product.find()
response.status(200).json(product)
}
catch (error) {
console.log(error.message)
response.status(500).json({ message: error.message })
}
})
app.get('/product/:id', async (request, response) => {
try {
const id = request.params.id
const product = await Product.findById(id)
if (!product) return response.status(404).json({ massage: `can not find product by ${id}`})
response.status(200).json(product)
}
catch (error) {
console.log(error.message)
response.status(500).json({ message: error.message })
}
})
app.delete('/product/:id', async (request, response) => {
try {
const id = request.params.id
const product = await Product.findOneAndDelete(id)
if (!product) return response.status(404).json({ massage: `can not find product by ${id}`})
response.status(200).json(product)
}
catch (error) {
console.log(error.message)
response.status(500).json({ message: error.message })
}
})
app.put('/product/:id', async(request, response) => {
try {
const id = request.params.id
const product = await Product.findByIdAndUpdate(id, request.body)
if (!product) return response.status(404).json({ massage: `can not find product by ${id}`})
response.status(200).json(product)
}
catch (error) {
console.log(error.massage)
response.status(500).json({ massage: error.massage })
}
})
app.post('/product', async(request, response) => {
try {
const product = await Product.create(request.body)
response.status(200).json(product)
}
catch (error) {
console.log(error.message)
response.status(500).json({ message: error.message })
}
})
확실히 쌩 node.js로 짜는 것보다 편한거 같다.
using Microsoft.AspNetCore.Mvc;
using MongoDB.Driver;
using System.Collections.Generic;
using System.Threading.Tasks;
[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
private readonly IMongoCollection<Product> _products;
public ProductController(IMongoClient client)
{
var database = client.GetDatabase("YourDatabaseName");
_products = database.GetCollection<Product>("Products");
}
[HttpGet]
public async Task<ActionResult<List<Product>>> Get()
{
var products = await _products.Find(product => true).ToListAsync();
return Ok(products);
}
[HttpGet("{id}")]
public async Task<ActionResult<Product>> Get(string id)
{
var product = await _products.Find<Product>(p => p.Id == id).FirstOrDefaultAsync();
if (product == null)
return NotFound();
return Ok(product);
}
[HttpPost]
public async Task<ActionResult<Product>> Create(Product product)
{
await _products.InsertOneAsync(product);
return CreatedAtAction(nameof(Get), new { id = product.Id }, product);
}
[HttpPut("{id}")]
public async Task<ActionResult> Update(string id, Product product)
{
var result = await _products.ReplaceOneAsync(p => p.Id == id, product);
if (result.MatchedCount == 0)
return NotFound();
return NoContent();
}
[HttpDelete("{id}")]
public async Task<ActionResult> Delete(string id)
{
var result = await _products.DeleteOneAsync(p => p.Id == id);
if (result.DeletedCount == 0)
return NotFound();
return NoContent();
}
}
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
GPT에 같은 코드를 C#으로 짜면 어쩌냐고 물어보니까 이렇게 하라고 주더라.
이거 node.js보다 C#이 더 직관적인거 같긴 하다. 물론 거는 내가 C#사용자 여서 그럴수도 있다.
ASP.NET Core의 주요 응답 메서드
- Ok():
- 상태 코드 200(OK)을 가진 성공적인 응답을 생성합니다. 선택적으로 응답 본문을 제공할 수 있습니다.
- 예: return Ok(product);
- NotFound():
- 상태 코드 404(Not Found)를 가진 응답을 생성합니다. 요청한 리소스를 찾을 수 없을 때 사용됩니다.
- 예: return NotFound();
- Created():
- 상태 코드 201(Created)을 가진 응답을 생성합니다. 새 리소스가 성공적으로 생성되었음을 나타냅니다.
- 예: return CreatedAtAction(nameof(Get), new { id = product.Id }, product);
- BadRequest():
- 상태 코드 400(Bad Request)을 가진 응답을 생성합니다. 클라이언트의 요청이 잘못되었을 때 사용됩니다.
- 예: return BadRequest("Invalid request.");
- NoContent():
- 상태 코드 204(No Content)를 가진 응답을 생성합니다. 요청은 성공했지만 응답 본문이 없는 경우 사용됩니다.
- 예: return NoContent();
- StatusCode(int statusCode):
- 사용자 정의 상태 코드를 가진 응답을 생성할 수 있습니다.
- 예: return StatusCode(418, "I'm a teapot");
GPT가 이런건 미리 다 만들어져 있다고 이야기 해준다. 요거 읽어보니까 Post를 했을때 200이 아니라 201을 반환해야 하는거 같다.
https://aigoia.tistory.com/search/DynamoDB
Goetita
aigoia.tistory.com
예전에 코드를 보고 있는데 확실히 자바스크립트로 쌩으로 짜는 것보다. mongoose와 express를 쓰는게 더 직관적인거 같다. 그리고 다시 보니까 왠지 MongoDB가 좀더 직관적인거 같기도 하고 아리송송하다. 이게 내가 할수 있다가 아니라 그래서 가르쳐서 넘겨 줄수 있냐가 관건이기 때문이다.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Lambda.Core;
using Amazon.Lambda.APIGatewayEvents;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace HelloWorld
{
public class Function
{
static HttpClient Client => new();
static async Task<string> GetCallingIp()
{
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Add("User-Agent", "AWS Lambda .Net Client");
var massage = await Client.GetStringAsync("http://checkip.amazonaws.com/").ConfigureAwait(continueOnCapturedContext:false);
return massage.Replace("\n","");
}
public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest eventPayload, ILambdaContext context)
{
if (string.IsNullOrEmpty(eventPayload.Body))
{
return new APIGatewayProxyResponse
{
Body = "Invalid request: Body is null or empty",
StatusCode = 400,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
try
{
var eventToJob = JsonSerializer.Deserialize<Job>(eventPayload.Body);
if (string.IsNullOrEmpty(eventToJob.Title))
{
return new APIGatewayProxyResponse
{
Body = "Invalid request: Deserialize error",
StatusCode = 500,
Headers = new Dictionary<string, string> { { "Content-Type", "text/plain" } }
};
}
if (eventPayload.RequestContext.HttpMethod.ToUpper() == "GET")
{
var dynamoContext = new DynamoDBContext(new AmazonDynamoDBClient());
var jobContext = await dynamoContext.LoadAsync<Job>(eventToJob.Title);
var location = await GetCallingIp();
var body = new Dictionary<string, string>
{
{ "Job", jobContext.Title},
{ "Job description", jobContext.Description}
};
return new APIGatewayProxyResponse
{
Body = JsonSerializer.Serialize(body),
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
return new APIGatewayProxyResponse
{
Body = $"Error occurred: POST is not made yet",
StatusCode = 500,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
catch (Exception exception)
{
return new APIGatewayProxyResponse
{
Body = $"Error occurred: {exception.Message}",
StatusCode = 500,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
}
}
public class Job
{
[DynamoDBHashKey]
public string Title { get; set; }
public string Description { get; set; }
public Job() { }
}
와 전에 짠 코드 보고 있는데 이거랑 비교해 보니 개어렵게 짰다. 이게 프레임 워크 없이 쌩 날로 짜면 이렇구나. 프레임워크를 쓰기는 써야 하는거 같다. 챗GPT도 모르고 강의도 없을때라 공식문서 보면서 짲었던 기억이난다.
C#을 쓰면 ASP net core를 쓰긴 써야 겠구나.
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Add DynamoDB client
builder.Services.AddSingleton<IAmazonDynamoDB>(sp =>
{
var config = builder.Configuration.GetSection("AWS");
return new AmazonDynamoDBClient(
config["AccessKeyId"],
config["SecretAccessKey"],
Amazon.RegionEndpoint.GetBySystemName(config["Region"]));
});
builder.Services.AddScoped<IDynamoDBContext, DynamoDBContext>();
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseAuthorization();
app.MapControllers();
app.Run();
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Amazon.DynamoDBv2.DataModel;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.Text.Json;
namespace MyWebApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class JobsController : ControllerBase
{
private readonly IDynamoDBContext _dynamoDbContext;
private readonly ILogger<JobsController> _logger;
public JobsController(IDynamoDBContext dynamoDbContext, ILogger<JobsController> logger)
{
_dynamoDbContext = dynamoDbContext;
_logger = logger;
}
// GET api/jobs/{title}
[HttpGet("{title}")]
public async Task<ActionResult<Job>> Get(string title)
{
if (string.IsNullOrEmpty(title))
{
return BadRequest("Invalid request: Title is null or empty");
}
try
{
var job = await _dynamoDbContext.LoadAsync<Job>(title);
if (job == null)
{
return NotFound($"Job with title {title} not found");
}
return Ok(job);
}
catch (System.Exception ex)
{
_logger.LogError(ex, "Error occurred while fetching job");
return StatusCode(500, $"Internal server error: {ex.Message}");
}
}
// POST api/jobs
[HttpPost]
public async Task<ActionResult<Job>> Post([FromBody] Job job)
{
if (job == null || string.IsNullOrEmpty(job.Title))
{
return BadRequest("Invalid request: Job or Title is null or empty");
}
try
{
await _dynamoDbContext.SaveAsync(job);
return CreatedAtAction(nameof(Get), new { title = job.Title }, job);
}
catch (System.Exception ex)
{
_logger.LogError(ex, "Error occurred while creating job");
return StatusCode(500, $"Internal server error: {ex.Message}");
}
}
}
[DynamoDBTable("Jobs")]
public class Job
{
[DynamoDBHashKey]
public string Title { get; set; }
public string Description { get; set; }
public Job() { }
}
}
GPT가 앞으로 이렇게 짜라고 알려주었다. 보니까 프레임 워크를 쓰지 않는 코드는 말그대로 빈 편지지 json에다가 기록을 해서 보내는 거고 ASP는 확실히 한번 더 추상화가 된거 같다.
일단은 그냥 진행하자.
'학습 > AWS' 카테고리의 다른 글
AWS EC2 서버 SSH로 접속하기 (0) | 2025.03.17 |
---|---|
공부는 CRUD만 하자 (2) | 2024.09.13 |
자유자제로 다룰수 없으면 아는게 아니다 (0) | 2024.09.13 |
몽고 DB 후반전 (0) | 2024.09.12 |
더 짧은 이걸로 해야 겠다 (0) | 2024.09.12 |