我国力争 2030 年饲草总产量达 1.3 亿吨
Readhub
农业农村部近日印发《全国畜牧兽医行业发展「十五五」规划》,提出包含肉类总产量、禽蛋产量、奶类产量等在内的 15 项定量目标,明确 2030 年我国饲草总产量将达到 1.3 亿吨。
Балл: 57.22Уверенность: 54%
ПодробнееЗагружаем каталог…
НАВИГАТОР ПО ВОЗМОЖНОСТЯМ ИИ
Найдите свой ИИ-инструмент. Бесплатный доступ, пробные периоды и кредиты — в одном месте.
Readhub
农业农村部近日印发《全国畜牧兽医行业发展「十五五」规划》,提出包含肉类总产量、禽蛋产量、奶类产量等在内的 15 项定量目标,明确 2030 年我国饲草总产量将达到 1.3 亿吨。
Балл: 57.22Уверенность: 54%
Подробнееvelog
How to Recover Lost or Misappropriated Funds: A Complete Guide Losing money because of fraud, unauthorized transactions, financial scams, or the misappropriation of funds can be a stressful experience. However, taking the right steps quickly can improve your ability to protect your accounts, document what happened, and explore available recovery options. Whether the loss involves a bank transaction, investment scam, business funds, or another type of financial dispute, understanding the fund recovery process is important. This guide explains what to do after losing money, how lost funds may be recovered, and what steps can help protect you from further financial loss. If you need other information just contact us: Visit Now my websites: https://dqtlx.com Email : info@dqtlx.com How Can Lost or Misappropriated Funds Be Recovered? The first step in recovering lost or misappropriated funds is identifying how the money was lost. The appropriate recovery process can vary depending on whether the loss resulted from fraud, an unauthorized transaction, an accounting error, a financial scam, or another form of misconduct. Start by gathering all available evidence. Keep bank statements, transaction records, invoices, contracts, emails, messages, receipts, and other documents connected to the incident. A complete record can make it easier to explain the situation to your bank, financial institution, authorities, or legal representative. Next, notify the relevant financial institution as soon as possible. If the loss involves an unauthorized transaction, the bank or payment provider may have a specific process for investigating and disputing the transaction. You may also need to report suspected fraud to the appropriate authorities or regulatory organizations. For significant or disputed losses, obtaining advice from a qualified legal professional may help you understand the recovery options available under applicable laws. Acting promptly, preserving evidence, and following the appropriate reporting procedures are important parts of recovering potentially lost funds. What Steps Can Help With Recovering Lost Funds? If you discover that money has been lost or transferred without authorization, taking immediate action can help protect your remaining funds and preserve important evidence. Gather All Relevant Evidence Collect bank statements, payment confirmations, transaction IDs, emails, text messages, contracts, receipts, and other records related to the loss. Avoid deleting communications with the person or organization involved. Contact Your Financial Institution Notify your bank, credit card provider, payment platform, or other relevant financial institution immediately. Explain what happened and ask about their dispute, fraud-reporting, or transaction-reversal procedures. Secure Your Accounts If you suspect that your account information has been compromised, change relevant passwords and enable additional security measures where available. Review recent transactions for other unauthorized activity. Report Suspected Fraud Depending on your location and the nature of the incident, you may need to report the matter to law enforcement, a consumer protection agency, or a financial regulator. Seek Professional Advice When Necessary For substantial losses, complicated financial disputes, or suspected misappropriation, consider consulting an appropriately qualified legal or financial professional. They can help you understand the available options and documentation requirements. Keep Track of Every Report Maintain a record of complaint numbers, correspondence, dates, names of representatives, and actions taken. Organized records can make follow-ups much easier. How Does the Funds Recovery Process Work? The funds recovery process generally depends on how the money was lost and which institution or party handled the transaction. The process often begins by documenting the incident and notifying the relevant financial institution. Banks and payment providers may have internal procedures for investigating disputed or unauthorized transactions. If the initial complaint does not resolve the matter, you may be able to escalate it through the institution's formal complaint process. Depending on the jurisdiction, additional options may include regulatory complaints, consumer protection agencies, mediation, arbitration, or legal proceedings. For cases involving fraud or criminal activity, reporting the incident to law enforcement may also be appropriate. Authorities can determine whether an investigation is warranted. In more complicated cases, a qualified professional may help assess the evidence and identify appropriate legal or financial recovery options. It is important to be cautious when choosing a recovery service. Some scammers specifically target people who have already lost money by promising guaranteed recovery in exchange for upfront fees or sensitive information. What Should You Do After Losing Money to a Financial Scam? If you have lost money to a financial scam, acting quickly is important. Although recovery is not guaranteed, several steps can help limit further damage and preserve potential recovery options. If you need other information just contact us: Visit Now my websites: https://dqtlx.com Email : info@dqtlx.com Contact Your Bank or Payment Provider Immediately Tell the financial institution that you believe you have been the victim of fraud. Provide transaction details and ask whether the payment can be stopped, reversed, or disputed. The available options can depend on the payment method, the timing of the transaction, and the applicable rules. Preserve Evidence Save emails, messages, screenshots, payment confirmations, website addresses, account information, and other communications connected to the scam. Do not alter or delete potentially relevant evidence. Report the Scam Report the incident to the appropriate law enforcement agency, financial regulator, or consumer protection organization in your jurisdiction. Reporting can help authorities identify patterns of fraudulent activity. Protect Your Personal Information If you shared passwords, identification documents, banking information, or other sensitive information with scammers, take steps to secure your accounts. Change compromised passwords and monitor your financial accounts for unusual activity. Be Careful of Follow-Up Recovery Scams After a financial scam, you may be contacted by someone claiming they can recover your money for a fee. Be cautious about unsolicited recovery offers, particularly promises of guaranteed results or requests for upfront payments or sensitive account information. Can Misappropriated Business Funds Be Recovered? Businesses may face fund misappropriation when money is improperly transferred, diverted, or used without authorization. The appropriate response depends on the circumstances and applicable laws. Businesses should preserve financial records, accounting documents, transaction histories, contracts, internal communications, and other relevant evidence. Access to financial systems should also be reviewed and secured where necessary. The business may need to notify its bank, payment provider, auditors, insurers, regulators, or law enforcement, depending on the circumstances. For significant losses, obtaining advice from a qualified legal professional can help determine what recovery or enforcement options may be available. Taking prompt action can also help prevent additional unauthorized transactions while the matter is being investigated. How Can You Protect Yourself From Future Financial Scams? Preventing future losses is an important part of financial security. Consider using strong, unique passwords and enabling multi-factor authentication on financial and email accounts. Regularly review bank and credit card statements and investigate unfamiliar transactions promptly. Be cautious about unexpected investment opportunities, urgent payment requests, and messages asking for passwords, verification codes, or financial information. For businesses, internal controls such as approval procedures, transaction limits, account monitoring, and regular financial reviews can help reduce the risk of unauthorized use of funds. Final Thoughts Recovering lost or misappropriated funds can be complicated, and the available options depend on how the loss occurred, how quickly it was reported, and the laws and procedures that apply. The most important steps are to act promptly, document the incident, notify the relevant financial institution, secure your accounts, and report suspected fraud to the appropriate authorities. For complex or high-value disputes, professional legal or financial advice may also be appropriate. Most importantly, be cautious about anyone who promises guaranteed recovery of your money. Legitimate recovery processes rarely depend on unrealistic promises, and scammers may target victims again after an initial financial loss.
Балл: 54.4Уверенность: 49%
Подробнееvelog
Spring / JPA TIL 1. 오류 해결 Memo 생성자 오류 RequestDto 를 받는 생성자가 없어서 발생. public Memo(RequestDto requestDto) { this.title = requestDto.getTitle(); this.contents = requestDto.getContents(); } IntelliJ: Alt + Insert → Constructor Ctrl + Alt + L → 코드 정렬 Ctrl + Shift + F → 프로젝트 전체 검색 Ctrl + F → 현재 파일 검색 POST 404 오류 Controller와 요청 URL이 달라서 발생. Controller: POST /api/memo 요청: POST /api/memos → API 요청 경로와 Controller의 매핑 경로를 동일하게 맞춰야 함. 2. JDBC JDBC는 Java에서 데이터베이스와 통신하기 위한 표준 API. Java → JDBC → DB Driver → Database 직접 SQL을 작성하고 Connection, Statement, ResultSet 등을 관리해야 함. 3. 3 Layer Architecture Controller → Service → Repository → Database Controller : HTTP 요청/응답 담당 Service : 비즈니스 로직 담당 Repository : DB 접근 담당 4. IoC / DI / Bean IoC 객체의 생성과 관리에 대한 제어권을 개발자가 아닌 Spring이 관리하는 것 . DI 필요한 객체를 직접 생성하지 않고 외부(Spring)에서 주입받는 것 . public MemoService(MemoRepository memoRepository) { this.memoRepository = memoRepository; } 생성자 주입을 주로 사용한다. Bean Spring Container가 생성하고 관리하는 객체. Spring Container → Bean 생성/관리 → 필요한 곳에 DI 5. ORM / JPA ORM Java 객체와 관계형 데이터베이스를 매핑하는 기술. JPA Java ORM을 위한 표준 명세 . Hibernate JPA를 구현한 대표적인 구현체. Spring Data JPA → JPA → Hibernate → JDBC → Database 6. Entity DB 테이블과 매핑되는 Java 객체. @Entity public class Memo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String title; private String contents; } @Entity → Entity 지정 @Id → PK 지정 @GeneratedValue → ID 자동 생성 DB Row 하나 ↔ Entity 객체 하나 로 이해하면 됨. 7. 영속성 컨텍스트 JPA가 Entity를 관리하는 논리적인 공간. EntityManager → Persistence Context → Entity 관리 주요 기능: 1차 캐시 Dirty Checking Entity 생명주기 관리 Entity 상태 비영속 → 영속 → 준영속 ↘ 삭제 persist() → 영속 detach() → 준영속 clear() → 영속성 컨텍스트 비우기 remove() → 삭제 merge() → 준영속 Entity를 병합 8. Transaction DB 작업을 하나의 작업 단위로 묶는 것. Transaction 시작 → SQL 작업 → 성공 → COMMIT → 실패 → ROLLBACK COMMIT : 변경사항 확정 ROLLBACK : 변경사항 취소 JPA에서는 Transaction 안에서 Entity를 변경하면 Dirty Checking 을 통해 변경사항을 감지하고 DB에 반영할 수 있다. 9. JPA Auditing Entity의 생성/수정 시간을 자동으로 관리하는 기능. @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime modifiedAt; 10. Query Method Repository 메서드 이름을 기반으로 쿼리를 생성하는 기능. List<Memo> findByTitle(String title); → title 조건으로 조회하는 쿼리가 생성됨. findByTitle findByTitleAndContents findByTitleContaining 등의 규칙을 사용할 수 있다. 11. Java Generics 클래스나 메서드에서 사용할 타입을 지정하는 기능. List<String> names; JPA Repository에서도 사용된다. JpaRepository<Memo, Long> Memo → 관리할 Entity 타입 Long → Entity의 ID 타입 12. 핵심 흐름 Client ↓ Controller ↓ Service ↓ Repository ↓ Spring Data JPA ↓ JPA / Hibernate ↓ JDBC ↓ Database Spring Container → Bean 관리 → DI → Controller / Service / Repository에 객체 주입 Entity → Persistence Context에서 관리 → Dirty Checking → Transaction Commit → DB 반영 한 줄 회고 오늘은 Spring의 기본 구조부터 JPA의 영속성 컨텍스트와 Transaction까지 전체적인 흐름을 연결해서 이해할 수 있었고, 아직 헷갈리는 JPA 동작 원리는 직접 CRUD를 구현하며 더 익혀봐야겠다.
velog
Buy Old Gmail Accounts Buy Are you exploring the digital landscape for a strategic advantage? If so, consider the potential of old Gmail accounts. They may seem like relics from a bygone era, yet they offer unique benefits that modern accounts simply can’t match. As businesses strive to build trust and credibility online, many are turning to these aged accounts as an essential tool in their arsenal. Whether you’re looking to enhance your marketing strategies or protect sensitive information, buying old Gmail accounts could be your next smart move. Dive into this insightful guide and discover why acquiring these vintage assets is becoming increasingly popular among savvy businesses today 👉💪📩📢🔗🤳📶💼➤⚡️🕐 Instant Reply Guaranteed — Message now for quick assistance. 👉💪📩📢🔗🤳📶💼➤Telegram:@getpvasmm 👉💪📩📢🔗🤳📶💼➤WhatsApp: + 1 (830) 739-8217 👉💪📩📢🔗🤳📶💼➤Telegram:@getpvasmm 👉💪📩📢🔗🤳📶💼➤Discord: getpvasmm VISIT OUR SITE: https://getpvasmm.com/product/buy-old-gmail-accounts/ Why people groups buy old Gmail accounts more than modern accounts? Many individuals and organizations gravitate toward Buy old Gmail accounts for their established reputation. These accounts often come with a history that can enhance credibility in online interactions. With age comes trust. Older accounts are less likely to trigger spam filters, making them invaluable for marketing campaigns or important Getpvasmm.com communications. Users feel more secure when engaging with an account that has been around for years. Additionally, seasoned Gmail accounts typically possess higher domain authority. This characteristic can significantly improve email deliverability rates and the success of outreach efforts. For businesses aiming to build relationships quickly, leveraging these aged accounts is a strategic choice. They allow companies to connect authentically while minimizing the risk associated with newer, less-trusted profiles. Investing in Buy old Gmail accounts provides a unique edge—one that modern alternatives cannot replicate easily. Why old Gmail accounts are tallied as culminate for businesses? Buy Old Gmail accounts carry a certain prestige that modern accounts simply cannot match. These aged accounts often have established reputations, making them more trustworthy in the eyes of clients and partners. When businesses utilize older Gmail accounts, they benefit from Getpvasmm.com an already developed history. This can enhance credibility during communications and transactions. Additionally, old accounts are less likely to be flagged for spam activity. Since they’ve been active for a longer time, they come with a level of reliability that newer accounts may lack. Furthermore, many platforms recognize these older profiles as legitimate. This recognition allows businesses to navigate various online landscapes with ease. For companies looking to build relationships or expand their market presence quickly, investing in old Gmail accounts makes strategic sense. Their inherent value lies not just in age but also in the trust they inspire across digital platforms. 👉💪📩📢🔗🤳📶💼➤⚡️🕐 Instant Reply Guaranteed — Message now for quick assistance. 👉💪📩📢🔗🤳📶💼➤Telegram:@getpvasmm 👉💪📩📢🔗🤳📶💼➤WhatsApp: + 1 (830) 739-8217 👉💪📩📢🔗🤳📶💼➤Telegram:@getpvasmm 👉💪📩📢🔗🤳📶💼➤Discord: getpvasmm VISIT OUR SITE: https://getpvasmm.com/product/buy-old-gmail-accounts/ What are the best hones for helpful administration of Gmail accounts? Managing Buy Gmail accounts effectively requires a blend of organization and strategy. First, utilizing labels can help categorize emails by projects or priorities. This makes it easier to locate important messages quickly. Regularly cleaning your inbox is another essential practice. Archiving old emails keeps the inbox clutter-free while still retaining access to previous communications when needed. Automation tools like filters save time by sorting incoming messages automatically. They can direct specific emails straight to designated folders based on criteria you set, enhancing efficiency. Using two-factor authentication adds an extra layer of security, protecting sensitive information from unauthorized access. It’s crucial for safeguarding business communications. Regularly updating passwords ensures account safety as well. Getpvasmm Strong passwords combined with a secure management system reduce risks significantly and contribute to smoother administration of multiple accounts. Why businesses select to buy aged Gmail accounts? Businesses often prefer aged Gmail accounts due to their established credibility. An older account can present a trustworthy image to clients and partners, which is crucial for building relationships. Another factor is the lower risk of getting flagged as spam. New accounts may trigger security algorithms more readily, while older ones have a proven history of legitimate usage. This reliability facilitates smoother communication. Additionally, aged accounts come with access to features that newer accounts may lack at the outset. Features like higher storage limits or advanced settings can enhance workflow efficiency.Many companies also appreciate the chance to acquire verified email addresses that are less likely to face restrictions in various platforms and services. This helps streamline operations across multiple channels without unnecessary interruptions. 👉💪📩📢🔗🤳📶💼➤⚡️🕐 Instant Reply Guaranteed — Message now for quick assistance. 👉💪📩📢🔗🤳📶💼➤Telegram:@getpvasmm 👉💪📩📢🔗🤳📶💼➤WhatsApp: + 1 (830) 739-8217 👉💪📩📢🔗🤳📶💼➤Telegram:@getpvasmm 👉💪📩📢🔗🤳📶💼➤Discord: getpvasmm VISIT OUR SITE: https://getpvasmm.com/product/buy-old-gmail-accounts/ How can old Gmail accounts ensure client data and delicate data? Buy Old Gmail accounts often come with established trust and credibility. They have a history that can provide a sense of reliability for clients. A well-aged account generally has fewer spam filters, ensuring smoother communication. Security is another significant factor. Older accounts usually have robust security measures in place, like two-factor authentication, which helps protect sensitive information. This added layer keeps client data safer from breaches and unauthorized access. Moreover, seasoned accounts typically set up better recovery options. If an issue arises, accessing the account becomes easier due to prior recovery settings and linked devices.Clients also feel more at ease communicating through established addresses rather than newly created ones that might raise suspicion or concern about legitimacy. The longer history means less likelihood of being flagged as spam by other email systems too.Let’s attempt to investigate the genuine esteem of old Gmail accounts- Getpvasmm.comBuy Old Gmail accounts carry a unique value that often goes unnoticed. They possess a history that new accounts simply can’t replicate. This history fosters trust, especially in professional settings.These aged accounts typically boast higher credibility. Businesses appreciate this when reaching out to clients or partners. An established account is seen as more trustworthy than one created yesterday. Why we propose businesses to Buy Old Gmail accounts in bulk? Buy old Gmail accounts in bulk presents significant advantages for businesses. First, these accounts often come with established credibility. They have a history that can enhance trustworthiness when reaching out to clients or partners. Moreover, older accounts are less likely to be flagged as spam. This means higher deliverability rates for emails sent from these addresses, ensuring important communications reach their intended recipients without hassle. Additionally, bulk purchases allow companies to save time and resources. Instead of creating new accounts from Getpvasmm scratch, they can quickly acquire multiple aged profiles ready for use. When scaling operations or launching marketing campaigns, having access numerous stable email addresses streamlines processes. It provides flexibility in managing outreach and communication strategies effectively without the worry of account limitations common with newer profiles. 👉💪📩📢🔗🤳📶💼➤⚡️🕐 Instant Reply Guaranteed — Message now for quick assistance. 👉💪📩📢🔗🤳📶💼➤Telegram:@getpvasmm 👉💪📩📢🔗🤳📶💼➤WhatsApp: + 1 (830) 739-8217 👉💪📩📢🔗🤳📶💼➤Telegram:@getpvasmm 👉💪📩📢🔗🤳📶💼➤Discord: getpvasmm VISIT OUR SITE: https://getpvasmm.com/product/buy-old-gmail-accounts/ What are the best integrative of aged Gmail accounts? Buy Aged Gmail accounts come with several advantageous integrations that can enhance business productivity. One notable integration is the seamless connection to Google Workspace tools, like Docs and Sheets. This allows teams to collaborate effortlessly in real-time. Another strong point is the compatibility with various third-party applications. Many businesses rely on CRM systems or marketing platforms that easily link with Gmail, streamlining communication and data management. The ability to set up custom filters and labels also adds value. Users can organize incoming emails efficiently, ensuring critical messages don’t get lost in clutter. Additionally, older accounts often have a higher trust score among email providers, which may lead to better deliverability rates for campaigns. This reliability makes them an attractive option for businesses aiming for consistent outreach efforts without being flagged as spam. Utilizing aged accounts opens doors to improved analytics too. Businesses can track interactions more effectively over time, refining their strategies accordingly. Buy Old Gmail Accounts Are you exploring the digital landscape for a strategic advantage? Getpvasmm.com If so, consider the potential of old Gmail accounts. They may seem like relics from a bygone era, yet they offer unique benefits that modern accounts simply can’t match. As businesses strive to build trust and credibility online, many are turning to the
velog
JavaScript_Day.9 Day.8의 콜백 함수 다음 단계, Promise와 async/await. "비동기 작업이 끝난 뒤의 결과를 어떻게 받을까"에 대한 두 번째, 세 번째 답을 배운 날이다. 학습 아홉 번째 날이다. 오늘 배운 내용은 이렇다. Promise : 상태(pending, fulfilled, rejected), resolve 와 reject then , catch 와 체이닝 async/await 와 try/catch 콜백, Promise, async/await 비교 이벤트 버블링과 stopPropagation || , && 로 값 고르기 (리액트 문법) map , forEach , filter 1. Promise Promise는 비동기 작업(서버 요청, 타이머 등)의 결과를 나중에 받아서 처리하기 위해 쓰는 객체다. 상태 관리가 명확하고, then 을 이어 붙이는 체이닝 문법 이라 코드 읽기가 편하다. const promise = new Promise((resolve, reject) => { // 성공: resolve(data) → 보통 성공했을 때 호출 // 실패: reject(error) → 실패했을 때 호출 }); new Promise() 의 인자로 비동기 작업을 진행할 콜백 함수를 넣는다. 이 함수를 executor 라고 하고, 매개변수로 받는 resolve 와 reject 가 Promise의 상태를 바꾸는 스위치다. Promise의 세 가지 상태 상태 의미 pending 대기 중. resolve 도 reject 도 아직 호출되지 않은 초기 상태 fulfilled 성공. resolve 가 호출됨 rejected 실패. reject 가 호출됨 pending 상태 확인하기 const promise = new Promise(() => { setTimeout(() => { console.log('hi'); }, 3000); }); console.log(promise); // Promise {<pending>} // (3초 뒤) hi resolve 와 reject 를 받지도, 호출하지도 않았으므로 이 Promise는 영원히 pending 이다. 3초 뒤 hi 가 출력되지만, Promise의 상태는 바뀌지 않는다. resolve로 fulfilled 만들기 const promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('hi'); resolve('안녕'); // 성공 상태로 바꾸고, 결과값으로 '안녕'을 전달 }, 3000); }); setTimeout(() => { console.log(promise); }, 3000); // hi // Promise {<fulfilled>: '안녕'} 두 타이머가 모두 3초지만, Promise 안의 타이머가 먼저 등록되어 있어서 먼저 실행된다. resolve('안녕') 이 호출되어 상태가 fulfilled 가 되고, 그 뒤에 아래 타이머가 상태를 출력한다. reject로 rejected 만들기 const promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('hi'); reject('reject'); // 실패 상태로 바꾸고, 실패 이유로 'reject'를 전달 }, 3000); }); setTimeout(() => { console.log(promise); }, 3000); // hi // Promise {<rejected>: 'reject'} reject("reject") 는 단순히 값을 반환하는 게 아니라, reject 스위치를 작동시키면서 그 값을 실패 이유로 전달 하는 것이다. 이 코드를 콘솔에서 실행하면 Uncaught (in promise) reject 라는 빨간 오류도 함께 뜬다. 실패한 Promise를 catch 로 처리하지 않았기 때문이다. 바로 아래에서 catch 를 다룬다. 조건에 따라 성공과 실패 나누기 const promise = new Promise((resolve, reject) => { setTimeout(() => { const n = 100; if (typeof n === 'number') { resolve(n + 100); // 숫자이면 성공: 200 } else { reject('너 숫자 아닌데'); // 숫자가 아니면 실패 } }, 3000); }); setTimeout(() => { console.log(promise); // Promise {<fulfilled>: 200} console.log(typeof(promise)); // object }, 4000); Promise는 3초가 걸리는 작업 이고, 확인하는 타이머는 4초다. 3초에 resolve(200) 이 호출되어 이미 fulfilled 가 된 뒤에 출력하므로 성공으로 보인다. 만약 확인하는 타이머가 2초였다면 아직 작업이 끝나기 전이라 pending 으로 보였을 것이다. typeof(promise) 는 object 다. Promise도 객체이다. 2. then과 catch 상태를 직접 출력해 보는 방식은 불편하다. 보통은 성공했을 때 실행할 함수 와 실패했을 때 실행할 함수 를 등록한다. then: 성공했을 때 const promise = new Promise((resolve, reject) => { setTimeout(() => { const n = 100; if (typeof n === 'number') { resolve(n + 100); } else { reject('너 숫자 아닌데'); } }, 3000); }); promise.then((value) => { console.log(value); // 3초 뒤 200 }); then 은 "그 후에"라는 뜻이다. Promise가 성공했을 때 실행할 콜백을 등록하는 메소드다. executor에서 resolve 를 호출하면, then 에 전달한 콜백이 실행되면서 resolve 에 넘긴 값이 매개변수 value 로 들어온다. 실행 순서를 정리하면 이렇다. new Promise 가 실행되고 executor가 실행되어 setTimeout 이 예약된다. (3초 대기) promise.then(...) 이 등록되어 resolve 나 reject 를 기다린다. 3초 뒤 setTimeout 이 실행된다. n 이 숫자이므로 resolve(200) 이 호출된다. Promise가 pending 에서 fulfilled 로 바뀐다. 등록해 둔 then() 이 실행되면서 value 로 200을 받아 출력한다. 필기에서는 이 예제의 n 을 '100' (문자열)으로 적어 놓고 결과를 200으로 설명했는데, '100' 은 typeof 가 string 이라서 reject로 가고 then 은 실행되지 않는다. 위 코드는 숫자 100 으로 고쳤다. catch: 실패했을 때 const promise = new Promise((resolve, reject) => { setTimeout(() => { const n = null; if (typeof n === 'number') { resolve(n + 100); } else { reject('너 숫자 아닌데'); } }, 3000); }); promise.catch((error) => { console.log(error); // 3초 뒤 '너 숫자 아닌데' }); catch 는 then 과 반대로 Promise의 reject, 즉 실패값을 받아 실행되는 함수 를 등록한다. reject 에 전달한 값이 error 로 들어온다. null 의 typeof 는 'object' 라서 숫자 조건을 통과하지 못하고 reject로 간다. 3. 체이닝 then 을 이어 붙여서 앞 단계의 결과를 다음 단계로 넘길 수 있다. 각 then 이 return 한 값이 다음 then 의 value 가 된다. const myPromise = new Promise((resolve) => resolve('foo')); myPromise .then((value) => `${value} and bar`) .then((value) => `${value} and bar again`) .then((value) => `${value} and again`) .then((value) => `${value} and again`) .then((value) => { console.log(value); // foo and bar and bar again and again and again }) .catch((err) => { console.error(err); // 중간에 어디서든 실패하면 여기로 }); 위에서 아래로 읽으면 순서대로 일이 진행되는 것이 보인다. 중간 어느 단계에서 문제가 생기든 맨 끝의 catch 하나가 처리한다. Day.8의 콜백 함수로 같은 일을 하려면 콜백 안에 콜백을 계속 넣어야 해서 코드가 안쪽으로 파고드는데, 체이닝은 이를 평평하게 펴 준다. 4. async / await 필기 제목에 별표가 잔뜩 붙은 부분이다. "초 중요!" async 함수는 항상 Promise를 반환한다 async function test() { return { name: 'gildong', id: 'hong' }; } console.log(test()); // Promise {<fulfilled>: {name: 'gildong', id: 'hong'}} 함수 앞에 async 를 붙이면 그 함수의 반환값을 자동으로 Promise로 감싸 준다. 위 함수는 기다릴 코드가 없고 즉시 끝까지 실행되므로, 바로 fulfilled 상태의 Promise가 반환된다. 안에서 시간이 걸리는 경우 async function test() { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ name: 'gildong', id: 'hong' }); }, 2000); }); } console.log(test()); // Promise {<pending>} test().then(result => console.log(result)); // 2초 뒤 {name: 'gildong', id: 'hong'} console.log(test()) 는 Promise 객체 자체 를 출력한 것이다. 내부 Promise가 아직 기다리는 중이라 pending 으로 보인다. .then(result => ...) 의 result 는 resolve 에 넘긴 객체 값 이다. 2초 뒤 fulfilled 가 되면서 값이 나온다. await: 끝날 때까지 기다린다 async function test() { await new Promise((resolve) => setTimeout(resolve, 2000)); // 그냥 2초 동안 기다리는 장치다 return { name: 'aa', age: '123' }; } async function test2() { const data = await test(); // test()가 끝날 때까지 기다렸다가 결과를 data에 대입 console.log(data); } test2(); // 2초 뒤 {name: 'aa', age: '123'} await 는 Promise가 끝날 때까지(결과값을 받을 때까지) 기다린다. setTimeout(resolve, 2000) 은 "2초 뒤에 resolve 를 호출해라"라는 뜻이다. 값 없이 시간만 보내는 용도로 쓸 수 있다. async 가 필요한 경우는 두 가지다. 1 함수 안에서 await 를 쓸 때, 2 함수가 Promise를 반환하게 만들고 싶을 때. await 는 async 함수 안에서만 쓸 수 있다. 그래서 위의 test2 도 async 로 선언했다. function test() { return new Promise((resolve) => { setTimeout(() => { resolve('1초 후 완료'); }, 1000); }); } async function start() { console.log('시작'); const result = await test(); // Promise가 끝날 때까지 기다린 뒤, resolve로 전달된 문자열을 result에 저장 console.log(result); console.log('끝'); } start(); // 시작 // (1초 뒤) 1초 후 완료 // 끝 await 덕분에 비동기 코드인데도 위에서 아래로 순서대로 읽힌다. console.log('끝') 은 await 가 끝나기 전까지 실행되지 않는다. 5. try / catch로 실패 처리 체이닝에서는 성공이면 then , 실패이면 catch 였다. async/await에서는 성공이면 try 안, 실패(reject)이면 catch 안 으로 간다. console.log('홍길동'); function profile(id) { return new Promise((resolve, reject) => { setTimeout(() => { if (id == 1) { resolve({ id: 1, name: '김길동' }); } else { reject('프로필 없음'); } }, 1000); }); } console.log('이길동'); 여기까지의 출력은 홍길동 , 이길동 이다. profile() 을 호출하기 전이라 동기 코드만 실행된다. 체이닝 방식 id 를 100으로 주면 reject 가 호출되므로 catch 가 실행된다. profile(100) .then((user) => console.log(user)) .catch((error) => console.log(error)); // 홍길동 // 이길동 // (1초 뒤) 프로필 없음 profile(1) 이면 then 이 실행되어 {id: 1, name: '김길동'} 이 출력된다. async/await 방식 async function start() { try { // 예외가 날 수도 있는 코드 const pro = await profile(100); console.log(pro); } catch (error) { // 예외가 발생하면 여기서 처리 console.log(error); // 프로필 없음 } } start(); 방식 성공 실패 체이닝 .then() .catch() async/await try { } catch (error) { } await 한 Promise가 reject되면 그 지점에서 예외가 던져지고, catch 블록으로 넘어간다. 6. 콜백, Promise, async/await 비교 같은 일을 세 가지 방식으로 구현해 보면 차이가 보인다. 3초 뒤 'hi' 를 전달받아 출력하는 문제다. 1 콜백 function fun1(callback) { setTimeout(() => { callback('hi'); }, 3000); } fun1((msg) => { console.log(msg); }); 2 Promise function fun2() { return new Promise((resolve, reject) => { setTimeout(() => resolve('hi'), 3000); }); } fun2().then((value) => console.log(value)); 3 async/await async function start() { const msg = await fun2(); console.log(msg); } start(); 방식 결과를 받는 법 특징 콜백 함수를 인자로 넘기고, 완료 시점에 호출 단계가 많아지면 콜백 안에 콜백이 겹친다 Promise then , catch 로 연결 체이닝으로 평평하게 쓸 수 있다 async/await await 로 기다려서 변수에 받음 동기 코드처럼 위에서 아래로 읽힌다 커피 예제(Day.8의 coffee )도 같은 방식으로 바꿔 본다. // Promise를 반환하는 함수 function test() { return new Promise((resolve) => { setTimeout(() => { resolve('latte'); }, 2000); }); } async function coffee() { let coffee2 = await test(); console.log(coffee2); // 2초 뒤 latte } coffee(); 필기의 test 는 async function test() 로 되어 있었는데, 이미 new Promise 를 직접 반환하고 있으므로 async 를 붙이지 않아도 결과가 같다. 위에서는 뺐다. 수업 문제에서 필기에 "내가 푼 것"과 "강사님이 푼 것"을 나란히 적어 놓은 부분이 있다. // 내가 푼 것 const fun1 = new Promise((resolve, reject) => { setTimeout(() => resolve('hi'), 3000); }); fun1.then((value) => console.log(value)); // 강사님이 푼 것 function fun2() { return new Promise((resolve, reject) => { setTimeout(() => resolve('hi'), 3000); }); } 둘 다 hi 가 나오지만 차이가 있다. const fun1 = new Promise(...) 은 변수에 대입하는 순간 작업이 시작 되고, 호출할 때마다 새로 실행되는 것이 아니다. fun2() 처럼 함수로 감싸면 호출하는 시점에 Promise가 새로 만들어져 필요할 때 필요한 만큼 실행할 수 있다. async/await로 바꿀 때도 await fun2() 처럼 함수 호출 형태가 자연스럽다. 7. 이벤트 버블링 <style> #d1 { border: 3px solid black; padding: 20px; } #d1 a { text-decoration: none; border: 3px solid black; } </style> <div id="d1"> <a class="a1" href="#none">태그링크</a> </div> <script> let d1 = document.querySelector('#d1'); let a1 = document.querySelector('.a1'); // div를 클릭하면 테두리 색을 blue로 (고전 이벤트 방식) d1.onclick = function () { this.style.borderColor = 'blue'; }; // a1을 클릭하면 red a1.addEventListener('click', function (e) { e.stopPropagation(); // 전파 막기 this.style.borderColor = 'red'; }); </script> stopPropagation 줄을 지우고 a 를 클릭하면 a 의 테두리는 빨강, 부모 div 의 테두리도 파랑으로 바뀐다. 처음에는 a 만 클릭했는데 왜 부모까지 바뀌는지가 의문이었다. 답은 이벤트 버블링 이다. 자식 요소에서 이벤트가 발생하면 그 이벤트가 부모, 그 위 부모로 거품처럼 올라가며 전달된다. a 는 d1 의 자식이고 d1 에 클릭 이벤트가 걸려 있으므로, a 를 클릭하면 d1 의 onclick 도 함께 실행된다. e.stopPropagation() : 이벤트 전파를 막는다. a 를 클릭해도 부모 d1 의 이벤트가 실행되지 않는다. 반대로 위에서 아래로 내려가는 단계를 캡처링 이라고 한다. 이벤트는 캡처링 → 대상 → 버블링 순서로 흐르는데, 보통 쓰는 것은 버블링이다. Day.8의 To Do List에서 목록 전체( #list )에만 이벤트를 걸어도 안쪽 아이콘 클릭이 처리되었던 이유가 바로 이 버블링 덕분이다. 자식의 이벤트가 부모까지 올라오니까 부모에서 e.target 으로 받을 수 있었다. 8. || 와 && 로 값 고르기 (리액트 문법) || 와 && 는 Day.2에서 조건식에 쓰는 논리 연산자로 배웠다. 리액트에서는 이것을 조건에 따라 값을 고르는 용도 로 쓴다. falsy 값 아래 값들은 조건에서 모두 false로 인식 된다. false 0 "" (빈 문자열) null undefined NaN || 연산자 왼쪽이 true 로 판정되면 → 왼쪽 값 이 반환된다. 왼쪽이 false 로 판정되면 → 오른쪽 값 이 반환된다. const n = null; const m = n || '문자열'; console.log(m); // 문자열 (왼쪽이 falsy → 오른쪽) const n2 = 20; const m2 = n2 || '문자열'; console.log(
velog
Spring MVC부터 SQL/JDBC까지 정리 1. MVC 디자인 패턴 소프트웨어를 Model, View, Controller 로 구분하여 각각의 역할을 분리하는 디자인 패턴이다. Model : 데이터와 비즈니스 로직을 담당하며, 데이터베이스와 연동하여 데이터를 저장하고 조회한다. View : 사용자 인터페이스를 담당하며, 사용자가 보는 화면과 버튼, 폼 등을 구현한다. Controller : Model과 View 사이의 상호작용을 조정한다. 사용자의 입력을 받아 Model에 전달하고, Model의 결과를 바탕으로 View를 업데이트한다. MVC의 장점 코드 재사용성 유지보수성 개발자 간 협업 용이 2. Spring MVC Spring MVC는 Servlet을 기반으로 HTTP 요청을 처리하고, MVC 디자인 패턴을 적용해 요청과 응답을 효율적으로 관리한다. Servlet Java를 사용하여 웹 페이지를 동적으로 생성하는 서버 측 프로그램 또는 사양이다. Servlet 동작 과정 Client(브라우저)에서 HTTP Request 발생 HttpServletRequest , HttpServletResponse 객체 생성 요청에 해당하는 Servlet 탐색 service() 호출 → HTTP Method에 따라 doGet() , doPost() 등 호출 처리 결과를 HttpServletResponse 에 담아 Client에 반환 응답 완료 후 Request / Response 객체 소멸 DispatcherServlet DispatcherServlet 은 요청을 분석하고 적절한 Controller로 요청을 전달한다. 예를 들어 @GetMapping("/api/hello") 요청이 들어오면 해당 요청을 처리할 Controller의 메서드를 찾아 실행한다. 동작 과정 HTTP 요청 분석 Handler Mapping 을 통해 Controller에 요청 전달 Controller에서 처리 후 결과(Model, View) 전달 DispatcherServlet 이 View에 Model을 적용하여 Client에 전달 3. @Controller @Controller 는 관련된 요청을 하나의 Controller에서 관리할 수 있도록 한다. 예를 들어 회원 관리 기능의 로그인, 회원가입, 로그아웃 등을 하나의 Controller에서 관리할 수 있다. @Controller @RequestMapping("/user") public class UserController { @GetMapping("/login") public String login() { // ... } @GetMapping("/logout") public String logout() { // ... } @GetMapping("/signup") public String signup() { // ... } @PostMapping("/signup") public String registerUser(SignupRequestDto requestDto) { // ... } } URL 경로 중복 HTTP Method가 다르면 같은 URL 경로를 사용할 수 있다. @GetMapping("/api/hello") @ResponseBody public String hello() { return "Hello World"; } @PostMapping("/api/hello") @ResponseBody public String post() { return "Hello World2"; } 4. @RequestMapping 공통되는 API 경로를 묶어서 관리할 수 있다. @Controller @RequestMapping("/api") public class HelloController { @GetMapping("/hello") @ResponseBody public String hello() { return "Hello World"; } } 위와 같이 설정하면 실제 요청 경로는 /api/hello 가 된다. 5. 정적 페이지와 동적 페이지 정적(Static) 페이지 이미 완성된 HTML 파일을 그대로 반환하는 페이지다. 예를 들어 http://localhost:8080/hello.html 을 요청하면 Controller를 거치지 않고 정적 리소스를 반환할 수 있다. Redirect @GetMapping("/html/redirect") public String htmlStatic() { return "redirect:/hello.html"; } redirect: 를 사용하면 해당 URL로 다시 요청을 보낸다. 동적 페이지 Controller에서 Model에 데이터를 담고, Template Engine이 HTML에 데이터를 적용하여 동적인 페이지를 생성한다. @GetMapping("/html/dynamic") public String htmlDynamic(Model model) { visitCount++; model.addAttribute("visits", visitCount); return "hello-visit"; } model.addAttribute() 로 전달한 값은 HTML의 ${visits} 와 같은 표현식에 적용된다. 동적 페이지 처리 과정 Controller에서 요청 처리 및 필요한 데이터를 Model에 저장 Template Engine(Thymeleaf)에 View와 Model 전달 Template Engine이 View에 Model을 적용 생성된 HTML을 Client에 전달 대표적인 Template Engine으로 Thymeleaf, Groovy, FreeMarker, JSP 등이 있다. 6. JSON 데이터 반환 서버에서 HTML 전체를 반환하는 대신 필요한 데이터를 JSON 형식으로 반환할 수 있다. String 반환 @GetMapping("/response/json/string") @ResponseBody public String helloStringJson() { return "{\"name\":\"Robbie\",\"age\":95}"; } Java 객체 반환 @GetMapping("/response/json/class") @ResponseBody public Star helloClassJson() { return new Star("Robbie", 95); } Spring은 Java 객체를 JSON으로 변환하여 반환할 수 있다. 7. @RestController @RestController 는 @Controller 와 @ResponseBody 를 함께 사용하는 것과 같다. @RestController public class HelloController { // ... } @ResponseBody 를 사용하면 HTML View가 아닌 데이터를 응답으로 반환한다. 8. Jackson Jackson은 JSON 데이터를 처리하는 라이브러리다. Java Object → JSON JSON → Java Object Spring은 Jackson과 관련된 기능을 제공하여 Java 객체를 JSON으로 변환할 수 있다. @Test @DisplayName("Object To JSON") void test1() throws JsonProcessingException { Star star = new Star("Robbie", 95); ObjectMapper objectMapper = new ObjectMapper(); String json = objectMapper.writeValueAsString(star); System.out.println("json = " + json); } 9. Path Variable과 Request Param 둘 다 HTTP 요청으로 데이터를 전달받는 방법이지만, 데이터가 URL에 표현되는 방식이 다르다. Path Variable URL 경로에 값을 포함하여 전달하는 방식이다. // GET http://localhost:8080/hello/request/star/Robbie/age/95 @GetMapping("/star/{name}/age/{age}") @ResponseBody public String helloRequestPath( @PathVariable String name, @PathVariable int age ) { return String.format( "Hello, @PathVariable.<br> name = %s, age = %d", name, age ); } {name} , {age} 형태로 URL 경로에 변수 지정 @PathVariable 로 해당 값 전달받음 Request Param Query String을 통해 데이터를 전달하는 방식이다. // GET http://localhost:8080/hello/request/form/param?name=Robbie&age=95 @GetMapping("/form/param") @ResponseBody public String helloGetRequestParam( @RequestParam(required = false) String name, int age ) { return String.format( "Hello, @RequestParam.<br> name = %s, age = %d", name, age ); } @RequestParam 생략 가능 required = false 설정 시 해당 값이 없어도 됨 10. HTTP 데이터를 객체로 처리 @ModelAttribute 여러 데이터를 하나씩 @RequestParam 으로 받는 대신 Java 객체로 한 번에 받을 수 있다. // POST http://localhost:8080/hello/request/form/model // Content-Type: application/x-www-form-urlencoded // Body: name=Robbie&age=95 @PostMapping("/form/model") @ResponseBody public String helloRequestBodyForm(@ModelAttribute Star star) { return String.format( "Hello, @ModelAttribute.<br> (name = %s, age = %d)", star.name, star.age ); } Query String에서도 사용할 수 있다. // GET http://localhost:8080/hello/request/form/param/model?name=Robbie&age=95 @GetMapping("/form/param/model") @ResponseBody public String helloRequestParam(@ModelAttribute Star star) { return String.format( "Hello, @ModelAttribute.<br> (name = %s, age = %d)", star.name, star.age ); } @ModelAttribute 는 생략할 수 있다. @RequestBody JSON 형식으로 전달된 HTTP Body를 Java 객체로 받을 때 사용한다. // POST http://localhost:8080/hello/request/form/json // Content-Type: application/json // Body: {"name":"Robbie","age":"95"} @PostMapping("/form/json") @ResponseBody public String helloPostRequestJson(@RequestBody Star star) { return String.format( "Hello, @RequestBody.<br> (name = %s, age = %d)", star.name, star.age ); } 11. CRUD 구현 CRUD는 데이터를 생성(Create), 조회(Read), 수정(Update), 삭제(Delete)하는 기본적인 데이터 처리 방식이다. DTO란? DTO(Data Transfer Object)는 데이터 전송 및 이동을 위해 사용하는 객체다. Client에서 전달받은 데이터를 객체로 처리 서버 계층 간 데이터 이동 Create @PostMapping("/memos") public MemoResponseDto createMemo(@RequestBody MemoRequestDto requestDto) { // RequestDto -> Entity Memo memo = new Memo(requestDto); // Memo Max ID Check Long maxId = memoList.size() > 0 ? Collections.max(memoList.keySet()) + 1 : 1; memo.setId(maxId); // DB 저장 memoList.put(memo.getId(), memo); // Entity -> ResponseDto MemoResponseDto memoResponseDto = new MemoResponseDto(memo); return memoResponseDto; } Read @GetMapping("/memos") public List<MemoResponseDto> getMemos() { List<MemoResponseDto> responseList = memoList.values().stream() .map(MemoResponseDto::new) .toList(); return responseList; } Update @PutMapping("/memos/{id}") public Long updateMemo( @PathVariable Long id, @RequestBody MemoRequestDto requestDto ) { if (memoList.containsKey(id)) { Memo memo = memoList.get(id); memo.update(requestDto); return memo.getId(); } else { throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다."); } } Delete @DeleteMapping("/memos/{id}") public Long deleteMemo(@PathVariable Long id) { if (memoList.containsKey(id)) { memoList.remove(id); return id; } else { throw new IllegalArgumentException("선택한 메모는 존재하지 않습니다."); } } 12. Database Spring에서 데이터를 다루기 위해서는 애플리케이션뿐 아니라 데이터베이스의 기본 구조도 이해해야 한다. DB(Database) : 데이터의 집합 DBMS(Database Management System) : 데이터베이스를 관리하고 운영하는 소프트웨어 RDBMS(Relational DBMS) : 관계형 데이터베이스 관리 시스템 RDBMS는 테이블 을 기본 단위로 데이터를 관리한다. 테이블은 행(row)과 열(column)으로 구성된다. 테이블 간에는 외래키를 통해 관계를 구성할 수 있다. 아이디 이름 전화번호 1 홍길동 010-7777-7777 2 김철수 010-6666-6666 3 이가영 010-8888-8888 13. SQL SQL(Structured Query Language)은 RDBMS에서 데이터를 조작하고 관리하기 위해 사용하는 언어다. DDL DDL(Data Definition Language)은 데이터베이스와 테이블의 구조를 정의하는 언어 CREATE CREATE DATABASE 데이터베이스이름; CREATE TABLE 테이블이름 ( 필드이름1 필드타입1, 필드이름2 필드타입2 ); ALTER ALTER TABLE 테이블이름 ADD 필드이름 필드타입; ALTER TABLE 테이블이름 DROP 필드이름; ALTER TABLE 테이블이름 MODIFY COLUMN 필드이름 필드타입; DROP 데이터베이스 또는 테이블을 삭제한다. DROP DATABASE 데이터베이스이름; DROP TABLE 테이블이름; TRUNCATE 테이블의 데이터를 삭제하고 테이블 구조는 유지한다. TRUNCATE TABLE 테이블이름; DML DML(Data Manipulation Language)은 데이터를 조작하는 언어 INSERT INSERT INTO 테이블이름(필드이름1, 필드이름2, 필드이름3) VALUES(데이터값1, 데이터값2, 데이터값3); SELECT SELECT 필드이름 FROM 테이블이름 WHERE 조건; UPDATE UPDATE 테이블이름 SET 필드이름1 = 데이터값1, 필드이름2 = 데이터값2 WHERE 필드이름 = 데이터값; DELETE DELETE FROM 테이블이름 WHERE 필드이름 = 데이터값; DCL DCL(Data Control Language)은 데이터베이스의 권한을 제어하는 언어 GRANT 사용자 또는 ROLE에 권한을 부여한다. GRANT [객체권한명] (컬럼) ON [객체명] TO { 유저명 | 롤명 | PUBLIC } [WITH GRANT OPTION]; REVOKE 사용자 또는 ROLE에 부여한 권한을 회수한다. REVOKE { 권한명 [, 권한명...] | ALL } ON 객체명 FROM { 유저명 [, 유저명...] | 롤명 | PUBLIC }; 14. JDBC JDBC(Java Database Connectivity)는 Java에서 데이터베이스에 접근할 수 있도록 제공하는 API다. JDBC를 사용하면 애플리케이션의 DB 접근 로직을 특정 DB에 직접 종속시키는 것을 줄일 수 있다. 애플리케이션의 DB 접근 과정 DB 연결(Connection) SQL 요청 결과 응답 예를 들어 MySQL에서 PostgreSQL로 DB를 변경할 경우 DB 연결 및 요청 방식이 달라질 수 있다. JDBC는 이러한 DB 접근을 위한 표준화된 인터페이스를 제공한다. JDBC Template JDBC를 사용할 때 반복되는 작업을 줄이기 위해 Spring에서는 JdbcTemplate 을 제공한다. 커넥션 연결 Statement 준비 및 실행 커넥션 종료 반복 작업을 줄여줌 등의 반복적인 작업을 대신 처리할 수 있다. 마무리 DispatcherServlet 을 중심으로 HTTP 요청이 Controller까지 전달되는 흐름 @RestController , @ResponseBody 를 이용한 JSON 응답 @PathVariable , @RequestParam , @ModelAttribute , @RequestBody 의 차이 CRUD의 기본적인 데이터 처리 방식 DDL / DML / DCL의 역할 JDBC와 JdbcTemplate 의 역할
velog
집에서 직접 개발한 웹 서버를 친구에게 보여주려 하거나, 로컬에서 구동한 게임 서버, SSH 원격 접속, 홈 NAS 등을 외부에 개방할 때 항상 마주치는 필수 관문이 바로 포트 포워딩(Port Forwarding) 이다. 공유기(사설망) 환경에서 왜 외부 접속이 곧바로 불가능한지, 포트 포워딩이 어떤 원리로 외부 요청을 내 컴퓨터로 정확히 배달해 주는지 정리한다. 1. 문제 상황: "분명 서버를 켰는데, 밖에서 왜 접속이 안 될까?" 내 방 컴퓨터에서 포트 8080 으로 웹 서버를 실행한 뒤, 같은 집 와이파이를 쓰는 노트북이나 스마트폰에서 192.168.0.5:8080 으로 접속하면 페이지가 잘 열린다. 하지만 회사나 카페, 혹은 친구 집 컴퓨터에서 내 주소로 접속을 시도하면 "사이트에 연결할 수 없음(Connection Timed Out)" 오류가 발생한다. 왜 바로 접속할 수 없을까? 이유는 내 컴퓨터가 공유기 뒤편의 '사설 IP(Private IP)'망 에 숨어 있기 때문이다. 사설 IP는 인터넷에서 길을 찾을 수 없다 내 컴퓨터의 IP( 192.168.0.5 )는 전 세계 수많은 가정과 사무실에서도 똑같이 사용 중인 내부 식별 번호다. 공인 인터넷망(백본 라우터)은 사설 IP 목적지 패킷을 받는 즉시 폐기(Drop)하도록 규정되어 있다. 공유기의 공인 IP로 접속해도 공유기는 누구 것인지 모른다 친구가 우리 집 공유기의 공인 IP( 203.0.113.50 ) 를 알아내어 접속 요청을 보냈다고 가정하자. 공유기 아래에는 내 데스크톱( 192.168.0.5 ), 거실 TV( 192.168.0.2 ), 스마트폰( 192.168.0.3 ) 등 여러 기기가 물려 있다. 외부에서 불쑥 먼저 들어온 접속 요청(Inbound)에 대해 공유기는 "이 8080번 데이터가 데스크톱 것인지, 스마트폰 것인지" 판단할 근거가 전혀 없다. 결국 공유기는 보안과 오류 방지를 위해 패킷을 버린다. [외부 접속자(친구)] [공유기 (공인 IP: 203.0.113.50)] [내부 사설망 기기들] | | | --- "접속 요청합니다!" (Port 8080) ---> | | | -- ? (누구에게 줘야 할지 모름) | | -- 데스크톱(192.168.0.5)? | | -- 스마트폰(192.168.0.2)? | | => 패킷 폐기 (접속 실패) 2. 포트 포워딩(Port Forwarding)이란? 포트 포워딩은 공유기에게 "외부에서 공유기의 특정 문(Port)으로 패킷이 들어오면, 내부에 있는 특정 사설 IP의 컴퓨터로 곧장 넘겨줘라" 하고 정적인 이정표(규칙)를 미리 지정해 두는 기술이다. 포트(Port) : 컴퓨터 안에서 동작하는 수많은 프로그램(웹 서버, 게임, 메신저 등) 중 어느 서비스로 갈지 지정하는 '방 번호' 포워딩(Forwarding) : 패킷을 가로채서 다른 곳으로 '전달(전송)' 쉽게 비유하자면, 회사 대표 번호(공인 IP)로 전화를 걸었을 때 교환원에게 "내선 번호 8080번(외부 포트)을 누르면 기획팀 홍길동의 자리(내부 사설 IP:포트)로 즉시 연결해 주세요"라고 시스템을 세팅해 두는 것과 같다. 3. 포트 포워딩의 동작 원리 포트 포워딩 규칙을 등록한 뒤 실제 외부 사용자의 접속 요청이 처리되는 단계별 과정이다. 3.1 공유기 관리자 설정 예시 외부 포트(External Port) : 8080 (외부 접속자가 입력할 포트) 내부 IP(Internal IP) : 192.168.0.5 (내 방 컴퓨터의 사설 IP) 내부 포트(Internal Port) : 8080 (내 방 컴퓨터에서 실제 실행 중인 프로그램의 포트) 프로토콜 : TCP 3.2 패킷 이동 흐름 [외부 접속자] [공유기 (포트 포워딩 규칙 적용)] [내 컴퓨터 (192.168.0.5)] | | | | -- 1. 203.0.113.50:8080 접속 ------> | | | | (규칙 확인: 8080번은 192.168.0.5로!) | | | -- 2. 목적지를 192.168.0.5로 변환 -> | | | (DNAT: 목적지 주소 변경) | | | | | <-- 4. 응답 전송 ------------------- | <-- 3. 응답 데이터 회신 ----------- | 외부 요청 : 친구가 브라우저에 203.0.113.50:8080 을 입력하고 엔터를 누른다. 규칙 대조 및 변환 : 공유기가 요청 패킷을 수신하고 포트 번호( 8080 )를 확인한다. 사전에 정의된 포트 포워딩 규칙을 찾아 목적지 IP를 공유기 공인 IP에서 192.168.0.5:8080 으로 바꿔치기(DNAT: Destination NAT) 한다. 내부 전달 : 변환된 패킷이 로컬 스위치를 거쳐 내 컴퓨터의 웹 서버 프로세스에 정상 도달한다. 응답 회신 : 내 컴퓨터가 웹페이지 데이터를 응답하면, 공유기는 다시 출발지 주소를 자신의 공인 IP로 변경하여 친구에게 전송한다. 4. 포트 포워딩 설정 시 필수 체크리스트 3가지 공유기 설정 페이지(보통 192.168.0.1 등)에서 포트 포워딩을 설정했음에도 여전히 접속되지 않는다면 다음 3가지를 반드시 확인해야 한다. 1) 내 컴퓨터의 사설 IP를 '고정'했는가? 기본적으로 공유기는 DHCP를 통해 기기들에게 사설 IP를 유동적으로 대여해 준다. 컴퓨터를 껐다 켜거나 공유기가 재부팅되면 내 컴퓨터의 IP가 192.168.0.5 에서 192.168.0.8 로 바뀔 수 있다. IP가 바뀌면 포트 포워딩 규칙(구 IP를 가리킴)이 어긋나므로, 공유기의 [DHCP 고정 IP 할당] 메뉴에서 내 컴퓨터의 MAC 주소와 사설 IP를 묶어두어야 한다. 2) 내 컴퓨터의 로컬 방화벽(Windows Defender 등)이 열려 있는가? 공유기가 패킷을 내 컴퓨터 앞까지 무사히 배달해 주어도, Windows 방화벽이 해당 포트의 외부 인바운드 접속을 차단하면 통신이 되지 않는다. Windows Defender 고급 보안 방화벽의 [인바운드 규칙] 에서 내가 사용하는 포트(예: TCP 8080)를 허용해 주어야 한다. 3) 통신사 공유기가 2중으로 물려 있지 않은가? (이중 NAT / Double NAT) 원룸이나 아파트 환경에서는 통신사 모뎀 겸 공유기(1차) 아래에 본인의 공유기(2차)를 추가로 연결해 쓰는 경우가 흔하다. 이 경우 최상단 통신사 공유기에서도 2차 공유기로 포트 포워딩을 해주거나, 2차 공유기를 브리지 모드(AP 모드) 로 전환해야 정상 통신이 가능하다. 5. 핵심 요약 구분 일반적인 웹서핑 (NAT) 포트 포워딩 (Port Forwarding) 통신 시작점 내부 기기 $\rightarrow$ 외부 인터넷 외부 사용자 $\rightarrow$ 내부 기기 변환 방식 출발지 주소를 공인 IP로 변환 (SNAT) 목적지 주소를 특정 내부 사설 IP로 변환 (DNAT) 테이블 성격 요청 시 동적으로 생성되었다가 통신 종료 시 소멸 관리자가 수동으로 입력해 둔 영구적인 정적 규칙 주 사용처 브라우저 서핑, 유튜브 시청, 파일 다운로드 웹 서버 호스팅, SSH 원격 접속, 게임 서버 오픈 사설 IP는 외부 인터넷에서 직접 찾을 수 없으므로, 외부 접속자는 공유기의 공인 IP 로 접근해야 한다. 공유기는 외부에서 먼저 들어온 요청을 어느 내부 컴퓨터로 줘야 할지 모르기 때문에 포트 포워딩 규칙(정적 매핑) 이 필요하다. 포트 포워딩을 안전하게 운용하려면 내부 IP 고정 과 로컬 OS 방화벽 인바운드 허용 이 함께 이루어져야 한다.
velog
오늘의 명언 : A discovery is said to be an accident meeting a prepared mind. _ Albert Szent-Gyorgyi "발견은 준비된 사람이 맞닥뜨린 우연이다." _ 알베르트 센트죄르지 오늘은 새로운 챕터인 전처리 및 시각화 파트에 들어갔다. 사실 가장 기대하고 또 열심히 해야겠다고 생각한 파트이기도 하다.. 최선을 다해서 달려보자~! 데이터 전처리 및 시각화 Day 1 오늘부터 새로운 과정인 데이터 전처리 및 시각화 를 시작했다. 그런데 첫날이라 그런지 본격적으로 Pandas를 이용해서 데이터를 만진다기보다는 데이터 분석은 왜 하는가? 데이터 전처리는 왜 필요한가? 앞으로 무엇을 배우게 되는가? 를 먼저 알아보는 오리엔테이션에 가까운 수업이었다. 그래서 오늘은 강의 내용 자체는 가볍게 정리하고 코드카타에서 새롭게 배운 부분을 조금 더 자세하게 기록해보려고 한다. 1. 데이터 분석은 왜 할까? 처음에는 데이터 분석이라고 하면 단순히 데이터를 계산하고 정리하는 일이라고 생각하기 쉬운데 오늘 강의에서는 데이터의 목적을 설득 이라고 표현했다. 데이터를 분석하는 것 자체가 목적이 아니라 어떤 문제가 있는지 확인하고 데이터를 통해 근거를 만들고 그 결과를 다른 사람에게 전달하고 의사결정을 할 수 있도록 만드는 것 까지가 중요하다는 의미였다. 특히 데이터가 아무리 많아도 전달하려는 내용이 명확하지 않으면 의미가 없기 때문에 시각화 역시 단순히 그래프를 예쁘게 만드는 기술이 아니라 분석 결과를 빠르게 이해시키기 위한 방법이라고 볼 수 있었다. 2. 전처리부터 무작정 시작하면 안 된다 오늘 가장 기억에 남았던 부분이다. 데이터를 받자마자 바로 가공하는 것이 아니라 먼저 목표 무엇을 확인하려고 데이터를 분석하는가? 예상 산출물 최종적으로 어떤 결과를 만들 것인가? As-is 현재 어떤 문제가 있는가? To-be 분석을 통해 무엇을 개선하고 싶은가? 를 생각해야 한다. 예를 들어 품질 데이터가 있다고 하면 단순히 "불량 데이터를 정리해야겠다" 가 아니라 "최근 불량률이 증가한 원인을 확인하기 위해 생산라인별 불량률을 비교할 수 있도록 데이터를 가공한다." 처럼 목적부터 정하는 것이 더 중요하다는 것이다. 품질관리에서도 꽤 중요한 사고방식이라고 느꼈다. 3. 데이터 전처리란? 데이터 전처리는 쉽게 말해서 내가 원하는 데이터를 보기 위해 데이터를 가공하는 모든 과정 이라고 이해했다. 실제 데이터는 생각보다 깔끔하지 않다. 예를 들어 성별 데이터가 남 남성 여 여자 여성 처럼 작성되어 있을 수도 있고 전화번호도 010-1234-5678 01012345678 010-12345678 처럼 형식이 제각각일 수 있다. 이런 데이터를 분석하려면 먼저 같은 의미를 가진 데이터들을 동일한 형식으로 맞춰야 한다. 품질 데이터에서도 비슷할 것 같다. 치수불량 치수 불량 치수NG Dimension NG 같은 데이터가 있다면 그대로 분석하기보다 하나의 기준으로 통일하는 작업이 먼저 필요할 것이다. 앞으로 이런 작업을 Pandas를 이용해서 배우게 된다. 4. Excel과 Pandas Excel도 데이터를 다루는 데 굉장히 좋은 도구지만 Pandas는 Python 코드로 데이터를 처리하기 때문에 반복적인 작업을 자동화하기 좋다는 장점이 있다. 특히 앞으로 배우게 될 작업은 데이터 정렬 데이터 필터링 집계 결측값 처리 데이터 가공 시각화 등이다. 오늘은 깊게 들어가지는 않았고 Pandas에서 사용하는 데이터 구조를 간단히 살펴봤다. DataFrame 표 형태의 데이터 Excel의 표를 생각하면 이해하기 쉽다. 제품 생산량 불량수 0 A 100 3 1 B 120 5 2 C 90 2 Series DataFrame에서 하나의 열을 가져온 형태라고 생각하면 된다. 예를 들어 생산량 100 120 90 하나의 속성을 가진 데이터 집합이다. 아직은 개념만 알아두고 앞으로 실제 Pandas 코드를 사용하면서 익숙해지면 될 것 같다. 5. 오늘의 코드카타 오늘도 Python 코드카타를 진행했다. 오늘은 특히 문자열 처리와 zip() 그리고 반복문을 이용한 누적 계산 문제가 많이 나왔다. 6. 수박수박수박수... 길이 n 에 맞게 수박수박수박... 패턴을 만드는 문제였다. 처음에는 이런 아이디어를 전혀 생각하지 못했다. 가장 간단한 방법은 def solution(n): return ("수박" * n)[:n] 이었다. 예를 들어 "수박" * 3 을 하면 수박수박수박 이 되고 [:3] 으로 앞의 세 글자만 가져오면 수박수 가 된다. 문자열도 숫자처럼 * 를 이용해서 반복할 수 있다는 것을 다시 확인했다. 하지만 지금 나한테 더 이해하기 쉬운 정석 풀이는 아래 방식이었다. def solution(n): answer = "" for i in range(n): if i % 2 == 0: answer += "수" else: answer += "박" return answer 인덱스가 0 1 2 3 4 ... 로 진행되기 때문에 짝수 → 수 홀수 → 박 을 넣는 방식이다. 오늘의 포인트 같은 문제라도 반복문으로 직접 구현하는 방법 문자열의 규칙을 이용해서 간단하게 만드는 방법 둘 다 존재할 수 있다. 아직은 정석적인 반복문 풀이를 먼저 이해하고 짧은 풀이는 새로운 아이디어로 챙겨가는 게 좋은 것 같다. 7. 두 배열의 내적과 zip() 두 리스트의 같은 위치에 있는 숫자를 곱한 뒤 모두 더하는 문제였다. a = [1, 2, 3] b = [4, 5, 6] 이라면 1 × 4 2 × 5 3 × 6 을 모두 더하면 된다. 인덱스를 이용하면 def solution(a, b): answer = 0 for i in range(len(a)): answer += a[i] * b[i] return answer 으로 해결할 수 있다. 그런데 이전에도 한 번 배웠던 zip() 을 사용하면 더 직관적으로 표현할 수 있었다. def solution(a, b): answer = 0 for x, y in zip(a, b): answer += x * y return answer zip(a, b) 는 같은 위치의 값을 묶어준다. a = [1, 2, 3] b = [4, 5, 6] 이면 (1, 4) (2, 5) (3, 6) 처럼 짝을 만들어준다. 그래서 for x, y in zip(a, b): 라고 하면 각각의 값을 바로 사용할 수 있다. 기억하기 zip() = 여러 리스트의 같은 위치 값을 묶어준다. 개인적으로 range(len()) 보다 zip() 방식이 더 직관적으로 느껴졌다. 8. 약수의 개수가 짝수인지 홀수인지 left 부터 right 까지의 숫자 중 약수의 개수가 짝수 → 더하기 약수의 개수가 홀수 → 빼기 를 하는 문제였다. 우선 약수를 직접 세는 방식으로 풀 수 있다. def solution(left, right): answer = 0 for n in range(left, right + 1): count = 0 for i in range(1, n + 1): if n % i == 0: count += 1 if count % 2 == 0: answer += n else: answer -= n return answer 여기서는 반복문이 두 번 사용된다. 첫 번째 반복문은 for n in range(left, right + 1): 각 숫자를 확인하기 위한 것이고 두 번째 반복문은 for i in range(1, n + 1): 해당 숫자의 약수를 찾기 위한 것이다. 그리고 if n % i == 0: 이면 나누어떨어지는 것이므로 i 가 약수라는 뜻이다. 추가로 새로운 규칙도 알게 되었다. 제곱수는 약수의 개수가 홀수이다. 예를 들어 16 은 1 × 16 2 × 8 4 × 4 에서 4 × 4 처럼 같은 숫자가 짝을 이루기 때문에 약수의 개수가 홀수가 된다. 그래서 제곱수인지 확인하는 방식으로도 문제를 풀 수 있다. if int(n ** 0.5) ** 2 == n: 예전에 완전제곱수 문제에서 봤던 코드가 다시 등장했다. 9. 문자열 내림차순 정렬 문자열을 큰 문자부터 작은 문자 순으로 정렬하는 문제였다. 처음부터 한 줄로 작성하기보다 단계별로 풀면 def solution(s): answer = list(s) answer.sort(reverse=True) answer = "".join(answer) return answer 이 된다. 흐름은 문자열 ↓ list() ↓ sort(reverse=True) ↓ join() ↓ 문자열 이다. 예를 들어 s = "Zbcdefg" 를 list(s) 하면 ['Z', 'b', 'c', 'd', 'e', 'f', 'g'] 가 되고 answer.sort(reverse=True) 하면 ['g', 'f', 'e', 'd', 'c', 'b', 'Z'] 가 된다. 마지막으로 "".join(answer) 을 사용하면 gfedcbZ 라는 문자열이 된다. 예전에 숫자를 내림차순으로 정렬했던 문제와 거의 같은 구조였다. 이번에는 처음부터 문자열이기 때문에 마지막에 다시 int() 로 변환할 필요가 없다는 차이가 있다. 10. 놀이기구 이용료 계산 놀이기구를 탈 때마다 가격이 1번째 → price × 1 2번째 → price × 2 3번째 → price × 3 ... 으로 증가하는 문제였다. 정석적으로 풀면 def solution(price, money, count): total = 0 for i in range(1, count + 1): total += price * i if total > money: return total - money else: return 0 으로 해결할 수 있다. 예를 들어 price = 3 money = 20 count = 4 라면 3 × 1 = 3 3 × 2 = 6 3 × 3 = 9 3 × 4 = 12 총 이용료는 3 + 6 + 9 + 12 = 30 이 되고 가진 돈이 20이므로 30 - 20 = 10 이 부족하다. 이 문제는 내가 지금까지 많이 연습했던 answer = 0 for ... answer += ... if ... 형태의 누적 계산 문제라 이전보다 훨씬 익숙하게 느껴졌다. 11. 오늘 새롭게 익힌 것 오늘 코드카타를 하면서 다시 느낀 것은 문제를 보고 바로 짧은 코드를 떠올리지 못해도 괜찮다는 것이다. 일단 내가 알고 있는 for if range % list sort join 같은 문법으로 하나씩 구현할 수 있으면 된다. 그다음 다른 사람의 풀이를 보면서 ("수박" * n)[:n] 처럼 문자열의 특성을 이용하거나 zip(a, b) 처럼 기존 반복문을 더 직관적으로 표현하는 방법을 하나씩 추가하면 된다. 특히 오늘 기억할 것은 zip() → 같은 위치의 값 묶기 "문자열" * n → 문자열 반복 [:n] → 앞에서 n개까지 자르기 sort(reverse=True) → 내림차순 정렬 "".join(list) → 문자 리스트를 문자열로 합치기 n % i == 0 → 약수인지 확인 answer += 값 → 반복하면서 값 누적 이다. 12. Day 1 마무리 오늘 데이터 전처리 및 시각화 수업은 본격적인 실습보다는 앞으로 무엇을 배우게 될지 방향을 잡는 시간에 가까웠다. 그래도 분석 목적 설정 → 필요한 데이터 전처리 → 분석 → 시각화 → 의사결정 이라는 전체적인 흐름을 먼저 이해할 수 있었다. 다음 수업부터 Pandas를 본격적으로 사용하게 되면 오늘 배운 왜 데이터를 전처리하는가? 라는 질문을 계속 생각하면서 코드를 작성해봐야겠다. 코드카타에서는 점점 새로운 문법 자체보다 기존에 배운 문법을 어떻게 조합해서 문제를 해결할지가 중요해지고 있는 것 같다. 특히 오늘은 zip() 을 다시 사용해본 것과 문자열 반복 + 슬라이싱처럼 내가 쉽게 떠올리지 못했던 풀이를 본 것이 가장 기억에 남았다. 이.해.완.료
velog
华纳国际万宝路华纳直营放心娱乐。 东南亚最靠谱的综合平台 提款秒到,大额无忧 ♣️百+乐♥️,牛牛,龙🐉虎🐅,炸金花,推同子,PG🎮AG,麻将胡🀄️,捕鱼,彩票,体育 上百款电子游戏等你来体验你暴富我暴单双赢才是我们的目标 不会注册或注册不了的请联系下方代理专业进行开户即可游戏 出入支持。银行卡,微信,支付宝,USDT,康讯,缅帀 万宝路官方网址: 228983.com PG电子网址: sts2956.com 代理专员: @stswt01 招商代理: @stswt01 代理QQ: 3874447568
Балл: 54.4Уверенность: 49%
Подробнееvelog
📌 이번 주 주제 git rebase 와 git merge 의 차이점을 설명하고, 각각 어떤 상황에서 사용하는 것이 적절한지 설명해주세요. git fetch 와 git pull 의 차이점을 설명하고, 각각을 사용하는 것이 적절한 상황을 설명해주세요. 🔗 git rebase 와 git merge 의 차이점을 설명하고, 각각 어떤 상황에서 사용하는 것이 적절한지 설명해주세요. git rebase 와 git merge 는 서로 다른 브랜치에서 작업한 내용을 하나로 합칠 때 사용하는 명령어이다. 둘 다 브랜치의 변경 사항을 통합한다는 목적은 같지만, 커밋 히스토리를 정리하는 방식에 차이 가 있다. 1. git rebase (리베이스) git rebase 는 브랜치가 갈라진 시점 이후의 내 커밋들을 다른 브랜치의 최신 커밋 위로 다시 배치하는 방식이다. 예를 들어 main 브랜치에 새로운 커밋이 추가된 상황에서 내 feature 브랜치의 커밋을 main 의 최신 커밋 뒤로 옮길 수 있다. 이렇게 하면 브랜치가 갈라졌다가 다시 합쳐지는 형태가 아니라 하나의 선형적인 커밋 히스토리 를 만들 수 있어 히스토리를 확인하기 편하다는 장점이 있다. 🚨 주의할 점 다만 rebase는 기존 커밋을 그대로 이동시키는 것이 아니라 커밋을 새로운 커밋으로 다시 작성하는 방식 이기 때문에 커밋의 해시가 변경된다. 따라서 이미 여러 사람이 함께 사용하고 있는 공용 브랜치에서 rebase를 사용하면 다른 사람의 작업에 영향을 줄 수 있어 주의해야 한다. 또한 rebase 과정에서 충돌이 발생하면 충돌을 해결한 뒤 계속해서 rebase를 진행해야 한다. 정리하면 커밋 히스토리를 깔끔한 선형 구조로 만들고 싶을 때 아직 다른 사람과 공유하지 않은 개인 작업 브랜치를 정리할 때 최신 main 의 변경 사항을 내 브랜치에 반영하면서 히스토리를 깔끔하게 유지하고 싶을 때 git rebase 를 사용할 수 있다. 2. git merge (병합) git merge 는 두 브랜치의 변경 사항을 하나로 합치는 방식이다. 두 브랜치가 서로 다른 커밋을 가지고 있는 상태에서 merge하면 각 브랜치의 히스토리를 그대로 유지하면서 두 브랜치를 연결하는 Merge Commit을 생성 할 수 있다. 예를 들어 main 에서 feature 브랜치를 merge하면 feature 브랜치에서 어떤 작업을 했는지, 어느 시점에 브랜치가 합쳐졌는지 등의 정보를 히스토리에서 확인할 수 있다. 또한 merge는 기존 커밋을 다시 작성하지 않기 때문에 기존 히스토리를 변경하지 않는 비파괴적인 방식 이라는 특징이 있다. 🚨 주의할 점 다만 여러 브랜치를 계속 merge하다 보면 브랜치가 여러 갈래로 나뉘었다가 합쳐지는 형태가 반복되어 커밋 히스토리가 복잡해질 수 있다. 정리하면 기존 커밋 히스토리를 그대로 유지하고 싶을 때 여러 사람이 함께 작업하는 브랜치를 안전하게 통합할 때 브랜치가 언제 생성되고 언제 병합되었는지 등의 작업 흐름을 히스토리에 남기고 싶을 때 git merge 를 사용할 수 있다. 결국 둘 중 하나가 항상 더 좋은 것은 아니고, 히스토리를 어떻게 관리할 것인지에 따라 적절하게 선택하면 된다. 🔗 git fetch 와 git pull 의 차이점을 설명하고, 각각을 사용하는 것이 적절한 상황을 설명해주세요. git fetch 와 git pull 은 둘 다 원격 저장소의 변경 사항을 로컬 저장소로 가져오는 명령어이지만, 가져온 변경 사항을 바로 내 작업 브랜치에 반영하는지에 차이 가 있다. 1. git fetch (가져오기) git fetch 는 원격 저장소의 최신 커밋 정보를 로컬로 가져오되, 현재 작업 중인 코드에는 반영(병합)하지 않고 확인만 하는 명령어이다. 중요한 점은 fetch 를 실행해도 로컬 저장소에만 업데이트될 뿐, 현재 작업 중인 브랜치에는 아무런 영향을 주지 않는다는 것 이다. 예를 들어 다른 사람이 main 브랜치에 새로운 커밋을 올렸다고 해보자. git fetch origin 이렇게 하면 원격 저장소의 최신 정보를 로컬 저장소로 안전하게 가져온다. 따라서 이후에 원격 브랜치와 내 작업 브랜치의 차이를 확인한 뒤, 필요한 경우 직접 merge 또는 rebase를 진행할 수 있다. 즉, 원격 저장소의 변경 사항을 먼저 확인하고 신중하게 반영하고 싶을 때 유용하다. 정리하면 원격 저장소에 어떤 변경 사항이 있는지 먼저 확인하고 싶을 때 현재 작업에 영향을 주지 않고 최신 정보를 안전하게 가져오고 싶을 때 변경 사항을 확인한 후 직접 merge 또는 rebase하고 싶을 때 git fetch 를 사용할 수 있다. 2. git pull (가져와서 반영하기) git pull 은 원격 저장소의 변경 사항을 가져온 후 현재 작업 중인 브랜치에 바로 통합하는 명령어 이다. 일반적으로 다음 두 작업을 한 번에 수행하는 것으로 이해할 수 있다. git fetch git merge 따라서 별도로 fetch를 실행하고 merge할 필요 없이 원격 저장소의 최신 변경 사항을 바로 작업 브랜치에 반영할 수 있다. 예를 들어 작업을 시작하기 전에 원격 저장소의 최신 내용을 내 작업 브랜치에 바로 반영하고 싶다면 다음과 같이 사용할 수 있다. git pull origin main 💡 참고 ( git pull --rebase ) 기본적으로 git pull 은 fetch + merge 방식으로 동작하지만, 팀의 컨벤션이나 히스토리 관리 방식에 따라 git pull --rebase 를 사용하면 fetch + rebase 방식으로 가져와 선형적인 히스토리를 유지할 수도 있다. 다만 내 로컬에서 수정한 내용과 원격에서 변경된 내용이 같은 부분을 수정했다면 충돌(Conflict)이 발생할 수 있다. 정리하면 원격 저장소의 최신 변경 사항을 바로 현재 브랜치에 반영하고 싶을 때 작업을 시작하기 전에 원격 저장소의 최신 상태로 빠르게 업데이트하고 싶을 때 변경 사항을 별도로 확인할 필요가 없는 상황에서 git pull 을 사용할 수 있다. fetch 는 "일단 가져와서 확인" , pull 은 "가져와서 바로 반영" 이라고 기억하면 이해하기 쉽다. 출처 https://kim-oriental.tistory.com/92 https://hianna.tistory.com/1165 https://velog.io/@impmonzz/Git-fetch-vs-pull
velog
Bite problems can affect the way the upper and lower teeth meet, sometimes making chewing, speaking, or maintaining proper tooth alignment more challenging. Fixed Appliances in Dubai & Abu Dhabi may be considered when consistent orthodontic guidance is needed to address certain bite and alignment concerns. At Glamorous Clinic Dubai, treatment planning is personalized according to each patient's teeth, bite, oral health, and orthodontic requirements. Understanding Difficult Bite Problems A healthy bite depends on an appropriate relationship between the upper and lower teeth. When this relationship is altered, different types of malocclusion can develop. Common bite concerns include: Overbite Underbite Crossbite Open bite Uneven tooth contact Crowding associated with bite problems Jaw-positioning concerns Difficulty chewing comfortably The complexity of a bite problem can vary significantly from one person to another. A detailed assessment is therefore important before selecting an orthodontic appliance. How Fixed Appliances May Help Fixed orthodontic appliances remain attached or positioned in the mouth throughout the active treatment period. This allows consistent orthodontic forces or support to be provided according to the treatment plan. Fixed Appliances in Dubai & Abu Dhabi may include braces, palatal expanders, space maintainers, and selected habit-breaking appliances, depending on the patient's needs. For bite-related concerns, the appliance is selected according to factors such as tooth position, jaw relationship, age, dental development, and the type of correction required. Fixed Appliances for Different Bite Problems Overbite An overbite occurs when the upper front teeth overlap the lower teeth more than expected. Depending on the underlying cause, orthodontic treatment may be planned to improve the relationship between the dental arches. Underbite An underbite occurs when the lower teeth extend in front of the upper teeth when the mouth closes. Treatment planning depends on whether the concern is primarily related to tooth positioning, jaw development, or a combination of factors. Crossbite A crossbite can occur when one or more upper teeth sit inside the corresponding lower teeth. Selected fixed appliances may be used to support correction when clinically appropriate. Open Bite An open bite occurs when certain upper and lower teeth do not meet when the mouth is closed. Treatment requires careful assessment of tooth position, bite relationships, and contributing factors. Why Treatment Planning Matters Difficult bite problems are not always caused by a single issue. Tooth positioning, jaw development, oral habits, and other factors can contribute to the overall bite relationship. A personalized assessment helps determine: The type of bite problem Its severity Tooth positioning Jaw relationship Oral health status Appropriate appliance type Expected treatment stages Retention requirements At Glamorous Clinic Dubai, these factors can be considered when developing an individualized orthodontic treatment plan. The Fixed Appliance Treatment Process 1. Initial Assessment Treatment begins with an examination of the teeth and bite. Your dental history and orthodontic concerns may also be reviewed. 2. Diagnostic Evaluation Depending on the case, dental X-rays, photographs, scans, or other diagnostic information may be used to understand tooth and jaw positioning. 3. Treatment Planning The findings are used to develop a personalized plan. The selected appliance depends on the specific bite problem and the desired orthodontic correction. 4. Appliance Placement Once the treatment plan is established, the appropriate fixed appliance is placed according to the planned approach. Patients receive guidance about caring for their teeth and appliance. 5. Monitoring and Adjustments Regular appointments allow treatment progress to be evaluated. Adjustments may be made as the teeth gradually move toward their planned positions. 6. Retention After active orthodontic treatment, retention may be recommended to help maintain the corrected tooth positions. Caring for Your Fixed Appliance Good oral hygiene is especially important during fixed orthodontic treatment. Brackets, wires, and other components can create additional areas where plaque and food particles may accumulate. Patients should: Brush carefully around appliance components Clean between the teeth regularly Follow recommended oral hygiene instructions Avoid foods that may damage the appliance Attend scheduled follow-up visits Report loose or broken components promptly Maintaining these habits can support healthy teeth and gums throughout treatment. Benefits of Addressing Bite Problems When appropriate orthodontic treatment is completed, patients may experience improvements in tooth alignment and bite relationships. Treatment may also support more comfortable chewing and contribute to a more balanced smile. Potential goals can include: Improved bite coordination Better tooth positioning Enhanced chewing function Improved smile appearance Easier oral hygiene Greater stability with appropriate retention Results vary depending on the complexity of the bite problem and the individual's treatment response. Are Fixed Appliances Suitable for Every Bite Problem? Not necessarily. The appropriate treatment depends on the cause, severity, dental development, oral health, and overall treatment objectives. Some bite problems may require different orthodontic approaches or additional treatment considerations. For this reason, patients should undergo a professional assessment before deciding which appliance to use. For individuals considering Fixed Appliances in Dubai & Abu Dhabi , a personalized consultation can help clarify whether fixed treatment is appropriate for their specific bite concern. Frequently Asked Questions Can fixed appliances correct an overbite? Certain fixed orthodontic appliances may be used to address overbite-related concerns, depending on the cause and severity of the problem. Can they help with an underbite? Treatment for an underbite depends on whether the issue involves tooth position, jaw development, or both. A detailed assessment is necessary to determine an appropriate approach. Are fixed appliances useful for crossbite? Selected fixed appliances may be considered for certain crossbite cases. Treatment depends on the patient's dental and skeletal relationship. How long does bite correction take? Treatment duration varies according to the complexity of the bite problem, the selected appliance, and the individual's response to treatment. Is retention necessary after bite correction? Retention may be recommended after active treatment to help maintain the achieved tooth positions. The appropriate retention plan depends on the individual case. Improve Your Bite With Personalized Orthodontic Care Difficult bite problems require careful assessment rather than a one-size-fits-all approach. Fixed Appliances in Dubai & Abu Dhabi may provide consistent orthodontic support for selected alignment and bite concerns. Glamorous Clinic Dubai can evaluate your teeth and bite, explain suitable treatment options, and develop a personalized orthodontic plan designed around your dental needs and long-term smile goals.
velog
Security cameras have become an important part of property security for homes, villas, offices, shops, warehouses, and other commercial spaces. A properly planned CCTV system can help property owners monitor entrances, identify activity around important areas, and review recorded footage when needed. CCTV Installation in Ras Al Khaimah requires more than simply mounting cameras around a property. Camera type, placement, lighting, recording, networking, storage, and remote access all need to work together. The right setup depends on the property's layout, security requirements, and areas that need continuous monitoring. Why CCTV Is Important for Homes and Businesses A CCTV system provides greater visibility across a property by allowing cameras to monitor selected areas throughout the day and night. For homes and villas, cameras are commonly positioned around entrances, gates, driveways, parking areas, gardens, and other access points. Businesses may require broader coverage. Offices, retail stores, restaurants, warehouses, hotels, schools, and commercial buildings can use cameras to monitor entrances, reception areas, corridors, storage spaces, loading areas, and other operational zones. CCTV footage can also be useful when reviewing an incident. Instead of relying only on what someone remembers seeing, property owners or authorized staff can check recorded footage from the relevant time. What to Consider Before CCTV Installation in Ras Al Khaimah Before installing cameras, it is important to understand the property layout and identify areas that require monitoring. Entrances, gates, blind spots, parking areas, and locations containing valuable equipment or inventory may need different levels of coverage. Camera positioning should also be planned carefully. Installing too many cameras does not necessarily provide better coverage if they overlap unnecessarily or leave important areas outside the field of view. Lighting is another consideration. Outdoor cameras may need suitable night-vision or low-light capabilities, while indoor cameras should be selected according to the lighting conditions and viewing distance. The network infrastructure also matters, particularly for IP camera systems. Reliable cabling, network connectivity, and appropriate power arrangements help maintain consistent camera communication and recording. Choosing the Right CCTV Cameras for Your Property Different areas may require different camera designs and features. Dome cameras can be suitable for indoor areas and locations where a discreet appearance is preferred. Bullet cameras are commonly used for outdoor monitoring because their directional design can cover specific areas such as gates and entrances. For larger properties, PTZ cameras can provide the ability to change the viewing direction and zoom into specific areas. IP cameras are also widely used where high-resolution video and network-based monitoring are required. Important features can include high resolution, night vision, wide dynamic range, motion detection, weather resistance, and suitable viewing angles. The right combination depends on where the camera will be installed and what the property owner needs to monitor. For example, a camera covering a large outdoor entrance may require a different lens and night-vision capability than a camera installed inside a small office. Recording, Storage and Remote Monitoring A CCTV system is not only about capturing live video. Recording and storage are equally important when footage needs to be reviewed later. Many systems use an NVR for IP cameras or a DVR for compatible camera systems. Storage capacity depends on factors such as the number of cameras, resolution, recording mode, frame rate, and the required retention period. Continuous recording can provide a complete record but uses more storage. Motion-based recording can reduce storage requirements by recording when activity is detected. Remote monitoring can also allow authorized users to view cameras through a connected device. This can be useful for homeowners managing a property while away or for businesses that need to check different areas without being physically present. Secure configuration and appropriate access controls should be used to protect the system. CCTV Installation for Homes, Villas and Businesses Residential CCTV systems are generally planned around property access and outdoor activity. Gates, entrances, driveways, parking spaces, garden areas, and other vulnerable points may require coverage. For villas with multiple entry points, camera placement should account for the entire perimeter rather than focusing on only the main entrance. For businesses, CCTV requirements can vary considerably depending on the nature of the premises. A retail store may focus on entrances, customer areas, and inventory zones, while a warehouse may require coverage of storage areas, loading points, and large open spaces. Offices can use cameras around entrances, reception areas, corridors, and restricted access areas. Hotels, restaurants, schools, clinics, and other commercial properties may require a combination of indoor and outdoor cameras. CCTV can also work alongside other security and infrastructure systems. Access control, networking, structured cabling, and remote monitoring can be planned together to create a more organized security setup. How to Choose a CCTV Installation Provider in Ras Al Khaimah A professional installation should begin with an assessment of the property rather than selecting cameras based only on specifications. The installer should understand the areas that need coverage, lighting conditions, network requirements, recording needs, and future expansion possibilities. The installation process may include camera placement, cabling, network configuration, NVR or DVR setup, recording configuration, remote viewing, and system testing. Proper positioning is particularly important because even a high-resolution camera may provide limited useful footage if it is installed at an unsuitable angle. TechU Solutions provides CCTV services across the UAE, including Ras Al Khaimah, while its main office is based in Dubai. Customers in Ras Al Khaimah can coordinate with the Dubai team for CCTV site assessment, installation, configuration, networking, maintenance, and related requirements, subject to service availability. Frequently Asked Questions About CCTV Installation in Ras Al Khaimah Q1. How many CCTV cameras does a property need? There is no fixed number. The requirement depends on the property size, layout, entrances, blind spots, and areas that need monitoring. A site assessment can help determine suitable camera locations. Q2. Can CCTV cameras work at night? Yes. Cameras with infrared night vision or suitable low-light capabilities can provide monitoring in dark conditions. The required specification depends on the installation environment. Q3. Can I view CCTV cameras remotely? Many modern IP CCTV systems support remote viewing through authorized mobile or computer access. The system needs suitable networking and secure configuration. Q4. Is CCTV suitable for both homes and businesses? Yes. CCTV can be planned for villas, apartments, offices, retail stores, warehouses, restaurants, hotels, schools, clinics, and other property types. Q5. What is the difference between DVR and NVR? A DVR is generally used with compatible analog camera systems, while an NVR is designed for network-based IP cameras. The appropriate recording system depends on the type of cameras being installed. Final Thoughts A CCTV system should be planned around the actual security requirements of a property rather than simply focusing on the number of cameras. Proper placement, suitable camera features, reliable recording, network connectivity, storage, and secure remote access all contribute to a practical surveillance setup. For homeowners and businesses looking for CCTV Installation in Ras Al Khaimah, understanding these factors before installation can make it easier to build a system that provides useful coverage today and can be expanded when requirements change.
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%