간단한 RSS 목록 애플리케이션
네트워크 리소스를 가져와 표시하는 방법을 보여주는 예시입니다.
이 예제는 RSS 목록 애플리케이션을 통해, 사용자가 요청한 리소스를 가져오고 응답에 포함된 데이터를 표시하는 방법을 보여줍니다. (RDF Site Summary 또는 Really Simple Syndication은 웹 사이트의 업데이트 정보를 전달하기 위한 표준 형식입니다. 자세한 내용은 https://www.rssboard.org/rss-specification을 참조하십시오.) 이 예제의 초점은 네트워킹 사용 방법에 있으므로 그림에 표시된 사용자 인터페이스는 단순하지만, 본격적인 RSS 리더의 경우 당연히 더 정교한 인터페이스가 필요할 것입니다.
또한 이 예제는 데이터를 수신하는 즉시 비동기적으로 구문 분석하는 방법을 보여 주며, 멤버 변수에 상태를 유지함으로써 증분 구문 분석기가 네트워크를 통해 도착하는 데이터 청크를 처리할 수 있도록 합니다. 파싱된 콘텐츠의 구성 요소는 한 데이터 청크에서 시작되었더라도 다음 청크에서야 완료될 수 있으므로, 파서는 호출 간에 상태를 유지해야 합니다.

메인 프로그램은 상당히 간결합니다. 이 프로그램은 단순히 ` QApplication `와 ` RSSListing ` 위젯을 인스턴스화하고, 후자를 표시한 다음 제어권을 전자로 넘겨줍니다. 설명을 위해, 이 프로그램은 위젯에 확인할 리소스의 기본값으로 Qt 블로그의 URL을 지정합니다.
int main(int argc, char **argv)
{
QApplication app(argc, argv);
RSSListing rsslisting(u"https://www.qt.io/blog/rss.xml"_s);
rsslisting.show();
return app.exec();
}RSSListing 클래스
class RSSListing : public QWidget
{
Q_OBJECT
public:
explicit RSSListing(const QString &url = QString(), QWidget *widget = nullptr);
public slots:
void fetch();
void finished(QNetworkReply *reply);
void consumeData();
void error(QNetworkReply::NetworkError);
private:
void parseXml();
void get(const QUrl &url);
// Parser state:
QXmlStreamReader xml;
QString currentTag;
QString linkString;
QString titleString;
// Network state:
QNetworkAccessManager manager;
QNetworkReply *currentReply;
// UI elements:
QLineEdit *lineEdit;
QTreeWidget *treeWidget;
QPushButton *fetchButton;
};이 위젯은 가져올 URL을 지정하고, 사용 가능한 업데이트가 표시되면 업데이트된 항목의 다운로드를 제어할 수 있는 간단한 사용자 인터페이스를 제공합니다. URL 입력은 ` QLineEdit `가 담당하며, 가져온 결과의 표시는 ` QTreeWidget `가 담당합니다.
이 위젯은 RSS(XML의 한 형태)를 비동기적으로 다운로드하고 파싱하며, 데이터가 도착하는 대로 XML 리더로 전달합니다. 이를 통해 매우 방대한 데이터 소스의 읽기를 지원합니다. 데이터가 네트워크에서 XML 리더를 통해 스트리밍되므로, 메모리에 XML의 전체 텍스트를 보관할 필요가 없습니다. 다른 맥락에서는, 유사한 접근 방식을 통해 사용자가 이러한 점진적 로딩을 중단할 수 있게 할 수도 있습니다.
구현
RSSListing::RSSListing(const QString &url, QWidget *parent)
: QWidget(parent), currentReply(0)
{
connect(&manager, &QNetworkAccessManager::finished, this, &RSSListing::finished);
lineEdit = new QLineEdit(this);
lineEdit->setText(url);
connect(lineEdit, &QLineEdit::returnPressed, this, &RSSListing::fetch);
fetchButton = new QPushButton(tr("Fetch"), this);
connect(fetchButton, &QPushButton::clicked, this, &RSSListing::fetch);
treeWidget = new QTreeWidget(this);
connect(treeWidget, &QTreeWidget::itemActivated,
// Open the link in the browser:
this, [](QTreeWidgetItem *item) { QDesktopServices::openUrl(QUrl(item->text(1))); });
treeWidget->setHeaderLabels(QStringList { tr("Title"), tr("Link") });
treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
QHBoxLayout *hboxLayout = new QHBoxLayout;
hboxLayout->addWidget(lineEdit);
hboxLayout->addWidget(fetchButton);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addLayout(hboxLayout);
layout->addWidget(treeWidget);
setWindowTitle(tr("RSS listing example"));
resize(640, 480);
}생성자는 위젯의 다양한 구성 요소를 설정하고, 각 구성 요소의 신호를 이를 처리하기 위해 사용할 슬롯에 연결합니다.
사용자 인터페이스는 라인 에디트, 푸시 버튼, 리스트 뷰 위젯으로 구성됩니다. 라인 에디트는 가져올 URL을 입력하는 데 사용되며, 푸시 버튼은 업데이트 가져오기 과정을 시작합니다. 라인 에디트는 기본적으로 비어 있지만, main() 에서와 같이 생성자를 호출하는 측에서 이를 재정의할 수 있습니다. 어쨌든 사용자는 기본값을 다른 RSS 피드의 URL로 대체할 수 있습니다.
목록 뷰에는 RSS 피드에서 보고된 업데이트된 항목들이 표시됩니다. 이 중 하나를 더블 클릭하면 QDesktopServices::openUrl()를 사용하여 해당 URL이 사용자의 브라우저나 다른 사용자 에이전트로 전송됩니다.
슬롯
void RSSListing::fetch()
{
lineEdit->setReadOnly(true);
fetchButton->setEnabled(false);
treeWidget->clear();
get(QUrl(lineEdit->text()));
}
void RSSListing::consumeData()
{
int statusCode = currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode >= 200&& statusCode < 300)
parseXml();
}
void RSSListing::error(QNetworkReply::NetworkError)
{
qWarning("error retrieving RSS feed");
xml.clear();
currentReply->disconnect(this);
currentReply->deleteLater();
currentReply = nullptr;
}
void RSSListing::finished(QNetworkReply*reply)
{
Q_UNUSED(reply);
lineEdit->setReadOnly(false);
fetchButton->setEnabled(true);
}모든 슬롯은 까다로운 작업을 비공개 메서드에 위임함으로써 단순하게 유지됩니다.
사용자가 “Fetch” 버튼을 클릭하거나 라인 에디트에서 리턴 키를 눌러 URL 입력을 완료하면, ` fetch() ` 슬롯은 “Fetch” 버튼을 비활성화하고 라인 에디트의 추가 편집을 차단합니다. 또한 사용 가능한 업데이트 목록을 지우고, HTTP GET 요청의 시작을 ` get() `에 위임합니다.
데이터가 수신되면, 네트워크 응답이 ` readyRead()` 신호를 트리거하며, ` get() `는 이 신호를 ` consumeData() ` 슬롯에 연결합니다. 이 슬롯은 응답에 성공 상태 코드가 포함되었는지 확인하고, 포함된 경우 ` parseXml() `를 호출하여 데이터를 처리합니다.
네트워크 응답에서 오류가 발생하면, 이 오류는 error() 슬롯으로 전달됩니다. 이 슬롯은 오류를 보고하고, XML 스트림 리더를 지운 다음 응답과의 연결을 끊고 응답을 삭제합니다.
네트워크 응답이 완료되면(성공 여부와 관계없이), finished() 슬롯은 라인 편집 상자와 “Fetch” 버튼을 다시 활성화하여 UI를 복원함으로써, 새로 가져올 URL을 수신할 준비를 합니다.
get() 메서드
void RSSListing::get(const QUrl &url)
{
if (currentReply) {
currentReply->disconnect(this);
currentReply->deleteLater();
}
currentReply = url.isValid() ? manager.get(QNetworkRequest(url)) : nullptr;
if (currentReply) {
connect(currentReply, &QNetworkReply::readyRead, this, &RSSListing::consumeData);
connect(currentReply, &QNetworkReply::errorOccurred, this, &RSSListing::error);
}
xml.setDevice(currentReply); // Equivalent to clear() if currentReply is null.
}비공개 메서드인 ` get() `는 ` fetch() ` 슬롯에서 HTTP GET 요청을 시작하는 데 사용됩니다. 이 메서드는 먼저 XML 스트림 리더를 지우고, 현재 활성화된 응답이 있는 경우 연결을 끊고 해당 응답을 삭제합니다. 전달된 URL이 유효한 경우, 네트워크 액세스 관리자에게 해당 URL에 대한 GET 요청을 수행하도록 요청합니다. 이 메서드는 관련 슬롯을 결과 응답(있는 경우)의 신호에 연결하고, 응답에서 데이터를 읽을 수 있도록 XML 스트림 리더를 설정합니다. 네트워크 응답 객체 또한 QIODevice 이며, 여기서 데이터를 읽을 수 있습니다.
parseXml() 메서드
void RSSListing::parseXml()
{
while (!xml.atEnd()) {
xml.readNext();
if (xml.isStartElement()) {
if (xml.name()== u"item") {
linkString = xml.attributes().value("rss:about").toString();
titleString.clear();
}
currentTag = xml.name().toString();
} else if (xml.isEndElement()) {
if (xml.name()== u"item") {
QTreeWidgetItem*item = new QTreeWidgetItem;
item->setText(0, titleString);
item->setText(1, linkString);
treeWidget->addTopLevelItem(item);
}
} else if (xml.isCharacters()&& !xml.isWhitespace()) {
if (currentTag== "title")
titleString+= xml.text();
else if (currentTag== "link")
linkString+= xml.text();
}
}
if (xml.error()&& xml.error() != QXmlStreamReader::PrematureEndOfDocumentError)
qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString();
}데이터가 수신되어 XML 스트림 리더가 이를 사용할 수 있게 되면, ` parseXml() `는 XML 스트림에서 데이터를 읽으며 ` item ` 요소를 확인하고, 그 안에서 ` title ` 및 ` link ` 요소를 찾습니다. item 의 rss:about 속성을 트리 뷰의 Link 열에 URL로 사용하며, 해당 속성이 없으면 link 요소의 내용을 사용합니다. 또한 title 요소의 내용을 트리 뷰의 Title 열에 사용합니다. 각 item 요소가 닫힐 때마다, 해당 요소의 세부 정보는 트리 위젯의 새 행으로 변환되며, 추출된 제목과 URL은 각각 ‘제목’ 및 ‘링크’ 열에 표시됩니다.
구문 분석 상태를 추적하는 변수인 linkString, titleString 및 currentTag 는 RSSListing 클래스의 멤버 변수입니다. 비록 이 메서드에서만 액세스되지만, 새로운 데이터가 도착함에 따라 이 메서드가 반복적으로 호출될 수 있고, 수신된 한 청크의 데이터가 다음 청크가 도착할 때까지 완료되지 않는 요소를 시작할 수도 있기 때문입니다. 이를 통해 파서는 모든 데이터가 도착할 때까지 기다릴 필요 없이, 데이터가 도착하는 대로 비동기적으로 작동할 수 있습니다.
QNetworkReply 및 QXmlStreamReader도 참조하십시오 .
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.